mirror of
https://github.com/firefly-iii/firefly-iii.git
synced 2025-02-25 18:45:27 -06:00
First version of routine #732
This commit is contained in:
parent
1878b5287b
commit
5d10a19bfa
@ -42,6 +42,7 @@ SHOW_INCOMPLETE_TRANSLATIONS=false
|
|||||||
CACHE_PREFIX=firefly
|
CACHE_PREFIX=firefly
|
||||||
|
|
||||||
EXCHANGE_RATE_SERVICE=fixerio
|
EXCHANGE_RATE_SERVICE=fixerio
|
||||||
|
PASSWORD_SERVICE=false
|
||||||
|
|
||||||
GOOGLE_MAPS_API_KEY=
|
GOOGLE_MAPS_API_KEY=
|
||||||
ANALYTICS_ID=
|
ANALYTICS_ID=
|
||||||
|
@ -17,6 +17,7 @@ use Config;
|
|||||||
use FireflyConfig;
|
use FireflyConfig;
|
||||||
use FireflyIII\Events\RegisteredUser;
|
use FireflyIII\Events\RegisteredUser;
|
||||||
use FireflyIII\Http\Controllers\Controller;
|
use FireflyIII\Http\Controllers\Controller;
|
||||||
|
use FireflyIII\Http\Requests\UserRegistrationRequest;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Illuminate\Foundation\Auth\RegistersUsers;
|
use Illuminate\Foundation\Auth\RegistersUsers;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
@ -56,7 +57,7 @@ class RegisterController extends Controller
|
|||||||
*
|
*
|
||||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Http\RedirectResponse|\Illuminate\Routing\Redirector|\Illuminate\View\View
|
||||||
*/
|
*/
|
||||||
public function register(Request $request)
|
public function register(UserRegistrationRequest $request)
|
||||||
{
|
{
|
||||||
// is allowed to?
|
// is allowed to?
|
||||||
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
|
$singleUserMode = FireflyConfig::get('single_user_mode', Config::get('firefly.configuration.single_user_mode'))->data;
|
||||||
|
@ -37,7 +37,7 @@ class ProfileFormRequest extends Request
|
|||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'current_password' => 'required',
|
'current_password' => 'required',
|
||||||
'new_password' => 'required|confirmed',
|
'new_password' => 'required|confirmed|secure_password',
|
||||||
'new_password_confirmation' => 'required',
|
'new_password_confirmation' => 'required',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
53
app/Http/Requests/UserRegistrationRequest.php
Normal file
53
app/Http/Requests/UserRegistrationRequest.php
Normal file
@ -0,0 +1,53 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* UserRegistrationRequest.php
|
||||||
|
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||||
|
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Http\Requests;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class UserRegistrationRequest
|
||||||
|
*
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Http\Requests
|
||||||
|
*/
|
||||||
|
class UserRegistrationRequest extends Request
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
// Only everybody
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function getUserData(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'email' => $this->string('email'),
|
||||||
|
'password' => $this->string('password'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'email' => 'email|required',
|
||||||
|
'password' => 'confirmed|secure_password',
|
||||||
|
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
@ -39,6 +39,8 @@ use FireflyIII\Support\Amount;
|
|||||||
use FireflyIII\Support\ExpandedForm;
|
use FireflyIII\Support\ExpandedForm;
|
||||||
use FireflyIII\Support\FireflyConfig;
|
use FireflyIII\Support\FireflyConfig;
|
||||||
use FireflyIII\Support\Navigation;
|
use FireflyIII\Support\Navigation;
|
||||||
|
use FireflyIII\Support\Password\PwndVerifier;
|
||||||
|
use FireflyIII\Support\Password\Verifier;
|
||||||
use FireflyIII\Support\Preferences;
|
use FireflyIII\Support\Preferences;
|
||||||
use FireflyIII\Support\Steam;
|
use FireflyIII\Support\Steam;
|
||||||
use FireflyIII\Support\Twig\AmountFormat;
|
use FireflyIII\Support\Twig\AmountFormat;
|
||||||
@ -147,6 +149,9 @@ class FireflyServiceProvider extends ServiceProvider
|
|||||||
$this->app->bind(FiscalHelperInterface::class, FiscalHelper::class);
|
$this->app->bind(FiscalHelperInterface::class, FiscalHelper::class);
|
||||||
$this->app->bind(BalanceReportHelperInterface::class, BalanceReportHelper::class);
|
$this->app->bind(BalanceReportHelperInterface::class, BalanceReportHelper::class);
|
||||||
$this->app->bind(BudgetReportHelperInterface::class, BudgetReportHelper::class);
|
$this->app->bind(BudgetReportHelperInterface::class, BudgetReportHelper::class);
|
||||||
|
|
||||||
|
// password verifier thing
|
||||||
|
$this->app->bind(Verifier::class, PwndVerifier::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
51
app/Support/Password/PwndVerifier.php
Normal file
51
app/Support/Password/PwndVerifier.php
Normal file
@ -0,0 +1,51 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* PwndVerifier.php
|
||||||
|
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||||
|
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Support\Password;
|
||||||
|
|
||||||
|
use Log;
|
||||||
|
use Requests;
|
||||||
|
use Requests_Exception;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Class PwndVerifier
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Support\Password
|
||||||
|
*/
|
||||||
|
class PwndVerifier implements Verifier
|
||||||
|
{
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Verify the given password against (some) service.
|
||||||
|
*
|
||||||
|
* @param string $password
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function validPassword(string $password): bool
|
||||||
|
{
|
||||||
|
$hash = sha1($password);
|
||||||
|
$uri = sprintf('https://haveibeenpwned.com/api/v2/pwnedpassword/%s', $hash);
|
||||||
|
$opt = ['useragent' => 'Firefly III v' . config('firefly.version'), 'timeout' => 2];
|
||||||
|
|
||||||
|
try {
|
||||||
|
$result = Requests::get($uri, ['originalPasswordIsAHash' => 'true'], $opt);
|
||||||
|
} catch (Requests_Exception $e) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
Log::debug(sprintf('Status code returned is %d', $result->status_code));
|
||||||
|
if ($result->status_code === 404) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
29
app/Support/Password/Verifier.php
Normal file
29
app/Support/Password/Verifier.php
Normal file
@ -0,0 +1,29 @@
|
|||||||
|
<?php
|
||||||
|
/**
|
||||||
|
* Verifier.php
|
||||||
|
* Copyright (c) 2017 thegrumpydictator@gmail.com
|
||||||
|
* This software may be modified and distributed under the terms of the Creative Commons Attribution-ShareAlike 4.0 International License.
|
||||||
|
*
|
||||||
|
* See the LICENSE file for details.
|
||||||
|
*/
|
||||||
|
|
||||||
|
declare(strict_types=1);
|
||||||
|
|
||||||
|
namespace FireflyIII\Support\Password;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Interface Verifier
|
||||||
|
*
|
||||||
|
* @package FireflyIII\Support\Password
|
||||||
|
*/
|
||||||
|
interface Verifier
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Verify the given password against (some) service.
|
||||||
|
* @param string $password
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function validPassword(string $password): bool;
|
||||||
|
|
||||||
|
}
|
@ -24,11 +24,15 @@ use FireflyIII\Models\PiggyBank;
|
|||||||
use FireflyIII\Models\TransactionType;
|
use FireflyIII\Models\TransactionType;
|
||||||
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
use FireflyIII\Repositories\Budget\BudgetRepositoryInterface;
|
||||||
use FireflyIII\Rules\Triggers\TriggerInterface;
|
use FireflyIII\Rules\Triggers\TriggerInterface;
|
||||||
|
use FireflyIII\Support\Password\Verifier;
|
||||||
use FireflyIII\User;
|
use FireflyIII\User;
|
||||||
use Google2FA;
|
use Google2FA;
|
||||||
use Illuminate\Contracts\Encryption\DecryptException;
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Illuminate\Contracts\Translation\Translator;
|
use Illuminate\Contracts\Translation\Translator;
|
||||||
use Illuminate\Validation\Validator;
|
use Illuminate\Validation\Validator;
|
||||||
|
use Log;
|
||||||
|
use Requests;
|
||||||
|
use Requests_Exception;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Class FireflyValidator
|
* Class FireflyValidator
|
||||||
@ -274,6 +278,24 @@ class FireflyValidator extends Validator
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param $attribute
|
||||||
|
* @param $value
|
||||||
|
* @param $parameters
|
||||||
|
*
|
||||||
|
* @return bool
|
||||||
|
*/
|
||||||
|
public function validateSecurePassword($attribute, $value, $parameters): bool
|
||||||
|
{
|
||||||
|
$enabled = env('PASSWORD_SERVICE');
|
||||||
|
if (!$enabled) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
/** @var Verifier $service */
|
||||||
|
$service = app(Verifier::class);
|
||||||
|
return $service->validPassword($value);
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
* @SuppressWarnings(PHPMD.UnusedFormalParameter)
|
||||||
* @param $attribute
|
* @param $attribute
|
||||||
|
@ -88,4 +88,5 @@ return [
|
|||||||
'in_array' => 'The :attribute field does not exist in :other.',
|
'in_array' => 'The :attribute field does not exist in :other.',
|
||||||
'present' => 'The :attribute field must be present.',
|
'present' => 'The :attribute field must be present.',
|
||||||
'amount_zero' => 'The total amount cannot be zero',
|
'amount_zero' => 'The total amount cannot be zero',
|
||||||
|
'secure_password' => 'This is not a secure password. Please try again. For more information, visit https://goo.gl/NCh2tN',
|
||||||
];
|
];
|
||||||
|
@ -1,38 +0,0 @@
|
|||||||
{% extends "./layout/default" %}
|
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
|
||||||
{{ Breadcrumbs.renderIfExists }}
|
|
||||||
{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-12 col-md-12 col-sm-12">
|
|
||||||
<div class="box box-default">
|
|
||||||
<div class="box-header with-border">
|
|
||||||
<h3 class="box-title">{{ 'import_finished'|_ }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="box-body">
|
|
||||||
<p>
|
|
||||||
{{ 'import_finished_intro'|_ }}
|
|
||||||
</p>
|
|
||||||
{% if tagId > 0 %}
|
|
||||||
<p>
|
|
||||||
{{ trans('firefly.import_finished_text_with_link', {tag: tagId})|raw }}
|
|
||||||
</p>
|
|
||||||
{% else %}
|
|
||||||
<p>
|
|
||||||
{{ 'import_finished_text_without_link'|_ }}
|
|
||||||
</p>
|
|
||||||
{% endif %}
|
|
||||||
|
|
||||||
<p>
|
|
||||||
{{ 'import_share_configuration'|_ }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{% endblock %}
|
|
||||||
{% block scripts %}
|
|
||||||
{% endblock %}
|
|
||||||
{% block styles %}
|
|
||||||
{% endblock %}
|
|
@ -1,157 +0,0 @@
|
|||||||
{% extends "./layout/default" %}
|
|
||||||
|
|
||||||
{% block breadcrumbs %}
|
|
||||||
{{ Breadcrumbs.renderIfExists }}
|
|
||||||
{% endblock %}
|
|
||||||
{% block content %}
|
|
||||||
|
|
||||||
{# Initial display. Will refresh (and disappear almost immediately. #}
|
|
||||||
|
|
||||||
<div class="row status_initial statusbox">
|
|
||||||
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
|
|
||||||
<div class="box box-primary">
|
|
||||||
<div class="box-header with-border">
|
|
||||||
<h3 class="box-title">{{ 'import_status_wait_title'|_ }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="box-body">
|
|
||||||
<p>
|
|
||||||
{{ 'import_status_wait_text'|_ }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# Fatal error display. Will be shown (duh) when something goes horribly wrong. #}
|
|
||||||
<div class="row fatal_error" style="display:none;">
|
|
||||||
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
|
|
||||||
<div class="box box-danger">
|
|
||||||
<div class="box-header with-border">
|
|
||||||
<h3 class="box-title">{{ 'import_status_fatal_title'|_ }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="box-body">
|
|
||||||
<p>
|
|
||||||
{{ 'import_status_fatal_text'|_ }}
|
|
||||||
</p>
|
|
||||||
<p class="text-danger fatal_error_txt">
|
|
||||||
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
{{ 'import_status_fatal_more'|_ }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# Box for when the job is ready to start #}
|
|
||||||
<div class="row status_configured statusbox" style="display:none;">
|
|
||||||
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
|
|
||||||
<div class="box box-primary">
|
|
||||||
<div class="box-header with-border">
|
|
||||||
<h3 class="box-title">{{ 'import_status_ready_title'|_ }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="box-body">
|
|
||||||
<p>
|
|
||||||
{{ 'import_status_ready_text'|_ }}
|
|
||||||
</p>
|
|
||||||
<p>
|
|
||||||
<code>php artisan firefly:start-import {{ job.key }}</code>
|
|
||||||
</p>
|
|
||||||
<div class="row">
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<a href="{{ route('import.download', [job.key]) }}" class="btn btn-default"><i
|
|
||||||
class="fa fa-fw fa-download"></i> {{ 'import_status_ready_config'|_ }}</a>
|
|
||||||
</div>
|
|
||||||
<div class="col-lg-4">
|
|
||||||
<button class="btn btn-success start-job"><i class="fa fa-fw fa-gears"></i> {{ 'import_status_ready_start'|_ }}</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p>
|
|
||||||
|
|
||||||
</p>
|
|
||||||
<p class="text-info">
|
|
||||||
{{ 'import_status_ready_share'|_ }}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# Box for when the job is running! #}
|
|
||||||
<div class="row status_running statusbox" style="display: none;">
|
|
||||||
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
|
|
||||||
<div class="box box-primary">
|
|
||||||
<div class="box-header with-border">
|
|
||||||
<h3 class="box-title" id="import-status-title">{{ 'import_status_running_title'|_ }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="box-body">
|
|
||||||
<div id="import-status-holder">
|
|
||||||
<div class="progress" id="import-status-holder">
|
|
||||||
<div id="import-status-bar" class="progress-bar progress-bar-info active progress-bar-striped" role="progressbar"
|
|
||||||
aria-valuenow="100" aria-valuemin="0"
|
|
||||||
aria-valuemax="100" style="width: 100%;min-width:40px;">
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<p id="import-status-txt">{{ 'import_status_running_placeholder'|_ }}</p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# displays the finished status of the import. #}
|
|
||||||
<div class="row status_finished statusbox" style="display:none;">
|
|
||||||
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
|
|
||||||
<div class="box box-default">
|
|
||||||
<div class="box-header with-border">
|
|
||||||
<h3 class="box-title">{{ 'import_status_finished_title'|_ }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="box-body">
|
|
||||||
<p id="import-status-intro">
|
|
||||||
{{ 'import_status_finished_text'|_ }}
|
|
||||||
</p>
|
|
||||||
<p id="import-status-more-info"></p>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{# box to show error information. #}
|
|
||||||
<div class="row info_errors" style="display:none;">
|
|
||||||
<div class="col-lg-8 col-lg-offset-2 col-md-12 col-sm-12">
|
|
||||||
<div class="box box-danger">
|
|
||||||
<div class="box-header with-border">
|
|
||||||
<h3 class="box-title">{{ 'import_status_errors_title'|_ }}</h3>
|
|
||||||
</div>
|
|
||||||
<div class="box-body">
|
|
||||||
<p id="import-status-error-intro">
|
|
||||||
</p>
|
|
||||||
<div id="import-status-error-list"></div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
|
|
||||||
{% endblock %}
|
|
||||||
{% block scripts %}
|
|
||||||
<script type="text/javascript">
|
|
||||||
|
|
||||||
// some useful translations.
|
|
||||||
var langImportSingleError = '{{ 'import_status_errors_single'|_|escape }}';
|
|
||||||
var langImportMultiError = '{{ 'import_status_errors_multi'|_|escape }}';
|
|
||||||
|
|
||||||
//var langImportFatalError = '{{ 'import_error_fatal'|_|escape }}';
|
|
||||||
//var langImportTimeOutError = '{{ 'import_error_timeout'|_|escape }}';
|
|
||||||
//var langImportFinished = '{{ 'import_finished_all'|_|escape }}';
|
|
||||||
|
|
||||||
|
|
||||||
var jobKey = '{{ job.key }}';
|
|
||||||
var jobImportUrl = '{{ route('import.json', [job.key]) }}';
|
|
||||||
var jobStartUrl = '{{ route('import.start', [job.key]) }}';
|
|
||||||
var token = '{{ csrf_token() }}';
|
|
||||||
</script>
|
|
||||||
<script type="text/javascript" src="js/ff/import/status.js"></script>
|
|
||||||
{% endblock %}
|
|
||||||
{% block styles %}
|
|
||||||
{% endblock %}
|
|
Loading…
Reference in New Issue
Block a user