Add contact_key

This commit is contained in:
Joshua Dwire 2016-05-24 17:02:28 -04:00
parent f8835268b4
commit 724f5738aa
13 changed files with 283 additions and 147 deletions

View File

@ -10,7 +10,7 @@ use App\Events\UserLoggedIn;
use App\Http\Controllers\Controller; use App\Http\Controllers\Controller;
use App\Ninja\Repositories\AccountRepository; use App\Ninja\Repositories\AccountRepository;
use App\Services\AuthService; use App\Services\AuthService;
use App\Models\Invitation; use App\Models\Contact;
use Illuminate\Foundation\Auth\AuthenticatesUsers; use Illuminate\Foundation\Auth\AuthenticatesUsers;
class AuthController extends Controller { class AuthController extends Controller {
@ -22,16 +22,13 @@ class AuthController extends Controller {
public function showLoginForm() public function showLoginForm()
{ {
$data = array( $data = array();
);
$invitation_key = session('invitation_key'); $contactKey = session('contact_key');
if($invitation_key){ if($contactKey){
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first(); $contact = Contact::where('contact_key', '=', $contactKey)->first();
if ($invitation && !$invitation->is_deleted) { if ($contact && !$contact->is_deleted) {
$invoice = $invitation->invoice; $account = $contact->account;
$client = $invoice->client;
$account = $client->account;
$data['account'] = $account; $data['account'] = $account;
$data['clientFontUrl'] = $account->getFontsUrl(); $data['clientFontUrl'] = $account->getFontsUrl();
@ -52,11 +49,11 @@ class AuthController extends Controller {
$credentials = $request->only('password'); $credentials = $request->only('password');
$credentials['id'] = null; $credentials['id'] = null;
$invitation_key = session('invitation_key'); $contactKey = session('contact_key');
if($invitation_key){ if($contactKey){
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first(); $contact = Contact::where('contact_key', '=', $contactKey)->first();
if ($invitation && !$invitation->is_deleted) { if ($contact && !$contact->is_deleted) {
$credentials['id'] = $invitation->contact_id; $credentials['id'] = $contact->id;
} }
} }
@ -75,4 +72,9 @@ class AuthController extends Controller {
'password' => 'required', 'password' => 'required',
]); ]);
} }
public function getSessionExpired()
{
return view('clientauth.sessionexpired');
}
} }

View File

@ -6,6 +6,7 @@ use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request; use Illuminate\Http\Request;
use Illuminate\Mail\Message; use Illuminate\Mail\Message;
use Illuminate\Support\Facades\Password; use Illuminate\Support\Facades\Password;
use App\Models\Contact;
use App\Models\Invitation; use App\Models\Invitation;
@ -42,16 +43,16 @@ class PasswordController extends Controller {
public function showLinkRequestForm() public function showLinkRequestForm()
{ {
$data = array(); $data = array();
$invitation_key = session('invitation_key'); $contactKey = session('contact_key');
if($invitation_key){ if($contactKey){
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first(); $contact = Contact::where('contact_key', '=', $contactKey)->first();
if ($invitation && !$invitation->is_deleted) { if ($contact && !$contact->is_deleted) {
$invoice = $invitation->invoice; $account = $contact->account;
$client = $invoice->client;
$account = $client->account;
$data['account'] = $account; $data['account'] = $account;
$data['clientFontUrl'] = $account->getFontsUrl(); $data['clientFontUrl'] = $account->getFontsUrl();
} }
} else {
return \Redirect::to('/client/sessionexpired');
} }
return view('clientauth.password')->with($data); return view('clientauth.password')->with($data);
@ -67,16 +68,16 @@ class PasswordController extends Controller {
{ {
$broker = $this->getBroker(); $broker = $this->getBroker();
$contact_id = null; $contactId = null;
$invitation_key = session('invitation_key'); $contactKey = session('contact_key');
if($invitation_key){ if($contactKey){
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first(); $contact = Contact::where('contact_key', '=', $contactKey)->first();
if ($invitation && !$invitation->is_deleted) { if ($contact && !$contact->is_deleted) {
$contact_id = $invitation->contact_id; $contactId = $contact->id;
} }
} }
$response = Password::broker($broker)->sendResetLink(array('id'=>$contact_id), function (Message $message) { $response = Password::broker($broker)->sendResetLink(array('id'=>$contactId), function (Message $message) {
$message->subject($this->getEmailSubject()); $message->subject($this->getEmailSubject());
}); });
@ -96,27 +97,36 @@ class PasswordController extends Controller {
* If no token is present, display the link request form. * If no token is present, display the link request form.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param string|null $invitation_key * @param string|null $key
* @param string|null $token * @param string|null $token
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function showResetForm(Request $request, $invitation_key = null, $token = null) public function showResetForm(Request $request, $key = null, $token = null)
{ {
if (is_null($token)) { if (is_null($token)) {
return $this->getEmail(); return $this->getEmail();
} }
$data = compact('token', 'invitation_key'); $data = compact('token');
$invitation_key = session('invitation_key'); if($key) {
if($invitation_key){ $contact = Contact::where('contact_key', '=', $key)->first();
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first(); if ($contact && !$contact->is_deleted) {
$account = $contact->account;
$data['contact_key'] = $contact->contact_key;
} else {
// Maybe it's an invitation key
$invitation = Invitation::where('invitation_key', '=', $key)->first();
if ($invitation && !$invitation->is_deleted) { if ($invitation && !$invitation->is_deleted) {
$invoice = $invitation->invoice; $account = $invitation->account;
$client = $invoice->client; $data['contact_key'] = $invitation->contact->contact_key;
$account = $client->account; }
}
if (!empty($account)) {
$data['account'] = $account; $data['account'] = $account;
$data['clientFontUrl'] = $account->getFontsUrl(); $data['clientFontUrl'] = $account->getFontsUrl();
} else {
return \Redirect::to('/client/sessionexpired');
} }
} }
@ -131,13 +141,13 @@ class PasswordController extends Controller {
* If no token is present, display the link request form. * If no token is present, display the link request form.
* *
* @param \Illuminate\Http\Request $request * @param \Illuminate\Http\Request $request
* @param string|null $invitation_key * @param string|null $key
* @param string|null $token * @param string|null $token
* @return \Illuminate\Http\Response * @return \Illuminate\Http\Response
*/ */
public function getReset(Request $request, $invitation_key = null, $token = null) public function getReset(Request $request, $key = null, $token = null)
{ {
return $this->showResetForm($request, $invitation_key, $token); return $this->showResetForm($request, $key, $token);
} }
/** /**
@ -156,11 +166,11 @@ class PasswordController extends Controller {
$credentials['id'] = null; $credentials['id'] = null;
$invitation_key = $request->input('invitation_key'); $contactKey = session('contact_key');
if($invitation_key){ if($contactKey){
$invitation = Invitation::where('invitation_key', '=', $invitation_key)->first(); $contact = Contact::where('contact_key', '=', $contactKey)->first();
if ($invitation && !$invitation->is_deleted) { if ($contact && !$contact->is_deleted) {
$credentials['id'] = $invitation->contact_id; $credentials['id'] = $contact->id;
} }
} }

View File

@ -17,6 +17,7 @@ use App\Models\Gateway;
use App\Models\Invitation; use App\Models\Invitation;
use App\Models\Document; use App\Models\Document;
use App\Models\PaymentMethod; use App\Models\PaymentMethod;
use App\Models\Contact;
use App\Ninja\Repositories\InvoiceRepository; use App\Ninja\Repositories\InvoiceRepository;
use App\Ninja\Repositories\PaymentRepository; use App\Ninja\Repositories\PaymentRepository;
use App\Ninja\Repositories\ActivityRepository; use App\Ninja\Repositories\ActivityRepository;
@ -70,7 +71,7 @@ class ClientPortalController extends BaseController
} }
Session::put($invitationKey, true); // track this invitation has been seen Session::put($invitationKey, true); // track this invitation has been seen
Session::put('invitation_key', $invitationKey); // track current invitation Session::put('contact_key', $invitation->contact->contact_key);// track current contact
$account->loadLocalizationSettings($client); $account->loadLocalizationSettings($client);
@ -162,6 +163,18 @@ class ClientPortalController extends BaseController
return View::make('invoices.view', $data); return View::make('invoices.view', $data);
} }
public function contactIndex($contactKey) {
if (!$contact = Contact::where('contact_key', '=', $contactKey)->first()) {
return $this->returnError();
}
$client = $contact->client;
Session::put('contact_key', $contactKey);// track current contact
return redirect()->to($client->account->enable_client_portal?'/client/dashboard':'/client/invoices/');
}
private function getPaymentTypes($client, $invitation) private function getPaymentTypes($client, $invitation)
{ {
$paymentTypes = []; $paymentTypes = [];
@ -277,13 +290,12 @@ class ClientPortalController extends BaseController
public function dashboard() public function dashboard()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$account = $invitation->account; $client = $contact->client;
$invoice = $invitation->invoice; $account = $client->account;
$client = $invoice->client;
$color = $account->primary_color ? $account->primary_color : '#0b4d78'; $color = $account->primary_color ? $account->primary_color : '#0b4d78';
if (!$account->enable_client_portal || !$account->enable_client_portal_dashboard) { if (!$account->enable_client_portal || !$account->enable_client_portal_dashboard) {
@ -310,12 +322,13 @@ class ClientPortalController extends BaseController
public function activityDatatable() public function activityDatatable()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return false; return $this->returnError();
} }
$invoice = $invitation->invoice;
$query = $this->activityRepo->findByClientId($invoice->client_id); $client = $contact->client;
$query = $this->activityRepo->findByClientId($client->id);
$query->where('activities.adjustment', '!=', 0); $query->where('activities.adjustment', '!=', 0);
return Datatable::query($query) return Datatable::query($query)
@ -341,11 +354,11 @@ class ClientPortalController extends BaseController
public function recurringInvoiceIndex() public function recurringInvoiceIndex()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$account = $invitation->account; $account = $contact->account;
if (!$account->enable_client_portal) { if (!$account->enable_client_portal) {
return $this->returnError(); return $this->returnError();
@ -356,7 +369,7 @@ class ClientPortalController extends BaseController
$data = [ $data = [
'color' => $color, 'color' => $color,
'account' => $account, 'account' => $account,
'client' => $invitation->invoice->client, 'client' => $contact->client,
'clientFontUrl' => $account->getFontsUrl(), 'clientFontUrl' => $account->getFontsUrl(),
'title' => trans('texts.recurring_invoices'), 'title' => trans('texts.recurring_invoices'),
'entityType' => ENTITY_RECURRING_INVOICE, 'entityType' => ENTITY_RECURRING_INVOICE,
@ -368,11 +381,11 @@ class ClientPortalController extends BaseController
public function invoiceIndex() public function invoiceIndex()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$account = $invitation->account; $account = $contact->account;
if (!$account->enable_client_portal) { if (!$account->enable_client_portal) {
return $this->returnError(); return $this->returnError();
@ -383,7 +396,7 @@ class ClientPortalController extends BaseController
$data = [ $data = [
'color' => $color, 'color' => $color,
'account' => $account, 'account' => $account,
'client' => $invitation->invoice->client, 'client' => $contact->client,
'clientFontUrl' => $account->getFontsUrl(), 'clientFontUrl' => $account->getFontsUrl(),
'title' => trans('texts.invoices'), 'title' => trans('texts.invoices'),
'entityType' => ENTITY_INVOICE, 'entityType' => ENTITY_INVOICE,
@ -395,29 +408,30 @@ class ClientPortalController extends BaseController
public function invoiceDatatable() public function invoiceDatatable()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return ''; return '';
} }
return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_INVOICE, Input::get('sSearch')); return $this->invoiceRepo->getClientDatatable($contact->id, ENTITY_INVOICE, Input::get('sSearch'));
} }
public function recurringInvoiceDatatable() public function recurringInvoiceDatatable()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return ''; return '';
} }
return $this->invoiceRepo->getClientRecurringDatatable($invitation->contact_id); return $this->invoiceRepo->getClientRecurringDatatable($contact->id);
} }
public function paymentIndex() public function paymentIndex()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$account = $invitation->account;
$account = $contact->account;
if (!$account->enable_client_portal) { if (!$account->enable_client_portal) {
return $this->returnError(); return $this->returnError();
@ -438,10 +452,10 @@ class ClientPortalController extends BaseController
public function paymentDatatable() public function paymentDatatable()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return false; return $this->returnError();
} }
$payments = $this->paymentRepo->findForContact($invitation->contact->id, Input::get('sSearch')); $payments = $this->paymentRepo->findForContact($contact->id, Input::get('sSearch'));
return Datatable::query($payments) return Datatable::query($payments)
->addColumn('invoice_number', function ($model) { return $model->invitation_key ? link_to('/view/'.$model->invitation_key, $model->invoice_number)->toHtml() : $model->invoice_number; }) ->addColumn('invoice_number', function ($model) { return $model->invitation_key ? link_to('/view/'.$model->invitation_key, $model->invoice_number)->toHtml() : $model->invoice_number; })
@ -502,11 +516,11 @@ class ClientPortalController extends BaseController
public function quoteIndex() public function quoteIndex()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$account = $invitation->account; $account = $contact->account;
if (!$account->enable_client_portal) { if (!$account->enable_client_portal) {
return $this->returnError(); return $this->returnError();
@ -528,20 +542,20 @@ class ClientPortalController extends BaseController
public function quoteDatatable() public function quoteDatatable()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return false; return false;
} }
return $this->invoiceRepo->getClientDatatable($invitation->contact_id, ENTITY_QUOTE, Input::get('sSearch')); return $this->invoiceRepo->getClientDatatable($contact->id, ENTITY_QUOTE, Input::get('sSearch'));
} }
public function documentIndex() public function documentIndex()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$account = $invitation->account; $account = $contact->account;
if (!$account->enable_client_portal) { if (!$account->enable_client_portal) {
return $this->returnError(); return $this->returnError();
@ -563,11 +577,11 @@ class ClientPortalController extends BaseController
public function documentDatatable() public function documentDatatable()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return false; return false;
} }
return $this->documentRepo->getClientDatatable($invitation->contact_id, ENTITY_DOCUMENT, Input::get('sSearch')); return $this->documentRepo->getClientDatatable($contact->id, ENTITY_DOCUMENT, Input::get('sSearch'));
} }
private function returnError($error = false) private function returnError($error = false)
@ -578,36 +592,28 @@ class ClientPortalController extends BaseController
]); ]);
} }
private function getInvitation() private function getContact() {
{ $contactKey = session('contact_key');
$invitationKey = session('invitation_key');
if (!$invitationKey) { if (!$contactKey) {
return false; return false;
} }
$invitation = Invitation::where('invitation_key', '=', $invitationKey)->first(); $contact = Contact::where('contact_key', '=', $contactKey)->first();
if (!$invitation || $invitation->is_deleted) { if (!$contact || $contact->is_deleted) {
return false; return false;
} }
$invoice = $invitation->invoice; return $contact;
if (!$invoice || $invoice->is_deleted) {
return false;
}
return $invitation;
} }
public function getDocumentVFSJS($publicId, $name){ public function getDocumentVFSJS($publicId, $name){
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$clientId = $invitation->invoice->client_id; $document = Document::scope($publicId, $contact->account_id)->first();
$document = Document::scope($publicId, $invitation->account_id)->first();
if(!$document->isPDFEmbeddable()){ if(!$document->isPDFEmbeddable()){
@ -615,9 +621,9 @@ class ClientPortalController extends BaseController
} }
$authorized = false; $authorized = false;
if($document->expense && $document->expense->client_id == $invitation->invoice->client_id){ if($document->expense && $document->expense->client_id == $contact->client_id){
$authorized = true; $authorized = true;
} else if($document->invoice && $document->invoice->client_id == $invitation->invoice->client_id){ } else if($document->invoice && $document->invoice->client_id ==$contact->client_id){
$authorized = true; $authorized = true;
} }
@ -692,7 +698,7 @@ class ClientPortalController extends BaseController
return $this->returnError(); return $this->returnError();
} }
Session::put('invitation_key', $invitationKey); // track current invitation Session::put('contact_key', $invitation->contact->contact_key);// track current contact
$invoice = $invitation->invoice; $invoice = $invitation->invoice;
@ -725,7 +731,7 @@ class ClientPortalController extends BaseController
return $this->returnError(); return $this->returnError();
} }
Session::put('invitation_key', $invitationKey); // track current invitation Session::put('contact_key', $invitation->contact->contact_key);// track current contact
$clientId = $invitation->invoice->client_id; $clientId = $invitation->invoice->client_id;
$document = Document::scope($publicId, $invitation->account_id)->firstOrFail(); $document = Document::scope($publicId, $invitation->account_id)->firstOrFail();
@ -746,11 +752,11 @@ class ClientPortalController extends BaseController
public function paymentMethods() public function paymentMethods()
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$client = $invitation->invoice->client; $client = $contact->client;
$account = $client->account; $account = $client->account;
$paymentMethods = $this->paymentService->getClientPaymentMethods($client); $paymentMethods = $this->paymentService->getClientPaymentMethods($client);
@ -780,11 +786,11 @@ class ClientPortalController extends BaseController
$amount1 = Input::get('verification1'); $amount1 = Input::get('verification1');
$amount2 = Input::get('verification2'); $amount2 = Input::get('verification2');
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$client = $invitation->invoice->client; $client = $contact->client;
$result = $this->paymentService->verifyClientPaymentMethod($client, $publicId, $amount1, $amount2); $result = $this->paymentService->verifyClientPaymentMethod($client, $publicId, $amount1, $amount2);
if (is_string($result)) { if (is_string($result)) {
@ -798,11 +804,11 @@ class ClientPortalController extends BaseController
public function removePaymentMethod($publicId) public function removePaymentMethod($publicId)
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$client = $invitation->invoice->client; $client = $contact->client;
$result = $this->paymentService->removeClientPaymentMethod($client, $publicId); $result = $this->paymentService->removeClientPaymentMethod($client, $publicId);
if (is_string($result)) { if (is_string($result)) {
@ -816,17 +822,16 @@ class ClientPortalController extends BaseController
public function addPaymentMethod($paymentType, $token=false) public function addPaymentMethod($paymentType, $token=false)
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$invoice = $invitation->invoice; $client = $contact->client;
$client = $invitation->invoice->client;
$account = $client->account; $account = $client->account;
$typeLink = $paymentType; $typeLink = $paymentType;
$paymentType = 'PAYMENT_TYPE_' . strtoupper($paymentType); $paymentType = 'PAYMENT_TYPE_' . strtoupper($paymentType);
$accountGateway = $invoice->client->account->getTokenGateway(); $accountGateway = $client->account->getTokenGateway();
$gateway = $accountGateway->gateway; $gateway = $accountGateway->gateway;
if ($token && $paymentType == PAYMENT_TYPE_BRAINTREE_PAYPAL) { if ($token && $paymentType == PAYMENT_TYPE_BRAINTREE_PAYPAL) {
@ -846,7 +851,7 @@ class ClientPortalController extends BaseController
$data = [ $data = [
'showBreadcrumbs' => false, 'showBreadcrumbs' => false,
'client' => $client, 'client' => $client,
'contact' => $invitation->contact, 'contact' => $contact,
'gateway' => $gateway, 'gateway' => $gateway,
'accountGateway' => $accountGateway, 'accountGateway' => $accountGateway,
'acceptedCreditCardTypes' => $acceptedCreditCardTypes, 'acceptedCreditCardTypes' => $acceptedCreditCardTypes,
@ -878,13 +883,14 @@ class ClientPortalController extends BaseController
public function postAddPaymentMethod($paymentType) public function postAddPaymentMethod($paymentType)
{ {
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$client = $contact->client;
$typeLink = $paymentType; $typeLink = $paymentType;
$paymentType = 'PAYMENT_TYPE_' . strtoupper($paymentType); $paymentType = 'PAYMENT_TYPE_' . strtoupper($paymentType);
$client = $invitation->invoice->client;
$account = $client->account; $account = $client->account;
$accountGateway = $account->getGatewayByType($paymentType); $accountGateway = $account->getGatewayByType($paymentType);
@ -929,12 +935,13 @@ class ClientPortalController extends BaseController
} }
public function setDefaultPaymentMethod(){ public function setDefaultPaymentMethod(){
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$client = $contact->client;
$validator = Validator::make(Input::all(), array('source' => 'required')); $validator = Validator::make(Input::all(), array('source' => 'required'));
$client = $invitation->invoice->client;
if ($validator->fails()) { if ($validator->fails()) {
return Redirect::to($client->account->enable_client_portal?'/client/dashboard':'/client/paymentmethods/'); return Redirect::to($client->account->enable_client_portal?'/client/dashboard':'/client/paymentmethods/');
} }
@ -963,12 +970,13 @@ class ClientPortalController extends BaseController
} }
public function setAutoBill(){ public function setAutoBill(){
if (!$invitation = $this->getInvitation()) { if (!$contact = $this->getContact()) {
return $this->returnError(); return $this->returnError();
} }
$client = $contact->client;
$validator = Validator::make(Input::all(), array('public_id' => 'required')); $validator = Validator::make(Input::all(), array('public_id' => 'required'));
$client = $invitation->invoice->client;
if ($validator->fails()) { if ($validator->fails()) {
return Redirect::to('client/invoices/recurring'); return Redirect::to('client/invoices/recurring');

View File

@ -20,39 +20,52 @@ class Authenticate {
$authenticated = Auth::guard($guard)->check(); $authenticated = Auth::guard($guard)->check();
if($guard == 'client' && !empty($request->invitation_key)){ if($guard == 'client' && !empty($request->invitation_key)){
$old_key = session('invitation_key'); $contact_key = session('contact_key');
if($old_key && $old_key != $request->invitation_key){ if($contact_key) {
if($this->getInvitationContactId($old_key) != $this->getInvitationContactId($request->invitation_key)){ $contact = $this->getContact($contact_key);
$invitation = $this->getInvitation($request->invitation_key);
if ($contact->id != $invitation->contact_id) {
// This is a different client; reauthenticate // This is a different client; reauthenticate
$authenticated = false; $authenticated = false;
Auth::guard($guard)->logout(); Auth::guard($guard)->logout();
} }
Session::put('contact_key', $contact->contact_key);
} }
Session::put('invitation_key', $request->invitation_key);
} }
if($guard=='client'){ if($guard=='client'){
$invitation_key = session('invitation_key'); if (!empty($request->contact_key)) {
$account_id = $this->getInvitationAccountId($invitation_key); $contact_key = $request->contact_key;
Session::put('contact_key', $contact_key);
} else {
$contact_key = session('contact_key');
}
if(Auth::guard('user')->check() && Auth::user('user')->account_id === $account_id){ if ($contact_key) {
$contact = $this->getContact($contact_key);
$account = $contact->account;
} elseif (!empty($request->invitation_key)) {
$invitation = $this->getInvitation($request->invitation_key);
$account = $invitation->account;
} else {
return \Redirect::to('client/sessionexpired');
}
if(Auth::guard('user')->check() && Auth::user('user')->account_id === $account->id){
// This is an admin; let them pretend to be a client // This is an admin; let them pretend to be a client
$authenticated = true; $authenticated = true;
} }
// Does this account require portal passwords? // Does this account require portal passwords?
$account = Account::whereId($account_id)->first();
if($account && (!$account->enable_portal_password || !$account->hasFeature(FEATURE_CLIENT_PORTAL_PASSWORD))){ if($account && (!$account->enable_portal_password || !$account->hasFeature(FEATURE_CLIENT_PORTAL_PASSWORD))){
$authenticated = true; $authenticated = true;
} }
if(!$authenticated){ if(!$authenticated && $contact && !$contact->password){
$contact = Contact::whereId($this->getInvitationContactId($invitation_key))->first();
if($contact && !$contact->password){
$authenticated = true; $authenticated = true;
} }
} }
}
if (!$authenticated) if (!$authenticated)
{ {
@ -77,15 +90,11 @@ class Authenticate {
else return null; else return null;
} }
protected function getInvitationContactId($key){ protected function getContact($key){
$invitation = $this->getInvitation($key); $contact = Contact::withTrashed()->where('contact_key', '=', $key)->first();
if ($contact && !$contact->is_deleted) {
return $invitation?$invitation->contact_id:null; return $contact;
} }
else return null;
protected function getInvitationAccountId($key){
$invitation = $this->getInvitation($key);
return $invitation?$invitation->account_id:null;
} }
} }

View File

@ -57,6 +57,7 @@ Route::group(['middleware' => 'auth:client'], function() {
Route::get('client/documents', 'ClientPortalController@documentIndex'); Route::get('client/documents', 'ClientPortalController@documentIndex');
Route::get('client/payments', 'ClientPortalController@paymentIndex'); Route::get('client/payments', 'ClientPortalController@paymentIndex');
Route::get('client/dashboard', 'ClientPortalController@dashboard'); Route::get('client/dashboard', 'ClientPortalController@dashboard');
Route::get('client/dashboard/{contact_key}', 'ClientPortalController@contactIndex');
Route::get('client/documents/js/{documents}/{filename}', 'ClientPortalController@getDocumentVFSJS'); Route::get('client/documents/js/{documents}/{filename}', 'ClientPortalController@getDocumentVFSJS');
Route::get('client/documents/{invitation_key}/{documents}/{filename?}', 'ClientPortalController@getDocument'); Route::get('client/documents/{invitation_key}/{documents}/{filename?}', 'ClientPortalController@getDocument');
Route::get('client/documents/{invitation_key}/{filename?}', 'ClientPortalController@getInvoiceDocumentsZip'); Route::get('client/documents/{invitation_key}/{filename?}', 'ClientPortalController@getInvoiceDocumentsZip');
@ -101,6 +102,7 @@ Route::get('/user/confirm/{code}', 'UserController@confirm');
Route::get('/client/login', array('as' => 'login', 'uses' => 'ClientAuth\AuthController@getLogin')); Route::get('/client/login', array('as' => 'login', 'uses' => 'ClientAuth\AuthController@getLogin'));
Route::post('/client/login', array('as' => 'login', 'uses' => 'ClientAuth\AuthController@postLogin')); Route::post('/client/login', array('as' => 'login', 'uses' => 'ClientAuth\AuthController@postLogin'));
Route::get('/client/logout', array('as' => 'logout', 'uses' => 'ClientAuth\AuthController@getLogout')); Route::get('/client/logout', array('as' => 'logout', 'uses' => 'ClientAuth\AuthController@getLogout'));
Route::get('/client/sessionexpired', array('as' => 'logout', 'uses' => 'ClientAuth\AuthController@getSessionExpired'));
Route::get('/client/recover_password', array('as' => 'forgot', 'uses' => 'ClientAuth\PasswordController@getEmail')); Route::get('/client/recover_password', array('as' => 'forgot', 'uses' => 'ClientAuth\PasswordController@getEmail'));
Route::post('/client/recover_password', array('as' => 'forgot', 'uses' => 'ClientAuth\PasswordController@postEmail')); Route::post('/client/recover_password', array('as' => 'forgot', 'uses' => 'ClientAuth\PasswordController@postEmail'));
Route::get('/client/password/reset/{invitation_key}/{token}', array('as' => 'forgot', 'uses' => 'ClientAuth\PasswordController@getReset')); Route::get('/client/password/reset/{invitation_key}/{token}', array('as' => 'forgot', 'uses' => 'ClientAuth\PasswordController@getReset'));

View File

@ -77,4 +77,9 @@ class Contact extends EntityModel implements AuthenticatableContract, CanResetPa
return ''; return '';
} }
} }
public function getLinkAttribute()
{
return \URL::to('client/dashboard/' . $this->contact_key);
}
} }

View File

@ -1311,6 +1311,10 @@ $LANG = array(
'new_start_date' => 'New start date', 'new_start_date' => 'New start date',
'security' => 'Security', 'security' => 'Security',
'see_whats_new' => 'See what\'s new in v:version', 'see_whats_new' => 'See what\'s new in v:version',
'view_dashboard' => 'View Dashboard',
'client_session_expired' => 'Session Expired',
'client_session_expired_message' => 'Your session has expired. Please click the link in your email again.'
); );
return $LANG; return $LANG;

View File

@ -61,7 +61,7 @@
@section('body') @section('body')
<div class="container"> <div class="container">
@include('partials.warn_session', ['redirectTo' => '/client/login']) @include('partials.warn_session', ['redirectTo' => '/client/sessionexpired'])
{!! Former::open('client/login') {!! Former::open('client/login')
->rules(['password' => 'required']) ->rules(['password' => 'required'])

View File

@ -45,6 +45,14 @@
.form-signin .form-control:focus { .form-signin .form-control:focus {
z-index: 2; z-index: 2;
} }
.modal-header a:link,
.modal-header a:visited,
.modal-header a:hover,
.modal-header a:active {
text-decoration: none;
color: white;
}
</style> </style>
@stop @stop

View File

@ -45,6 +45,14 @@
.form-signin .form-control:focus { .form-signin .form-control:focus {
z-index: 2; z-index: 2;
} }
.modal-header a:link,
.modal-header a:visited,
.modal-header a:hover,
.modal-header a:active {
text-decoration: none;
color: white;
}
</style> </style>
@stop @stop
@ -70,7 +78,7 @@
<div class="inner"> <div class="inner">
<input type="hidden" name="token" value="{{{ $token }}}"> <input type="hidden" name="token" value="{{{ $token }}}">
<input type="hidden" name="invitation_key" value="{{{ $invitation_key }}}"> <input type="hidden" name="contact_key" value="{{{ $contact_key }}}">
<p> <p>
{!! Former::password('password')->placeholder(trans('texts.password'))->raw() !!} {!! Former::password('password')->placeholder(trans('texts.password'))->raw() !!}

View File

@ -0,0 +1,79 @@
@extends('public.header')
@section('head')
@parent
<style type="text/css">
body {
padding-top: 40px;
padding-bottom: 40px;
}
.modal-header {
border-top-left-radius: 3px;
border-top-right-radius: 3px;
background:#222;
color:#fff
}
.modal-header h4 {
margin:0;
}
.modal-header img {
float: left;
margin-right: 20px;
}
.form-signin {
max-width: 400px;
margin: 0 auto;
background: #fff;
}
p.link a {
font-size: 11px;
}
.form-signin .inner {
padding: 20px;
border-bottom-right-radius: 3px;
border-bottom-left-radius: 3px;
border-left: 1px solid #ddd;
border-right: 1px solid #ddd;
border-bottom: 1px solid #ddd;
}
.form-signin .checkbox {
font-weight: normal;
}
.form-signin .form-control {
margin-bottom: 17px !important;
}
.form-signin .form-control:focus {
z-index: 2;
}
.modal-header a:link,
.modal-header a:visited,
.modal-header a:hover,
.modal-header a:active {
text-decoration: none;
color: white;
}
</style>
@endsection
@section('body')
<div class="container">
<div class="form-signin">
<div class="modal-header">
@if (!isset($account) || !$account->hasFeature(FEATURE_WHITE_LABEL))
<a href="{{ NINJA_WEB_URL }}" target="_blank">
<img src="{{ asset('images/icon-login.png') }}" />
<h4>Invoice Ninja | {{ trans('texts.client_session_expired') }}</h4>
</a>
@else
<h4>{{ trans('texts.session_expired') }}</h4>
@endif
</div>
<div class="inner">
<div class="alert alert-info">{{ trans('texts.client_session_expired_message') }}</div>
</div>
</div>
</div>
@endsection

View File

@ -146,6 +146,7 @@
@if ($contact->phone) @if ($contact->phone)
<i class="fa fa-phone" style="width: 20px"></i>{{ $contact->phone }}<br/> <i class="fa fa-phone" style="width: 20px"></i>{{ $contact->phone }}<br/>
@endif @endif
<i class="fa fa-dashboard" style="width: 20px"></i><a href="{{ $contact->link }}">{{ trans('texts.view_dashboard') }}</a><br/>
@endforeach @endforeach
</div> </div>

View File

@ -8,7 +8,7 @@
<div> <div>
<center> <center>
@include('partials.email_button', [ @include('partials.email_button', [
'link' => URL::to("client/password/reset/".session('invitation_key')."/{$token}"), 'link' => URL::to("client/password/reset/".session('contact_key')."/{$token}"),
'field' => 'reset', 'field' => 'reset',
'color' => '#36c157', 'color' => '#36c157',
]) ])