New views for password reset, login and other user forms.

This commit is contained in:
James Cole 2018-11-25 11:31:02 +01:00
parent 99cc7a9a60
commit 4420df6e5d
No known key found for this signature in database
GPG Key ID: C16961E655E74B5E
41 changed files with 792 additions and 76 deletions

View File

@ -109,10 +109,11 @@ class ForgotPasswordController extends Controller
$singleUserMode = FireflyConfig::get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
$userCount = User::count();
$allowRegistration = true;
$pageTitle = (string)trans('firefly.forgot_pw_page_title');
if (true === $singleUserMode && $userCount > 0) {
$allowRegistration = false;
}
return view('auth.passwords.email')->with(compact('allowRegistration'));
return view('auth.passwords.email')->with(compact('allowRegistration', 'pageTitle'));
}
}

View File

@ -72,7 +72,7 @@ class RegisterController extends Controller
{
// is allowed to?
$allowRegistration = true;
$loginProvider = envNonEmpty('LOGIN_PROVIDER','eloquent');
$loginProvider = envNonEmpty('LOGIN_PROVIDER', 'eloquent');
$singleUserMode = FireflyConfig::get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
$userCount = User::count();
if (true === $singleUserMode && $userCount > 0 && 'eloquent' === $loginProvider) {
@ -113,10 +113,11 @@ class RegisterController extends Controller
public function showRegistrationForm(Request $request)
{
$allowRegistration = true;
$loginProvider = envNonEmpty('LOGIN_PROVIDER','eloquent');
$loginProvider = envNonEmpty('LOGIN_PROVIDER', 'eloquent');
$isDemoSite = FireflyConfig::get('is_demo_site', config('firefly.configuration.is_demo_site'))->data;
$singleUserMode = FireflyConfig::get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
$userCount = User::count();
$pageTitle = (string)trans('firefly.register_page_title');
if (true === $isDemoSite) {
$allowRegistration = false;
@ -138,7 +139,7 @@ class RegisterController extends Controller
$email = $request->old('email');
return view('auth.register', compact('isDemoSite', 'email'));
return view('auth.register', compact('isDemoSite', 'email', 'pageTitle'));
}
}

View File

@ -78,18 +78,18 @@ class ResetPasswordController extends Controller
return view('error', compact('message'));
}
// is allowed to register?
$singleUserMode = FireflyConfig::get('single_user_mode', config('firefly.configuration.single_user_mode'))->data;
$userCount = User::count();
$allowRegistration = true;
$pageTitle = (string)trans('firefly.reset_pw_page_title');
if (true === $singleUserMode && $userCount > 0) {
$allowRegistration = false;
}
/** @noinspection PhpUndefinedFieldInspection */
return view('auth.passwords.reset')->with(
['token' => $token, 'email' => $request->email, 'allowRegistration' => $allowRegistration]
['token' => $token, 'email' => $request->email, 'allowRegistration' => $allowRegistration,'pageTitle' => $pageTitle]
);
}
@ -129,5 +129,17 @@ class ResetPasswordController extends Controller
: $this->sendResetFailedResponse($request, $response);
}
/**
* Get the password reset validation rules.
*
* @return array
*/
protected function rules()
{
return [
'token' => 'required',
'email' => 'required|email',
'password' => 'required|confirmed|min:6|secure_password',
];
}
}

View File

@ -58,7 +58,7 @@ class PwndVerifierV2 implements Verifier
$uri = sprintf('https://api.pwnedpasswords.com/range/%s', $prefix);
$opt = [
'headers' => ['User-Agent' => 'Firefly III v' . config('firefly.version')],
'timeout' => 2];
'timeout' => 5];
Log::debug(sprintf('hash prefix is %s', $prefix));
Log::debug(sprintf('rest is %s', $rest));

View File

@ -394,7 +394,7 @@ trait RequestInformation
$data,
[
'email' => 'required|string|email|max:255|unique:users',
'password' => 'required|string|secure_password|confirmed',
'password' => 'required|string|min:6|secure_password|confirmed',
]
);
}

View File

@ -177,6 +177,10 @@ return [
'reset_button' => 'Reset',
'want_to_login' => 'I want to login',
'login_page_title' => 'Login to Firefly III',
'register_page_title' => 'Register at Firefly III',
'forgot_pw_page_title' => 'Forgot your password for Firefly III',
'reset_pw_page_title' => 'Reset your password for Firefly III',
'cannot_reset_demo_user' => 'You cannot reset the password of the demo user.',
'button_register' => 'Register',
'authorization' => 'Authorization',
'active_bills_only' => 'active bills only',
@ -535,14 +539,13 @@ return [
'invalid_password' => 'Invalid password!',
'what_is_pw_security' => 'What is "verify password security"?',
'secure_pw_title' => 'How to choose a secure password',
'secure_pw_history' => 'In August 2017 well known security researcher Troy Hunt released a list of 306 million stolen passwords. These passwords were stolen during breakins at companies like LinkedIn, Adobe and NeoPets (and many more).',
'secure_pw_check_box' => 'By checking the box, Firefly III will send the first five characters of the SHA1 hash of your password to <a href="https://www.troyhunt.com/introducing-306-million-freely-downloadable-pwned-passwords/">the website of Troy Hunt</a> to see if it is on the list. This will stop you from using unsafe passwords as is recommended in the latest <a href="https://pages.nist.gov/800-63-3/sp800-63b.html">NIST Special Publication</a> on this subject.',
'secure_pw_sha1' => 'But I thought SHA1 was broken?',
'secure_pw_hash_speed' => 'Yes, but not in this context. As you can read on <a href="https://shattered.io/">the website detailing how they broke SHA1</a>, it is now slightly easier to find a "collision": another digest that results in the same SHA1-hash. It now only takes 10,000 years using a single-GPU machine.',
'secure_pw_hash_security' => 'This digest would not be equal to your password, nor would it be useful on (a site like) Firefly III. This application does not use SHA1 for password verification. So it is safe to check this box. Your password is hashed and only the first five characters of this digest are sent over HTTPS.',
'secure_pw_history' => 'Not a week goes by that you read in the news about a site losing the passwords of its users. Hackers and thieves use these passwords to try to steal your private information. This information is valuable.',
'secure_pw_ff' => 'Do you use the same password all over the internet? If one site loses your password, hackers have access to all your data. Firefly III relies on you to choose a strong and unique password to protect your financial records.',
'secure_pw_check_box' => 'To help you do that Firefly III can check if the password you want to use has been stolen in the past. If this is the case, Firefly III advises you NOT to use that password.',
'secure_pw_working_title' => 'How does it work?',
'secure_pw_working' => 'By checking the box, Firefly III will send the first five characters of the SHA1 hash of your password to <a href="https://www.troyhunt.com/introducing-306-million-freely-downloadable-pwned-passwords/">the website of Troy Hunt</a> to see if it is on the list. This will stop you from using unsafe passwords as is recommended in the latest <a href="https://pages.nist.gov/800-63-3/sp800-63b.html">NIST Special Publication</a> on this subject.',
'secure_pw_should' => 'Should I check the box?',
'secure_pw_long_password' => 'If you just generated a long, single-use password for Firefly III using some kind of password generator: <strong>no</strong>.',
'secure_pw_short' => 'If you just entered the password you always use: <em>Please yes</em>.',
'secure_pw_long_password' => 'Yes. Always verify your password is safe.',
'command_line_token' => 'Command line token',
'explain_command_line_token' => 'You need this token to perform command line options, such as importing or exporting data. Without it, such sensitive commands will not work. Do not share your command line token. Nobody will ask you for this token, not even me. If you fear you lost this, or when you\'re paranoid, regenerate this token using the button.',
'regenerate_command_line_token' => 'Regenerate command line token',

View File

@ -123,7 +123,7 @@ return [
'present' => 'The :attribute field must be present.',
'amount_zero' => 'The total amount cannot be zero.',
'unique_piggy_bank_for_user' => 'The name of the piggy bank must be unique.',
'secure_password' => 'This is not a secure password. Please try again. For more information, visit http://bit.ly/FF3-password-security.',
'secure_password' => 'This is not a secure password. Please try again. For more information, visit https://bit.ly/FF3-password-security',
'valid_recurrence_rep_type' => 'Invalid repetition type for recurring transactions.',
'valid_recurrence_rep_moment' => 'Invalid repetition moment for this type of repetition.',
'invalid_account_info' => 'Invalid account information.',

View File

@ -11,23 +11,21 @@
<p>
{{ 'secure_pw_history'|_ }}
</p>
<p>
{{ 'secure_pw_ff'|_ }}
</p>
<p>
{{ 'secure_pw_check_box'|_ }}
</p>
<h4>{{ 'secure_pw_sha1'|_ }}</h4>
<h4>{{ 'secure_pw_working_title'|_ }}</h4>
<p>
{{ 'secure_pw_hash_speed'|_ }}
</p>
<p>
{{ 'secure_pw_hash_security'|_ }}
{{ 'secure_pw_working'|_ }}
</p>
<h4>{{ 'secure_pw_should'|_ }}</h4>
<p>
{{ 'secure_pw_long_password'|_ }}
</p>
<p>
{{ 'secure_pw_short'|_ }}
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-default" data-dismiss="modal">{{ 'close'|_ }}</button>

View File

@ -1,39 +1,28 @@
<!doctype html>
<html lang="en" dir="ltr">
<head>
<base href="{{ route('index') }}/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta http-equiv="Content-Language" content="en"/>
{# favicons #}
{% include('partials.favicons') %}
<title>TODO replace meLogin</title>
<link rel="stylesheet" href="v2/lib/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="v2/assets/css/gf-source.css">
<script src="v2/assets/js/require.min.js"></script>
<script>
requirejs.config({
baseUrl: '.'
});
</script>
<!-- Dashboard Core -->
<link href="v2/assets/css/dashboard.css" rel="stylesheet"/>
<script src="v2/assets/js/dashboard.js"></script>
<!-- Input Mask Plugin -->
<script src="v2/assets/plugins/input-mask/plugin.js"></script>
</head>
<body class="">
<div class="page">
<div class="page-single">
{% extends "./layout/auth" %}
{% block content %}
<div class="page-single">
<div class="container">
<div class="row">
<div class="col col-login mx-auto">
<div class="text-center mb-6">
<img src="v2/assets/images/firefly-iii-48.png" class="h-6" alt="Firefly III">
<img src="v2/assets/images/firefly-iii-48.png" class="h-6" alt="Firefly III v{{ FF_VERSION }}" title="Firefly III v{{ FF_VERSION }}">
</div>
{# ERROR LOGIN STUFF #}
{% if errors.all|length > 0 %}
<div class="alert alert-danger" role="alert">
{% if errors.all|length == 1 %}
<strong>{{ 'flash_error'|_ }}</strong> {{ errors.first() }}
{% else %}
<strong>{{ 'flash_error'|_ }}</strong>
<ul>
{% for message in errors.all %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endif %}
<form class="card" action="{{ route('login') }}" method="post">
<input type="hidden" name="_token" value="{{ csrf_token() }}"/>
<div class="card-body p-6">
@ -52,10 +41,15 @@
<div class="form-group">
{% if env('LOGIN_PROVIDER', 'eloquent') == 'eloquent' %}
<label class="form-label">{{ trans('form.email') }}</label>
<input type="email" class="form-control" id="email" autocomplete="email" aria-describedby="emailHelp" placeholder="{{ trans('form.email') }}">
<input type="email" class="{% if errors.has('email') %}is-invalid{% endif %} form-control" name="email" id="email" value="{{ old('email') }}" autocomplete="email" aria-describedby="emailHelp" placeholder="{{ trans('form.email') }}" required>
{% if errors.has('email') %}
<div class="invalid-feedback">
{{ errors.get('email')[0] }}
</div>
{% endif %}
{% else %}
<label class="form-label">{{ trans('form.login_name') }}</label>
<input type="email" class="form-control" id="email" autocomplete="username" aria-describedby="emailHelp" placeholder="{{ trans('form.login_name') }}">
<input type="email" class="{% if errors.has('email') %}is-invalid{% endif %} form-control" name="email" id="email" autocomplete="username" aria-describedby="emailHelp" placeholder="{{ trans('form.login_name') }}" required>
{% endif %}
</div>
<div class="form-group">
@ -65,7 +59,12 @@
<a href="{{ route('password.reset.request') }}" class="float-right small">{{ 'forgot_my_password'|_ }}</a>
{% endif %}
</label>
<input type="password" class="form-control" autocomplete="password" id="password" placeholder="Password">
<input type="password" name="password" class="{% if errors.has('password') %}is-invalid{% endif %} form-control" autocomplete="password" id="password" placeholder="Password">
{% if errors.has('password') %}
<div class="invalid-feedback">
{{ errors.get('password')[0] }}
</div>
{% endif %}
</div>
<div class="form-group">
<label class="custom-control custom-checkbox">
@ -80,13 +79,11 @@
</form>
{% if allowRegistration %}
<div class="text-center text-muted">
Don't have account yet? <a href="./register.html">Sign up</a>
<a href="{{ route('register') }}">{{ 'register_new_account'|_ }}</a>
</div>
{% endif %}
</div>
</div>
</div>
</div>
</div>
</body>
</html>
{% endblock %}

View File

@ -0,0 +1,62 @@
{% extends "./layout/auth" %}
{% block content %}
<div class="page-single">
<div class="container">
<div class="row">
<div class="col col-login mx-auto">
<div class="text-center mb-6">
<img src="v2/assets/images/firefly-iii-48.png" class="h-6" alt="Firefly III v{{ FF_VERSION }}" title="Firefly III v{{ FF_VERSION }}">
</div>
{# ERRORS FOR RESET LOGIN STUFF #}
{% if errors.all|length > 0 %}
<div class="alert alert-danger" role="alert">
{% if errors.all|length == 1 %}
<strong>{{ 'flash_error'|_ }}</strong> {{ errors.first() }}
{% else %}
<strong>{{ 'flash_error'|_ }}</strong>
<ul>
{% for message in errors.all %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endif %}
<form class="card" action="{{ route('password.email') }}" method="post">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="card-body p-6">
{% if session('status') %}
<p>
{{ session('status') }}
</p>
{% else %}
<div class="card-title">{{ 'reset_password'|_ }}</div>
<div class="form-group">
<label class="form-label">{{ trans('form.email') }}</label>
<input autocomplete="email" type="email" name="email" class="{% if errors.has('email') %}is-invalid{% endif %} form-control"
placeholder="{{ trans('form.email') }}" value="{{ email }}" required>
{% if errors.has('email') %}
<div class="invalid-feedback">
{{ errors.get('email')[0] }}
</div>
{% endif %}
</div>
{% endif %}
{% if not session('status') %}
<div class="form-footer">
<button type="submit" class="btn btn-primary btn-block">{{ 'reset_button'|_ }}</button>
</div>
{% endif %}
</div>
</form>
<div class="text-center text-muted">
<a href="{{ route('login') }}">{{ 'want_to_login'|_ }}</a><br>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,105 @@
{% extends "./layout/auth" %}
{% block content %}
<div class="page-single">
<div class="container">
<div class="row">
<div class="col col-login mx-auto">
<div class="text-center mb-6">
<img src="v2/assets/images/firefly-iii-48.png" class="h-6" alt="Firefly III v{{ FF_VERSION }}" title="Firefly III v{{ FF_VERSION }}">
</div>
<form class="card" action="{{ route('password.reset.request') }}" method="post">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<input type="hidden" name="token" value="{{ token }}">
<div class="card-body p-6">
<div class="card-title">{{ 'reset_password'|_ }}</div>
<div class="form-group">
<label class="form-label">{{ trans('form.email') }}</label>
<input autocomplete="email" type="email" name="email" class="{% if errors.has('email') %}is-invalid{% endif %} form-control" placeholder="{{ trans('form.email') }}" value="{{ old('email') }}" required>
{% if errors.has('email') %}
<div class="invalid-feedback">
{{ errors.get('email')[0] }}
</div>
{% endif %}
</div>
<div class="form-group">
<label class="form-label">{{ trans('form.password') }}</label>
<input type="password" autocomplete="password" class="{% if errors.has('password') %}is-invalid{% endif %} form-control" name="password" placeholder="{{ trans('form.password') }}" required>
{% if errors.has('password') %}
<div class="invalid-feedback">
{{ errors.get('password')[0] }}
</div>
{% endif %}
</div>
<div class="form-group">
<label class="form-label">{{ trans('form.password_confirmation') }}</label>
<input type="password" autocomplete="password" name="{% if errors.has('password_confirmation') %}is-invalid{% endif %} password_confirmation" class="form-control" placeholder="{{ trans('form.password_confirmation') }}" required>
{% if errors.has('password_confirmation') %}
<div class="invalid-feedback">
{{ errors.get('password_confirmation')[0] }}
</div>
{% endif %}
</div>
<div class="form-group">
<label class="custom-control custom-checkbox">
<input type="checkbox" name="verify_password" value="1" checked class="custom-control-input" />
<span class="custom-control-label"><a href="#" data-toggle="modal" data-target="#pwModal">{{ trans('form.verify_password') }}</a></span>
</label>
</div>
<div class="form-footer">
<button type="submit" class="btn btn-primary btn-block">{{ 'button_reset_password'|_ }}</button>
</div>
</div>
</form>
<div class="text-center text-muted">
<a href="{{ route('login') }}">{{ 'want_to_login'|_ }}</a><br>
</div>
</div>
</div>
</div>
</div>
{# modal #}
<div class="modal fade" id="pwModal" tabindex="-1" role="dialog" aria-labelledby="pwModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
</button>
</div>
<div class="modal-body">
<p>
{{ 'secure_pw_history'|_ }}
</p>
<p>
{{ 'secure_pw_ff'|_ }}
</p>
<p>
{{ 'secure_pw_check_box'|_ }}
</p>
<h4>{{ 'secure_pw_working_title'|_ }}</h4>
<p>
{{ 'secure_pw_working'|_ }}
</p>
<h4>{{ 'secure_pw_should'|_ }}</h4>
<p>
{{ 'secure_pw_long_password'|_ }}
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">{{ 'close'|_ }}</button>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,78 @@
{% extends "./layout/auth" %}
{% block content %}
<div class="page-single">
<div class="container">
<div class="row">
<div class="col col-login mx-auto">
<div class="text-center mb-6">
<img src="v2/assets/images/firefly-iii-48.png" class="h-6" alt="Firefly III v{{ FF_VERSION }}" title="Firefly III v{{ FF_VERSION }}">
</div>
{# ERRORS FOR REGISTER STUFF #}
{% if errors.all|length > 0 %}
<div class="alert alert-danger" role="alert">
{% if errors.all|length == 1 %}
<strong>{{ 'flash_error'|_ }}</strong> {{ errors.first() }}
{% else %}
<strong>{{ 'flash_error'|_ }}</strong>
<ul>
{% for message in errors.all %}
<li>{{ message }}</li>
{% endfor %}
</ul>
{% endif %}
</div>
{% endif %}
<form class="card" action="{{ route('register') }}" method="post">
<input type="hidden" name="_token" value="{{ csrf_token() }}">
<div class="card-body p-6">
<div class="card-title">{{ 'register_new_account'|_ }}</div>
<div class="form-group">
<label class="form-label">{{ trans('form.email') }}</label>
<input autocomplete="email" type="email" name="email" class="{% if errors.has('email') %}is-invalid{% endif %} form-control" placeholder="{{ trans('form.email') }}" value="{{ email }}" required>
{% if errors.has('email') %}
<div class="invalid-feedback">
{{ errors.get('email')[0] }}
</div>
{% endif %}
</div>
<div class="form-group">
<label class="form-label">{{ trans('form.password') }}</label>
<input type="password" autocomplete="password" class="{% if errors.has('password') %}is-invalid{% endif %} form-control" name="password" placeholder="{{ trans('form.password') }}" required>
{% if errors.has('password') %}
<div class="invalid-feedback">
{{ errors.get('password')[0] }}
</div>
{% endif %}
</div>
<div class="form-group">
<label class="form-label">{{ trans('form.password_confirmation') }}</label>
<input type="password" autocomplete="password" name="{% if errors.has('password_confirmation') %}is-invalid{% endif %} password_confirmation" class="form-control" placeholder="{{ trans('form.password_confirmation') }}" required>
{% if errors.has('password_confirmation') %}
<div class="invalid-feedback">
{{ errors.get('password_confirmation')[0] }}
</div>
{% endif %}
</div>
<div class="form-group">
<label class="custom-control custom-checkbox">
<input type="checkbox" name="verify_password" value="1" checked class="custom-control-input" />
<span class="custom-control-label"><a href="#" data-toggle="modal" data-target="#pwModal">{{ trans('form.verify_password') }}</a></span>
</label>
</div>
<div class="form-footer">
<button type="submit" class="btn btn-primary btn-block">{{ 'button_register'|_ }}</button>
</div>
</div>
</form>
<div class="text-center text-muted">
<a href="{{ route('login') }}">{{ 'want_to_login'|_ }}</a><br>
</div>
</div>
</div>
</div>
</div>
{% endblock %}

View File

@ -0,0 +1,13 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Somebody (hopefully you) just created a new Firefly III API Access Token for your user account.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
With this token, they can access <strong>all</strong> of your financial records through the Firefly III API.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
If this wasn't you, please revoke this token as soon as possible at {{ route('profile.index') }}.
</p>
{% include 'emails.footer-html' %}

View File

@ -0,0 +1,7 @@
{% include 'emails.header-text' %}
Somebody (hopefully you) just created a new Firefly III API Access Token for your user account.
With this token, they can access all of your financial records through the Firefly III API.
If this wasn't you, please revoke this token as soon as possible at {{ route('profile.index') }}.
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,5 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
This is a test message from your Firefly III instance. It was sent to {{ email }}.
</p>
{% include 'emails.footer-html' %}

View File

@ -0,0 +1,3 @@
{% include 'emails.header-text' %}
This is a test message from your Firefly III instance. It was sent to {{ email }}.
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,20 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
To start using your brand new Firefly III account, you need to activate it. Activating your account allows the website to verify that this email address is
valid. Unfortunately, not even the most complex routines can work this out, without actually sending an email message. And here it is!
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
To active your account please follow the link below.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
<strong>PLEASE</strong> verify that this activation link goes to the Firefly III installation you expect it to be:
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
<a href="{{ route }}" style="color:#337ab7">{{ route }}</a>
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
You should be redirected to the index page right away. The link expires in about four hours.
</p>
{% include 'emails.footer-html' %}

View File

@ -0,0 +1,11 @@
{% include 'emails.header-text' %}
To start using your brand new Firefly III account, you need to activate it. Activating your account allows the website to verify that this email address is valid. Unfortunately, not even the most complex routines can work this out, without actually sending an email message. And here it is!
To active your account please follow the link below.
PLEASE verify that this activation link goes to the Firefly III installation you expect it to be:
{{ route }}
You should be redirected to the index page right away. The link expires in about four hours.
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,18 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
You or somebody with access to your Firefly III account has changed your email address. If you did not expect this message, please ignore and delete it.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
The old email addres was: {{ oldEmail }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
The new email address is: <strong>{{ newEmail }}</strong>
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
You cannot use Firefly III until you confirm this change. Please follow the link below to do so.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
<a href="{{ uri }}">{{ uri }}</a>
</p>
{% include 'emails.footer-html' %}

View File

@ -0,0 +1,9 @@
{% include 'emails.header-text' %}
You or somebody with access to your Firefly III account has changed your email address. If you did not expect this message, please ignore and delete it.
The old email addres was: {{ oldEmail }}
The new email address is: {{ newEmail }}
You cannot use Firefly III until you confirm this change. Please follow the link to do so: {{ uri }}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,47 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Firefly III v{{ version }} ran into an error: <span style="font-family: monospace;">{{ errorMessage }}</span>
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
The error was of type "{{ class }}".
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
The error occured on/at: {{ time }}.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
This error occured in file <span style="font-family: monospace;">{{ file }}</span> on line {{ line }} with code {{ code }}.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{% if loggedIn %}
The error was encountered by user #{{ user.id }}, <a href="mailto:{{ user.email }}">{{ user.email }}</a>.
{% else %}
There was no user logged in for this error or no user was detected.
{% endif %}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
The IP address related to this error is: {{ ip }}<br />
URL is: {{ url }}<br>
User agent: {{ userAgent }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
The full stacktrace is below. If you think this is a bug in Firefly III, you
can forward this message to
<a href="mailto:thegrumpydictator@gmail.com?subject=BUG!">thegrumpydictator@gmail.com</a>.
This can help fix the bug you just encountered.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
If you prefer, you can also open a new issue on <a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
The full stacktrace is below:</p>
<p style="font-family: monospace;font-size:11px;color:#aaa">
{{ stackTrace|nl2br }}
</p>
{% include 'emails.footer-html' %}

View File

@ -0,0 +1,31 @@
{% include 'emails.header-text' %}
Firefly III v{{ version }} ran into an error: {{ errorMessage }}.
The error was of type "{{ class }}".
The error occured on/at: {{ time }}.
This error occured in file "{{ file }}" on line {{ line }} with code {{ code }}.
{% if loggedIn %}
The error was encountered by user #{{ user.id }}, {{ user.email }}.
{% else %}
There was no user logged in for this error or no user was detected.
{% endif %}
The IP address related to this error is: {{ ip }}
URL is: {{ url }}
User agent: {{ userAgent }}
The full stacktrace is below. If you think this is a bug in Firefly III, you
can forward this message to thegrumpydictator@gmail.com. This can help fix
the bug you just encountered.
If you prefer, you can also open a new issue here:
https://github.com/firefly-iii/firefly-iii/issues
The full stacktrace is below:
{{ stackTrace }}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,13 @@
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Beep boop,
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
The Firefly III Mail Robot
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:11px;color:#aaa;">
PS: This message was sent because a request from IP {{ ip }}{{ userIp }}{{ ipAddress }} triggered it.
</p>
</body>
</html>

View File

@ -0,0 +1,6 @@
Beep boop,
The Firefly III Mail Robot
PS: This message was sent because a request from IP {{ ip }}{{ userIp }}{{ ipAddress }} triggered it.

View File

@ -0,0 +1,10 @@
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<meta content="text/html; charset=UTF-8" http-equiv="Content-Type">
</head>
<body>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Hi there,
</p>

View File

@ -0,0 +1,2 @@
Hi there,

View File

@ -0,0 +1,14 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Somebody (hopefully you) just created a new Firefly III API OAuth Client for your user account. It's labeled "{{ client.name }}"
and has callback URL <span style="font-family: monospace;">{{ client.redirect }}</span>.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
With this client, they can access <strong>all</strong> of your financial records through the Firefly III API.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
If this wasn't you, please revoke this client as soon as possible at {{ route('profile.index') }}.
</p>
{% include 'emails.footer-html' %}

View File

@ -0,0 +1,9 @@
{% include 'emails.header-text' %}
Somebody (hopefully you) just created a new Firefly III API OAuth Client for your user account. It's labeled "{{ client.name }}" and has callback URL:
{{ client.redirect }}
With this client, they can access <strong>all</strong> of your financial records through the Firefly III API.
If this wasn't you, please revoke this client as soon as possible at {{ route('profile.index') }}.
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,13 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Somebody tried to reset your password. If it was you, please follow the link below to do so.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
<strong>PLEASE</strong> verify that the link actually goes to the Firefly III you expect it to go!
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
<a href="{{ url }}">{{ url }}</a>
</p>
{% include 'emails.footer-html' %}

View File

@ -0,0 +1,7 @@
{% include 'emails.header-text' %}
Somebody tried to reset your password. If it was you, please follow the link below to do so.
PLEASE verify that the link actually goes to the Firefly III you expect it to go!
{{ url }}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,18 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
Welkome to <a style="color:#337ab7" href="{{ address }}">Firefly III</a>. Your registration has made it, and this email is here to confirm it. Yay!
</p>
<ul>
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
If you have forgotten your password already, please reset it using
<a style="color:#337ab7" href="{{ address }}/password/reset">the password reset tool</a>.
</li>
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
There is a help-icon in the top right corner of each page. If you need help, click it!
</li>
<li style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
If you haven't already, please read the <a style="color:#337ab7" href="https://firefly-iii.org/description/">full description</a>.
</li>
</ul>
{% include 'emails.footer-html' %}

View File

@ -0,0 +1,20 @@
{% include 'emails.header-text' %}
Welkome to Firefly III. Your registration has made it, and this email is here to confirm it. Yay!
* If you have forgotten your password already, please reset it using the password reset tool.
* There is a help-icon in the top right corner of each page. If you need help, click it!
* If you haven't already, please read the first use guide and the full description.
Enjoy!
Firefly III:
{{ address }}
Password reset:
{{ address }}/password/reset
Documentation:
https://github.com/firefly-iii/firefly-iii
https://firefly-iii.org/
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,34 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
{% if journals.count == 1 %}
Firefly III has created a transaction for you.
{% endif %}
{% if journals.count > 1 %}
Firefly III has created {{ journals.count }} transactions for you.
{% endif %}
</p>
{% if journals.count == 1 %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
You can find it in your Firefly III installation:<br />
{% for journal in journals %}
<a href="{{ route('transactions.show', journal.id) }}">{{ journal.description }}</a> ({{ journal|journalTotalAmount }})
{% endfor %}
</p>
{% endif %}
{% if journals.count > 1 %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
You can find them in your Firefly III installation:
</p>
<ul>
{% for journal in journals %}
<li>
<a href="{{ route('transactions.show', journal.id) }}">{{ journal.description }}</a> ({{ journal|journalTotalAmount }})
</li>
{% endfor %}
</ul>
{% endif %}
{% include 'emails.footer-html' %}

View File

@ -0,0 +1,25 @@
{% include 'emails.header-text' %}
{% if journals.count == 1 %}
Firefly III has created a transaction for you.
{% endif %}
{% if journals.count > 1 %}
Firefly III has created {{ journals.count }} transactions for you.
{% endif %}
{% if journals.count == 1 %}
You can find in in your Firefly III installation:
{% for journal in journals %}
{{ journal.description }}: {{ route('transactions.show', journal.id) }} ({{ journal|journalTotalAmountPlain }})
{% endfor %}
{% endif %}
{% if journals.count > 1 %}
You can find them in your Firefly III installation:
{% for journal in journals %}
- {{ journal.description }}: {{ route('transactions.show', journal.id) }} ({{ journal|journalTotalAmountPlain }})
{% endfor %}
{% endif %}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,18 @@
{% include 'emails.header-html' %}
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
You or somebody with access to your Firefly III account has changed your email address.
If you did not expect this to happen, you <strong>must</strong> follow the "undo"-link below to protect your account!
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
If you initiated this change, you may safely ignore this message.
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
The old email addres was: <strong>{{ oldEmail }}</strong>
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
The new email address is: {{ newEmail }}
</p>
<p style="font-family: 'Helvetica Neue', Helvetica, Arial, sans-serif;font-size:13px;">
To undo the change, follow this link: <a href="{{ uri }}">{{ uri }}</a>
</p>
{% include 'emails.footer-html' %}

View File

@ -0,0 +1,12 @@
{% include 'emails.header-text' %}
You or somebody with access to your Firefly III account has changed your email address. If you did not expect this to happen,
you must follow the "undo"-link below to protect your account!
If you initiated this change, you may safely ignore this message.
The old email addres was: {{ oldEmail }}
The new email address is: {{ newEmail }}
To undo the change, follow this link: {{ uri }}
{% include 'emails.footer-text' %}

View File

@ -0,0 +1,35 @@
<!doctype html>
<html lang="en" dir="ltr">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta http-equiv="Content-Language" content="en" />
{# favicons #}
{% include('partials.favicons') %}
<link rel="icon" href="./favicon.ico" type="image/x-icon"/>
<link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" />
<!-- Generated: 2018-04-16 09:29:05 +0200 -->
<title>500</title>
<link rel="stylesheet" href="v2/lib/font-awesome/4.7.0/css/font-awesome.min.css?v={{ FF_VERSION }}">
<link rel="stylesheet" href="v2/assets/css/gf-source.css?v={{ FF_VERSION }}">
<link href="v2/assets/css/dashboard.css" rel="stylesheet" />
</head>
<body class="">
<div class="page">
<div class="page-content">
<div class="container text-center">
<div class="display-1 text-muted mb-5">Firefly III error</div>
<h1 class="h2 mb-3">{{ message |default('General unknown errror')|raw }}</h1>
<p class="h4 text-muted font-weight-normal mb-7">
If you do not know how to handle this error, please open an issue on
<a href="https://github.com/firefly-iii/firefly-iii/issues">GitHub</a>
or <a href="mailto:thegrumpydictator@gmail.com">send me a message</a>.</p>
<a class="btn btn-primary" href="javascript:history.back()">
<i class="fe fe-arrow-left mr-2"></i>Go back
</a>
</div>
</div>
</div>
</body>
</html>

View File

@ -0,0 +1,29 @@
<!doctype html>
<html lang="en" dir="ltr">
<head>
<base href="{{ route('index') }}/">
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta http-equiv="Content-Language" content="en"/>
{# favicons #}
{% include('partials.favicons') %}
<title>{{ pageTitle|default('Firefly III') }} (v{{ FF_VERSION }})</title>
<link rel="stylesheet" href="v2/lib/font-awesome/4.7.0/css/font-awesome.min.css">
<link rel="stylesheet" href="v2/assets/css/gf-source.css">
<link href="v2/assets/css/dashboard.css" rel="stylesheet"/>
</head>
<body>
<div class="page">
{% block content %}{% endblock %}
<script src="v2/assets/js/vendors/jquery-3.2.1.min.js"></script>
<script src="v2/assets/js/vendors/bootstrap.bundle.min.js"></script>
{# favicons #}
{% include('partials.password_modal') %}
</div>
</body>
</html>

View File

@ -7,19 +7,9 @@
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<meta http-equiv="Content-Language" content="en" />
{# favicons #}
{% include('partials.favicons') %}
<meta name="msapplication-TileColor" content="#2d89ef">
<meta name="theme-color" content="#4188c9">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">
<link rel="icon" href="./favicon.ico" type="image/x-icon"/>
<link rel="shortcut icon" type="image/x-icon" href="./favicon.ico" />
<!-- Generated: 2018-04-16 09:29:05 +0200 -->
<title>
{% if subTitle %}
{{ subTitle }} »

View File

@ -8,4 +8,9 @@
<meta name="application-name" content="Firefly III">
<meta name="msapplication-TileColor" content="#2d89ef">
<meta name="msapplication-TileImage" content="/mstile-144x144.png?v=3e8AboOwbd">
<meta name="theme-color" content="#ffffff">
<meta name="theme-color" content="#ffffff">
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent"/>
<meta name="apple-mobile-web-app-capable" content="yes">
<meta name="mobile-web-app-capable" content="yes">
<meta name="HandheldFriendly" content="True">
<meta name="MobileOptimized" content="320">

View File

@ -0,0 +1,35 @@
{# modal #}
<div class="modal fade" id="pwModal" tabindex="-1" role="dialog" aria-labelledby="pwModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Modal title</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
</button>
</div>
<div class="modal-body">
<p>
{{ 'secure_pw_history'|_ }}
</p>
<p>
{{ 'secure_pw_ff'|_ }}
</p>
<p>
{{ 'secure_pw_check_box'|_ }}
</p>
<h4>{{ 'secure_pw_working_title'|_ }}</h4>
<p>
{{ 'secure_pw_working'|_ }}
</p>
<h4>{{ 'secure_pw_should'|_ }}</h4>
<p>
{{ 'secure_pw_long_password'|_ }}
</p>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-primary" data-dismiss="modal">{{ 'close'|_ }}</button>
</div>
</div>
</div>
</div>