Add support for including password in email; include portal customizations

This commit is contained in:
Joshua Dwire 2016-03-05 18:09:50 -05:00
parent 793ba76415
commit d0d30e1e26
10 changed files with 129 additions and 41 deletions

View File

@ -431,7 +431,6 @@ class AccountController extends BaseController
$data = [
'client_view_css' => $css,
'enable_portal_password' => $account->enable_portal_password,
'fill_portal_password' => $account->fill_portal_password,
'send_portal_password' => $account->send_portal_password,
'title' => trans("texts.client_portal"),
'section' => ACCOUNT_CLIENT_PORTAL,
@ -549,8 +548,8 @@ class AccountController extends BaseController
$account = Auth::user()->account;
$account->client_view_css = $sanitized_css;
$account->enable_client_portal = !!Input::get('enable_client_portal');
$account->enable_portal_password = !!Input::get('enable_portal_password');
$account->fill_portal_password = !!Input::get('fill_portal_password');
$account->send_portal_password = !!Input::get('send_portal_password');
$account->save();

View File

@ -22,7 +22,24 @@ class AuthController extends Controller {
public function showLoginForm()
{
return view('clientauth.login');
$data = array(
);
$invitation_key = session('invitation_key');
if($invitation_key){
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first();
if ($invitation && !$invitation->is_deleted) {
$invoice = $invitation->invoice;
$client = $invoice->client;
$account = $client->account;
$data['hideLogo'] = $account->isWhiteLabel();
$data['clientViewCSS'] = $account->clientViewCSS();
$data['clientFontUrl'] = $account->getFontsUrl();
}
}
return view('clientauth.login')->with($data);
}
/**

View File

@ -2,7 +2,6 @@
use Config;
use App\Http\Controllers\Controller;
use App\Http\Brokers\ClientPasswordBroker;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
use Illuminate\Mail\Message;
@ -42,7 +41,22 @@ class PasswordController extends Controller {
public function showLinkRequestForm()
{
return view('clientauth.password');
$data = array();
$invitation_key = session('invitation_key');
if($invitation_key){
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first();
if ($invitation && !$invitation->is_deleted) {
$invoice = $invitation->invoice;
$client = $invoice->client;
$account = $client->account;
$data['hideLogo'] = $account->isWhiteLabel();
$data['clientViewCSS'] = $account->clientViewCSS();
$data['clientFontUrl'] = $account->getFontsUrl();
}
}
return view('clientauth.password')->with($data);
}
/**
@ -93,8 +107,23 @@ class PasswordController extends Controller {
if (is_null($token)) {
return $this->getEmail();
}
$data = compact('token', 'invitation_key');
$invitation_key = session('invitation_key');
if($invitation_key){
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first();
if ($invitation && !$invitation->is_deleted) {
$invoice = $invitation->invoice;
$client = $invoice->client;
$account = $client->account;
$data['hideLogo'] = $account->isWhiteLabel();
$data['clientViewCSS'] = $account->clientViewCSS();
$data['clientFontUrl'] = $account->getFontsUrl();
}
}
return view('clientauth.reset')->with(compact('token', 'invitation_key'));
return view('clientauth.reset')->with($data);
}

View File

@ -31,6 +31,7 @@ class ContactMailer extends Mailer
'viewButton',
'paymentLink',
'paymentButton',
'password',
];
public function sendInvoice(Invoice $invoice, $reminder = false, $pdfString = false)
@ -109,6 +110,13 @@ class ContactMailer extends Mailer
'invitation' => $invitation,
'amount' => $invoice->getRequestedAmount()
];
if (empty($invitation->contact->password) && $account->isPro() && $account->enable_portal_password && $account->send_portal_password) {
// The contact needs a password
$variables['password'] = $password = $this->generatePassword();
$invitation->contact->password = bcrypt($password);
$invitation->contact->save();
}
$data = [
'body' => $this->processVariables($body, $variables),
@ -143,6 +151,28 @@ class ContactMailer extends Mailer
return $response;
}
}
protected function generatePassword($length = 9)
{
$sets = array(
'abcdefghjkmnpqrstuvwxyz',
'ABCDEFGHJKMNPQRSTUVWXYZ',
'23456789',
);
$all = '';
$password = '';
foreach($sets as $set)
{
$password .= $set[array_rand(str_split($set))];
$all .= $set;
}
$all = str_split($all);
for($i = 0; $i < $length - count($sets); $i++)
$password .= $all[array_rand($all)];
$password = str_shuffle($password);
return $password;
}
public function sendPaymentConfirmation(Payment $payment)
{
@ -253,6 +283,7 @@ class ContactMailer extends Mailer
'$customClient2' => $account->custom_client_label2,
'$customInvoice1' => $account->custom_invoice_text_label1,
'$customInvoice2' => $account->custom_invoice_text_label2,
'$password' => isset($data['password'])?$data['password']:false,
];
// Add variables for available payment types

View File

@ -14,7 +14,6 @@ class AddClientPassword extends Migration {
{
Schema::table('accounts', function ($table) {
$table->boolean('enable_portal_password')->default(0);
$table->boolean('fill_portal_password')->default(0);
$table->boolean('send_portal_password')->default(0);
});
@ -34,7 +33,6 @@ class AddClientPassword extends Migration {
{
Schema::table('accounts', function ($table) {
$table->dropColumn('enable_portal_password');
$table->dropColumn('fill_portal_password');
$table->dropColumn('send_portal_password');
});

View File

@ -1053,10 +1053,10 @@ $LANG = array(
'enable_client_portal_help' => 'Show/hide the dashboard page in the client portal.',
// Client Passwords
'client_portal_login_settings'=>'Login',
'enable_portal_password'=>'Require a password',
'enable_portal_password'=>'Password protect invoices',
'enable_portal_password_help'=>'Allows you to set a password for each contact. If a password is set, the contact will be required to enter a password before viewing invoices.',
'send_portal_password'=>'Generate password automatically',
'fill_portal_password'=>'Include password in invoice emails',
'send_portal_password_help'=>'If no password is set, one will be generated and sent with the first invoice.',
);
return $LANG;

View File

@ -15,6 +15,7 @@
{!! Former::populateField('enable_client_portal', intval($account->enable_client_portal)) !!}
{!! Former::populateField('client_view_css', $client_view_css) !!}
{!! Former::populateField('enable_portal_password', $enable_portal_password) !!}
{!! Former::populateField('send_portal_password', $send_portal_password) !!}
@if (!Utils::isNinja() && !Auth::user()->account->isWhiteLabel())
<div class="alert alert-warning" style="font-size:larger;">
@ -40,16 +41,13 @@
<div class="col-md-10 col-md-offset-1">
{!! Former::checkbox('enable_portal_password')
->text(trans('texts.enable_portal_password'))
->label('&nbsp;') !!}
</div>
<div class="col-md-10 col-md-offset-1">
{!! Former::checkbox('fill_portal_password')
->text(trans('texts.fill_portal_password'))
->help(trans('texts.enable_portal_password_help'))
->label('&nbsp;') !!}
</div>
<div class="col-md-10 col-md-offset-1">
{!! Former::checkbox('send_portal_password')
->text(trans('texts.send_portal_password'))
->help(trans('texts.send_portal_password_help'))
->label('&nbsp;') !!}
</div>
</div>
@ -67,7 +65,6 @@
->autofocus()
->maxlength(60000)
->style("min-width:100%;max-width:100%;font-family:'Roboto Mono', 'Lucida Console', Monaco, monospace;font-size:14px;'") !!}
</div>
</div>
</div>
</div>
@ -82,7 +79,6 @@
$('#enable_portal_password').change(fixCheckboxes);
function fixCheckboxes(){
var checked = $('#enable_portal_password').is(':checked');
$('#fill_portal_password').prop('disabled', !checked);
$('#send_portal_password').prop('disabled', !checked);
}
fixCheckboxes();

View File

@ -1,10 +1,7 @@
@extends('master')
@extends('public.header')
@section('head')
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('css/style.css') }}" rel="stylesheet" type="text/css"/>
@parent
<style type="text/css">
body {
padding-top: 40px;
@ -13,6 +10,8 @@
.modal-header {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
background:#222;
color:#fff
}
.modal-header h4 {
margin:0;
@ -69,11 +68,16 @@
->addClass('form-signin') !!}
{{ Former::populateField('remember', 'true') }}
<div class="modal-header">
<a href="{{ NINJA_WEB_URL }}" target="_blank">
<div class="modal-header">
@if (!isset($hideLogo) || !$hideLogo)
<a href="{{ NINJA_WEB_URL }}" target="_blank">
<img src="{{ asset('images/icon-login.png') }}" />
<h4>Invoice Ninja | {{ trans('texts.account_login') }}</h4>
</a>
@else
<h4>{{ trans('texts.account_login') }}</h4>
</a>
</div>
@endif
</div>
<div class="inner">
<p>
{!! Former::password('password')->placeholder(trans('texts.password'))->raw() !!}

View File

@ -1,10 +1,7 @@
@extends('master')
@extends('public.header')
@section('head')
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('css/style.css') }}" rel="stylesheet" type="text/css"/>
@parent
<style type="text/css">
body {
padding-top: 40px;
@ -13,6 +10,8 @@
.modal-header {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
background:#222;
color:#fff
}
.modal-header h4 {
margin:0;
@ -54,8 +53,16 @@
<div class="container">
{!! Former::open('client/forgot')->addClass('form-signin') !!}
<div class="modal-header">
<h4>{{ trans('texts.password_recovery') }}</h4></div>
<div class="modal-header">
@if (!isset($hideLogo) || !$hideLogo)
<a href="{{ NINJA_WEB_URL }}" target="_blank">
<img src="{{ asset('images/icon-login.png') }}" />
<h4>Invoice Ninja | {{ trans('texts.password_recovery') }}</h4>
</a>
@else
<h4>{{ trans('texts.password_recovery') }}</h4>
@endif
</div>
<div class="inner">
<p>{!! Button::success(trans('texts.send_email'))->large()->submit()->block() !!}</p>

View File

@ -1,10 +1,7 @@
@extends('master')
@extends('public.header')
@section('head')
<link href="{{ asset('css/bootstrap.min.css') }}" rel="stylesheet" type="text/css"/>
<link href="{{ asset('css/style.css') }}" rel="stylesheet" type="text/css"/>
@parent
<style type="text/css">
body {
padding-top: 40px;
@ -13,6 +10,8 @@
.modal-header {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
background:#222;
color:#fff
}
.modal-header h4 {
margin:0;
@ -58,8 +57,16 @@
'password_confirmation' => 'required',
)) !!}
<div class="modal-header">
<h4>{{ trans('texts.set_password') }}</h4></div>
<div class="modal-header">
@if (!isset($hideLogo) || !$hideLogo)
<a href="{{ NINJA_WEB_URL }}" target="_blank">
<img src="{{ asset('images/icon-login.png') }}" />
<h4>Invoice Ninja | {{ trans('texts.set_password') }}</h4>
</a>
@else
<h4>{{ trans('texts.set_password') }}</h4>
@endif
</div>
<div class="inner">
<input type="hidden" name="token" value="{{{ $token }}}">