mirror of
https://github.com/invoiceninja/invoiceninja.git
synced 2025-07-09 03:14:30 -04:00
Merge branch 'develop' of github.com:invoiceninja/invoiceninja into develop
This commit is contained in:
commit
4c4cbf316e
@ -310,7 +310,7 @@ if (! defined('APP_NAME')) {
|
||||
define('NINJA_APP_URL', env('NINJA_APP_URL', 'https://app.invoiceninja.com'));
|
||||
define('NINJA_DOCS_URL', env('NINJA_DOCS_URL', 'http://docs.invoiceninja.com/en/latest'));
|
||||
define('NINJA_DATE', '2000-01-01');
|
||||
define('NINJA_VERSION', '3.9.0' . env('NINJA_VERSION_SUFFIX'));
|
||||
define('NINJA_VERSION', '3.9.1' . env('NINJA_VERSION_SUFFIX'));
|
||||
|
||||
define('SOCIAL_LINK_FACEBOOK', env('SOCIAL_LINK_FACEBOOK', 'https://www.facebook.com/invoiceninja'));
|
||||
define('SOCIAL_LINK_TWITTER', env('SOCIAL_LINK_TWITTER', 'https://twitter.com/invoiceninja'));
|
||||
|
@ -10,6 +10,7 @@ use Illuminate\Foundation\Auth\AuthenticatesUsers;
|
||||
use Illuminate\Contracts\Auth\Authenticatable;
|
||||
use Event;
|
||||
use Cache;
|
||||
use Lang;
|
||||
use App\Events\UserLoggedIn;
|
||||
use App\Http\Requests\ValidateTwoFactorRequest;
|
||||
|
||||
@ -186,7 +187,7 @@ class LoginController extends Controller
|
||||
|
||||
$reason = htmlentities(request()->reason);
|
||||
if (!empty($reason) && Lang::has("texts.{$reason}_logout")) {
|
||||
sesion()->flash('warning', trans("texts.{$reason}_logout"));
|
||||
session()->flash('warning', trans("texts.{$reason}_logout"));
|
||||
}
|
||||
|
||||
return $response;
|
||||
|
@ -54,4 +54,14 @@ class ResetPasswordController extends Controller
|
||||
return $this->traitSendResetResponse($response);
|
||||
}
|
||||
}
|
||||
|
||||
public function showResetForm(Request $request, $token = null)
|
||||
{
|
||||
$passwordReset = PasswordReset::whereToken($token)->first();
|
||||
$email = $passwordReset ? $passwordReset->email : '';
|
||||
|
||||
return view('auth.passwords.reset')->with(
|
||||
['token' => $token, 'email' => $email]
|
||||
);
|
||||
}
|
||||
}
|
||||
|
@ -6,6 +6,8 @@ use Password;
|
||||
use Config;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\PasswordReset;
|
||||
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
@ -48,13 +50,16 @@ class ResetPasswordController extends Controller
|
||||
|
||||
protected function guard()
|
||||
{
|
||||
return auth()->guard('clients');
|
||||
return auth()->guard('client');
|
||||
}
|
||||
|
||||
public function showResetForm(Request $request, $token = null)
|
||||
{
|
||||
$passwordReset = PasswordReset::whereToken($token)->first();
|
||||
$email = $passwordReset ? $passwordReset->email : '';
|
||||
|
||||
return view('clientauth.passwords.reset')->with(
|
||||
['token' => $token, 'email' => $request->email]
|
||||
['token' => $token, 'email' => $email]
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -104,7 +104,7 @@ Route::get('/client/login', ['as' => 'login', 'uses' => 'ClientAuth\LoginControl
|
||||
Route::get('/client/logout', ['as' => 'logout', 'uses' => 'ClientAuth\LoginController@getLogout']);
|
||||
Route::get('/client/session_expired', ['as' => 'logout', 'uses' => 'ClientAuth\LoginController@getSessionExpired']);
|
||||
Route::get('/client/recover_password', ['as' => 'forgot', 'uses' => 'ClientAuth\ForgotPasswordController@showLinkRequestForm']);
|
||||
Route::get('/client/password/reset/{token}', ['as' => 'forgot', 'uses' => 'Auth\ResetPasswordController@showResetForm']);
|
||||
Route::get('/client/password/reset/{token}', ['as' => 'forgot', 'uses' => 'ClientAuth\ResetPasswordController@showResetForm']);
|
||||
|
||||
Route::group(['middleware' => ['lookup:contact']], function () {
|
||||
Route::post('/client/login', ['as' => 'login', 'uses' => 'ClientAuth\LoginController@login']);
|
||||
|
@ -183,6 +183,12 @@ class Contact extends EntityModel implements AuthenticatableContract, CanResetPa
|
||||
|
||||
return "{$url}/client/dashboard/{$this->contact_key}";
|
||||
}
|
||||
|
||||
public function sendPasswordResetNotification($token)
|
||||
{
|
||||
//$this->notify(new ResetPasswordNotification($token));
|
||||
app('App\Ninja\Mailers\ContactMailer')->sendPasswordReset($this, $token);
|
||||
}
|
||||
}
|
||||
|
||||
Contact::creating(function ($contact)
|
||||
|
13
app/Models/PasswordReset.php
Normal file
13
app/Models/PasswordReset.php
Normal file
@ -0,0 +1,13 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use Eloquent;
|
||||
|
||||
/**
|
||||
* Class Client.
|
||||
*/
|
||||
class PasswordReset extends Eloquent
|
||||
{
|
||||
|
||||
}
|
@ -256,7 +256,7 @@ class PaymentMethod extends EntityModel
|
||||
PaymentMethod::deleting(function ($paymentMethod) {
|
||||
$accountGatewayToken = $paymentMethod->account_gateway_token;
|
||||
if ($accountGatewayToken->default_payment_method_id == $paymentMethod->id) {
|
||||
$newDefault = $accountGatewayToken->payment_methods->first(function ($i, $paymentMethdod) use ($accountGatewayToken) {
|
||||
$newDefault = $accountGatewayToken->payment_methods->first(function ($paymentMethdod) use ($accountGatewayToken) {
|
||||
return $paymentMethdod->id != $accountGatewayToken->default_payment_method_id;
|
||||
});
|
||||
$accountGatewayToken->default_payment_method_id = $newDefault ? $newDefault->id : null;
|
||||
|
@ -421,6 +421,12 @@ class User extends Authenticatable
|
||||
{
|
||||
return $this->account->company->accounts->sortBy('id')->first();
|
||||
}
|
||||
|
||||
public function sendPasswordResetNotification($token)
|
||||
{
|
||||
//$this->notify(new ResetPasswordNotification($token));
|
||||
app('App\Ninja\Mailers\UserMailer')->sendPasswordReset($this, $token);
|
||||
}
|
||||
}
|
||||
|
||||
User::created(function ($user)
|
||||
|
@ -327,4 +327,19 @@ class ContactMailer extends Mailer
|
||||
|
||||
$this->sendTo($email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data);
|
||||
}
|
||||
|
||||
public function sendPasswordReset($contact, $token)
|
||||
{
|
||||
if (! $contact->email) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subject = trans('texts.your_password_reset_link');
|
||||
$view = 'client_password';
|
||||
$data = [
|
||||
'token' => $token,
|
||||
];
|
||||
|
||||
$this->sendTo($contact->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data);
|
||||
}
|
||||
}
|
||||
|
@ -154,4 +154,19 @@ class UserMailer extends Mailer
|
||||
|
||||
$this->sendTo($user->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data);
|
||||
}
|
||||
|
||||
public function sendPasswordReset($user, $token)
|
||||
{
|
||||
if (! $user->email) {
|
||||
return;
|
||||
}
|
||||
|
||||
$subject = trans('texts.your_password_reset_link');
|
||||
$view = 'password';
|
||||
$data = [
|
||||
'token' => $token,
|
||||
];
|
||||
|
||||
$this->sendTo($user->email, CONTACT_EMAIL, CONTACT_NAME, $subject, $view, $data);
|
||||
}
|
||||
}
|
||||
|
@ -59,7 +59,7 @@ author = u'Invoice Ninja'
|
||||
# The short X.Y version.
|
||||
version = u'3.9'
|
||||
# The full version, including alpha/beta/rc tags.
|
||||
release = u'3.9.0'
|
||||
release = u'3.9.1'
|
||||
|
||||
# The language for content autogenerated by Sphinx. Refer to documentation
|
||||
# for a list of supported languages.
|
||||
|
@ -2521,6 +2521,7 @@ $LANG = array(
|
||||
'self_host_login' => 'Self-Host Login',
|
||||
'set_self_hoat_url' => 'Self-Host URL',
|
||||
'local_storage_required' => 'Error: local storage is not available.',
|
||||
'your_password_reset_link' => 'Your Password Reset Link',
|
||||
|
||||
);
|
||||
|
||||
|
@ -3,11 +3,16 @@
|
||||
@section('form')
|
||||
<div class="container">
|
||||
|
||||
{!! Former::open('/password/reset')->addClass('form-signin')->rules(array(
|
||||
{!! Former::open('/password/reset')
|
||||
->addClass('form-signin')
|
||||
->autocomplete('off')
|
||||
->rules(array(
|
||||
'password' => 'required',
|
||||
'password_confirmation' => 'required',
|
||||
)) !!}
|
||||
|
||||
@include('partials.autocomplete_fix')
|
||||
|
||||
<h2 class="form-signin-heading">{{ trans('texts.set_password') }}</h2>
|
||||
<hr class="green">
|
||||
|
||||
@ -35,9 +40,9 @@
|
||||
<input type="hidden" name="token" value="{{{ $token }}}">
|
||||
|
||||
<div>
|
||||
{!! Former::text('email')->placeholder(trans('texts.email'))->raw() !!}
|
||||
{!! Former::password('password')->placeholder(trans('texts.password'))->raw() !!}
|
||||
{!! Former::password('password_confirmation')->placeholder(trans('texts.confirm_password'))->raw() !!}
|
||||
{!! Former::text('email')->placeholder(trans('texts.password'))->value($email)->raw() !!}
|
||||
{!! Former::password('password')->placeholder(trans('texts.password'))->autocomplete('new-password')->raw() !!}
|
||||
{!! Former::password('password_confirmation')->placeholder(trans('texts.confirm_password'))->autocomplete('new-password')->raw() !!}
|
||||
</div>
|
||||
|
||||
<p>{!! Button::success(trans('texts.save'))->large()->submit()->withAttributes(['class' => 'green'])->block() !!}</p>
|
||||
|
@ -3,11 +3,16 @@
|
||||
@section('form')
|
||||
<div class="container">
|
||||
|
||||
{!! Former::open('/client/password/reset')->addClass('form-signin')->rules(array(
|
||||
{!! Former::open('/client/password/reset')
|
||||
->addClass('form-signin')
|
||||
->autocomplete('false')
|
||||
->rules(array(
|
||||
'password' => 'required',
|
||||
'password_confirmation' => 'required',
|
||||
)) !!}
|
||||
|
||||
@include('partials.autocomplete_fix')
|
||||
|
||||
<h2 class="form-signin-heading">{{ trans('texts.set_password') }}</h2>
|
||||
<hr class="green">
|
||||
|
||||
@ -35,8 +40,9 @@
|
||||
<input type="hidden" name="token" value="{{{ $token }}}">
|
||||
|
||||
<div>
|
||||
{!! Former::password('password')->placeholder(trans('texts.password'))->raw() !!}
|
||||
{!! Former::password('password_confirmation')->placeholder(trans('texts.confirm_password'))->raw() !!}
|
||||
{!! Former::text('email')->placeholder(trans('texts.password'))->value($email)->raw() !!}
|
||||
{!! Former::password('password')->placeholder(trans('texts.password'))->autocomplete('new-password')->raw() !!}
|
||||
{!! Former::password('password_confirmation')->placeholder(trans('texts.confirm_password'))->autocomplete('new-password')->raw() !!}
|
||||
</div>
|
||||
|
||||
<p>{!! Button::success(trans('texts.save'))->large()->submit()->withAttributes(['class' => 'green'])->block() !!}</p>
|
||||
|
10
resources/views/emails/client_password_text.blade.php
Normal file
10
resources/views/emails/client_password_text.blade.php
Normal file
@ -0,0 +1,10 @@
|
||||
{{ trans('texts.reset_password') }}
|
||||
|
||||
{!! URL::to(SITE_URL . "/client/password/reset/{$token}") !!}
|
||||
|
||||
@if (Utils::isNinja() || ! Utils::isWhiteLabel())
|
||||
{{ trans('texts.email_signature') }}<br/>
|
||||
{{ trans('texts.email_from') }}
|
||||
@endif
|
||||
|
||||
{{ trans('texts.reset_password_footer', ['email' => env('CONTACT_EMAIL', CONTACT_EMAIL)]) }}
|
8
resources/views/emails/password_text.blade.php
Normal file
8
resources/views/emails/password_text.blade.php
Normal file
@ -0,0 +1,8 @@
|
||||
{{ trans('texts.reset_password') }}
|
||||
|
||||
{!! URL::to(SITE_URL . "/password/reset/{$token}") !!}
|
||||
|
||||
{{ trans('texts.email_signature') }}
|
||||
{{ trans('texts.email_from') }}
|
||||
|
||||
{{ trans('texts.reset_password_footer', ['email' => env('CONTACT_EMAIL', CONTACT_EMAIL)]) }}
|
@ -1,4 +1,4 @@
|
||||
<!-- http://stackoverflow.com/a/30873633/497368 -->
|
||||
<div style="display: none;">
|
||||
<input type="text" id="PreventChromeAutocomplete" name="PreventChromeAutocomplete" autocomplete="address-level4" />
|
||||
</div>
|
||||
</div>
|
||||
|
@ -132,7 +132,7 @@ class AcceptanceTester extends \Codeception\Actor
|
||||
$I->selectOption('#expiration_month', 12);
|
||||
$I->selectOption('#expiration_year', date('Y'));
|
||||
$I->click('.btn-success');
|
||||
$I->wait(3);
|
||||
$I->wait(5);
|
||||
$I->see('Successfully applied payment');
|
||||
});
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user