Merge pull request #4 from joshuadwire/laravel-acl

Laravel acl
This commit is contained in:
Joshua Dwire 2016-05-06 14:17:16 -04:00
commit 9ed44bdfe4
45 changed files with 334 additions and 290 deletions

View File

@ -2,13 +2,15 @@
use App\Http\Middleware\PermissionsRequired;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Auth;
use Utils;
class BaseController extends Controller
{
use DispatchesJobs;
use DispatchesJobs, AuthorizesRequests;
protected $model = 'App\Models\EntityModel';
protected $entity;
/**
* Setup the layout used by the controller.
@ -22,39 +24,21 @@ class BaseController extends Controller
}
}
protected function checkViewPermission($object, &$response = null){
if(!$object->canView()){
$response = response('Unauthorized.', 401);
return false;
}
return true;
protected function authorizeCreate() {
$this->authorize('create', $this->entity);
}
protected function checkEditPermission($object, &$response = null){
if(!$object->canEdit()){
$response = response('Unauthorized.', 401);
return false;
}
return true;
}
protected function checkCreatePermission(&$response = null){
if(!call_user_func(array($this->model, 'canCreate'))){
$response = response('Unauthorized.', 401);
return false;
}
return true;
}
protected function checkUpdatePermission($input, &$response = null){
protected function authorizeUpdate($input){
$creating = empty($input['public_id']) || $input['public_id'] == '-1';
if($creating){
return $this->checkCreatePermission($response);
$this->authorize('create', $this->entity);
}
else{
$object = call_user_func(array($this->model, 'scope'), $input['public_id'])->firstOrFail();
return $this->checkEditPermission($object, $response);
$className = Utils::getEntityName($this->entity);
$object = call_user_func(array("App\\Models\\{$className}", 'scope'), $input['public_id'])->firstOrFail();
$this->authorize('edit', $object);
}
}
}

View File

@ -35,7 +35,7 @@ class ClientController extends BaseController
{
protected $clientService;
protected $clientRepo;
protected $model = 'App\Models\Client';
protected $entity = ENTITY_CLIENT;
public function __construct(ClientRepository $clientRepo, ClientService $clientService)
{
@ -83,9 +83,7 @@ class ClientController extends BaseController
{
$data = $request->input();
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$this->authorizeUpdate($data);
$client = $this->clientService->save($data);
@ -104,17 +102,16 @@ class ClientController extends BaseController
{
$client = Client::withTrashed()->scope($publicId)->with('contacts', 'size', 'industry')->firstOrFail();
if(!$this->checkViewPermission($client, $response)){
return $response;
}
$this->authorize('view', $client);
$user = Auth::user();
Utils::trackViewed($client->getDisplayName(), ENTITY_CLIENT);
$actionLinks = [];
if(Task::canCreate()){
if($user->can('create', ENTITY_TASK)){
$actionLinks[] = ['label' => trans('texts.new_task'), 'url' => URL::to('/tasks/create/'.$client->public_id)];
}
if (Utils::hasFeature(FEATURE_QUOTES) && Invoice::canCreate()) {
if (Utils::hasFeature(FEATURE_QUOTES) && $user->can('create', ENTITY_INVOICE)) {
$actionLinks[] = ['label' => trans('texts.new_quote'), 'url' => URL::to('/quotes/create/'.$client->public_id)];
}
@ -122,15 +119,15 @@ class ClientController extends BaseController
$actionLinks[] = \DropdownButton::DIVIDER;
}
if(Payment::canCreate()){
if($user->can('create', ENTITY_PAYMENT)){
$actionLinks[] = ['label' => trans('texts.enter_payment'), 'url' => URL::to('/payments/create/'.$client->public_id)];
}
if(Credit::canCreate()){
if($user->can('create', ENTITY_CREDIT)){
$actionLinks[] = ['label' => trans('texts.enter_credit'), 'url' => URL::to('/credits/create/'.$client->public_id)];
}
if(Expense::canCreate()){
if($user->can('create', ENTITY_EXPENSE)){
$actionLinks[] = ['label' => trans('texts.enter_expense'), 'url' => URL::to('/expenses/create/0/'.$client->public_id)];
}
@ -157,9 +154,7 @@ class ClientController extends BaseController
*/
public function create()
{
if(!$this->checkCreatePermission($response)){
return $response;
}
$this->authorizeCreate();
if (Client::scope()->withTrashed()->count() > Auth::user()->getMaxNumClients()) {
return View::make('error', ['hideHeader' => true, 'error' => "Sorry, you've exceeded the limit of ".Auth::user()->getMaxNumClients()." clients"]);
@ -187,9 +182,7 @@ class ClientController extends BaseController
{
$client = Client::scope($publicId)->with('contacts')->firstOrFail();
if(!$this->checkEditPermission($client, $response)){
return $response;
}
$this->authorize('edit', $client);
$data = [
'client' => $client,
@ -235,9 +228,7 @@ class ClientController extends BaseController
{
$data = $request->input();
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$this->authorizeUpdate($data);
$client = $this->clientService->save($data);

View File

@ -17,7 +17,7 @@ class CreditController extends BaseController
{
protected $creditRepo;
protected $creditService;
protected $model = 'App\Models\Credit';
protected $entity = ENTITY_CREDIT;
public function __construct(CreditRepository $creditRepo, CreditService $creditService)
{
@ -57,9 +57,7 @@ class CreditController extends BaseController
public function create($clientPublicId = 0)
{
if(!$this->checkCreatePermission($response)){
return $response;
}
$this->authorizeCreate();
$data = array(
'clientPublicId' => Input::old('client') ? Input::old('client') : $clientPublicId,
@ -78,9 +76,7 @@ class CreditController extends BaseController
{
$credit = Credit::scope($publicId)->firstOrFail();
if(!$this->checkEditPermission($credit, $response)){
return $response;
}
$this->authorize('edit', $credit);
$credit->credit_date = Utils::fromSqlDate($credit->credit_date);

View File

@ -15,7 +15,7 @@ use App\Ninja\Repositories\DocumentRepository;
class DocumentController extends BaseController
{
protected $documentRepo;
protected $model = 'App\Models\Document';
protected $entity = ENTITY_DOCUMENT;
public function __construct(DocumentRepository $documentRepo)
{
@ -29,9 +29,7 @@ class DocumentController extends BaseController
$document = Document::scope($publicId)
->firstOrFail();
if(!$this->checkViewPermission($document, $response)){
return $response;
}
$this->authorize('view', $document);
return static::getDownloadResponse($document);
}
@ -67,9 +65,7 @@ class DocumentController extends BaseController
$document = Document::scope($publicId)
->firstOrFail();
if(!$this->checkViewPermission($document, $response)){
return $response;
}
$this->authorize('view', $document);
if(empty($document->preview)){
return Response::view('error', array('error'=>'Preview does not exist!'), 404);
@ -95,9 +91,7 @@ class DocumentController extends BaseController
$name = substr($name, 0, -3);
}
if(!$this->checkViewPermission($document, $response)){
return $response;
}
$this->authorize('view', $document);
if(!$document->isPDFEmbeddable()){
return Response::view('error', array('error'=>'Image does not exist!'), 404);
@ -118,9 +112,7 @@ class DocumentController extends BaseController
return;
}
if(!$this->checkCreatePermission($response)){
return $response;
}
$this->authorizeCreate();
$result = $this->documentRepo->upload(Input::all()['file'], $doc_array);

View File

@ -25,7 +25,7 @@ class ExpenseController extends BaseController
// Expenses
protected $expenseRepo;
protected $expenseService;
protected $model = 'App\Models\Expense';
protected $entity = ENTITY_EXPENSE;
public function __construct(ExpenseRepository $expenseRepo, ExpenseService $expenseService)
{
@ -71,9 +71,7 @@ class ExpenseController extends BaseController
public function create($vendorPublicId = null, $clientPublicId = null)
{
if(!$this->checkCreatePermission($response)){
return $response;
}
$this->authorizeCreate();
if($vendorPublicId != 0) {
$vendor = Vendor::scope($vendorPublicId)->with('vendorcontacts')->firstOrFail();
@ -101,9 +99,7 @@ class ExpenseController extends BaseController
{
$expense = Expense::scope($publicId)->with('documents')->firstOrFail();
if(!$this->checkEditPermission($expense, $response)){
return $response;
}
$this->authorize('edit', $expense);
$expense->expense_date = Utils::fromSqlDate($expense->expense_date);
@ -160,9 +156,7 @@ class ExpenseController extends BaseController
$data = $request->input();
$data['documents'] = $request->file('documents');
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$this->authorizeUpdate($data);
$expense = $this->expenseService->save($data, true);
@ -181,9 +175,7 @@ class ExpenseController extends BaseController
$data = $request->input();
$data['documents'] = $request->file('documents');
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$this->authorizeUpdate($data);
$expense = $this->expenseService->save($data);

View File

@ -37,7 +37,7 @@ class InvoiceController extends BaseController
protected $documentRepo;
protected $invoiceService;
protected $recurringInvoiceService;
protected $model = 'App\Models\Invoice';
protected $entity = ENTITY_INVOICE;
public function __construct(Mailer $mailer, InvoiceRepository $invoiceRepo, ClientRepository $clientRepo, InvoiceService $invoiceService, DocumentRepository $documentRepo, RecurringInvoiceService $recurringInvoiceService)
{
@ -96,9 +96,7 @@ class InvoiceController extends BaseController
->withTrashed()
->firstOrFail();
if(!$this->checkEditPermission($invoice, $response)){
return $response;
}
$this->authorize('edit', $invoice);
$entityType = $invoice->getEntityType();
@ -233,9 +231,7 @@ class InvoiceController extends BaseController
public function create($clientPublicId = 0, $isRecurring = false)
{
if(!$this->checkCreatePermission($response)){
return $response;
}
$this->authorizeCreate();
$account = Auth::user()->account;
$entityType = $isRecurring ? ENTITY_RECURRING_INVOICE : ENTITY_INVOICE;
@ -404,9 +400,7 @@ class InvoiceController extends BaseController
$data = $request->input();
$data['documents'] = $request->file('documents');
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$this->authorizeUpdate($data);
$action = Input::get('action');
$entityType = Input::get('entityType');
@ -445,9 +439,7 @@ class InvoiceController extends BaseController
$data = $request->input();
$data['documents'] = $request->file('documents');
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$this->authorizeUpdate($data);
$action = Input::get('action');
$entityType = Input::get('entityType');

View File

@ -32,7 +32,7 @@ use App\Http\Requests\UpdatePaymentRequest;
class PaymentController extends BaseController
{
protected $model = 'App\Models\Payment';
protected $entity = ENTITY_PAYMENT;
public function __construct(PaymentRepository $paymentRepo, InvoiceRepository $invoiceRepo, AccountRepository $accountRepo, ContactMailer $contactMailer, PaymentService $paymentService, UserMailer $userMailer)
{
@ -74,9 +74,7 @@ class PaymentController extends BaseController
public function create($clientPublicId = 0, $invoicePublicId = 0)
{
if(!$this->checkCreatePermission($response)){
return $response;
}
$this->authorizeCreate();
$invoices = Invoice::scope()
->where('is_recurring', '=', false)
@ -105,9 +103,7 @@ class PaymentController extends BaseController
{
$payment = Payment::scope($publicId)->firstOrFail();
if(!$this->checkEditPermission($payment, $response)){
return $response;
}
$this->authorize('edit', $payment);
$payment->payment_date = Utils::fromSqlDate($payment->payment_date);
@ -647,9 +643,7 @@ class PaymentController extends BaseController
{
$input = $request->input();
if(!$this->checkUpdatePermission($input, $response)){
return $response;
}
$this->authorizeUpdate($data);
$input['invoice_id'] = Invoice::getPrivateId($input['invoice']);
$input['client_id'] = Client::getPrivateId($input['client']);
@ -669,9 +663,7 @@ class PaymentController extends BaseController
{
$input = $request->input();
if(!$this->checkUpdatePermission($input, $response)){
return $response;
}
$this->authorizeUpdate($data);
$payment = $this->paymentRepo->save($input);

View File

@ -33,7 +33,7 @@ class QuoteController extends BaseController
protected $invoiceRepo;
protected $clientRepo;
protected $invoiceService;
protected $model = 'App\Models\Invoice';
protected $entity = ENTITY_INVOICE;
public function __construct(Mailer $mailer, InvoiceRepository $invoiceRepo, ClientRepository $clientRepo, InvoiceService $invoiceService)
{
@ -80,9 +80,7 @@ class QuoteController extends BaseController
public function create($clientPublicId = 0)
{
if(!$this->checkCreatePermission($response)){
return $response;
}
$this->authorizeCreate();
if (!Utils::hasFeature(FEATURE_QUOTES)) {
return Redirect::to('/invoices/create');

View File

@ -22,7 +22,7 @@ class TaskController extends BaseController
{
protected $taskRepo;
protected $taskService;
protected $model = 'App\Models\Task';
protected $entity = ENTITY_TASK;
public function __construct(TaskRepository $taskRepo, InvoiceRepository $invoiceRepo, TaskService $taskService)
{
@ -85,9 +85,7 @@ class TaskController extends BaseController
*/
public function create($clientPublicId = 0)
{
if(!$this->checkCreatePermission($response)){
return $response;
}
$this->authorizeCreate();
$this->checkTimezone();
$data = [
@ -117,9 +115,7 @@ class TaskController extends BaseController
$task = Task::scope($publicId)->with('client', 'invoice')->withTrashed()->firstOrFail();
if(!$this->checkEditPermission($task, $response)){
return $response;
}
$this->authorize('edit', $task);
$actions = [];
if ($task->invoice) {
@ -184,9 +180,7 @@ class TaskController extends BaseController
{
$action = Input::get('action');
if(!$this->checkUpdatePermission(array('public_id'=>$publicId)/* Hacky, but works */, $response)){
return $response;
}
$this->authorizeUpdate(array('public_id'=>$publicId)/* Hacky, but works */);
if (in_array($action, ['archive', 'delete', 'restore'])) {
return self::bulk();

View File

@ -30,7 +30,7 @@ class VendorController extends BaseController
{
protected $vendorService;
protected $vendorRepo;
protected $model = 'App\Models\Vendor';
protected $entity = ENTITY_VENDOR;
public function __construct(VendorRepository $vendorRepo, VendorService $vendorService)
{
@ -79,9 +79,7 @@ class VendorController extends BaseController
{
$data = $request->input();
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$this->authorizeUpdate($data);
$vendor = $this->vendorService->save($data);
@ -100,9 +98,7 @@ class VendorController extends BaseController
{
$vendor = Vendor::withTrashed()->scope($publicId)->with('vendorcontacts', 'size', 'industry')->firstOrFail();
if(!$this->checkViewPermission($vendor, $response)){
return $response;
}
$this->authorize('view', $vendor);
Utils::trackViewed($vendor->getDisplayName(), 'vendor');
@ -131,9 +127,7 @@ class VendorController extends BaseController
*/
public function create()
{
if(!$this->checkCreatePermission($response)){
return $response;
}
$this->authorizeCreate();
if (Vendor::scope()->count() > Auth::user()->getMaxNumVendors()) {
return View::make('error', ['hideHeader' => true, 'error' => "Sorry, you've exceeded the limit of ".Auth::user()->getMaxNumVendors()." vendors"]);
@ -161,9 +155,7 @@ class VendorController extends BaseController
{
$vendor = Vendor::scope($publicId)->with('vendorcontacts')->firstOrFail();
if(!$this->checkEditPermission($vendor, $response)){
return $response;
}
$this->authorize('edit', $vendor)
$data = [
'vendor' => $vendor,
@ -203,9 +195,7 @@ class VendorController extends BaseController
{
$data = $request->input();
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$this->authorizeUpdate($data);
$vendor = $this->vendorService->save($data);

View File

@ -222,20 +222,6 @@ class Document extends EntityModel
return $document;
}
public static function canCreate(){
return true;
}
public static function canViewItem($document){
if(Auth::user()->hasPermission('view_all'))return true;
if($document->expense){
if($document->expense->invoice)return $document->expense->invoice->canView();
return $document->expense->canView();
}
if($document->invoice)return $document->invoice->canView();
return Auth::user()->id == $item->user_id;
}
}
Document::deleted(function ($document) {

View File

@ -118,56 +118,4 @@ class EntityModel extends Eloquent
$name = $parts[count($parts)-1];
return strtolower($name) . '_id';
}
public static function canCreate() {
return Auth::user()->hasPermission('create_all');
}
public function canEdit() {
return static::canEditItem($this);
}
public static function canEditItem($item) {
return Auth::user()->hasPermission('edit_all') || (isset($item->user_id) && Auth::user()->id == $item->user_id);
}
public static function canEditItemById($item_id) {
if(Auth::user()->hasPermission('edit_all')) {
return true;
}
return static::whereId($item_id)->first()->user_id == Auth::user()->id;
}
public static function canEditItemByOwner($user_id) {
if(Auth::user()->hasPermission('edit_all')) {
return true;
}
return Auth::user()->id == $user_id;
}
public function canView() {
return static::canViewItem($this);
}
public static function canViewItem($item) {
return Auth::user()->hasPermission('view_all') || (isset($item->user_id) && Auth::user()->id == $item->user_id);
}
public static function canViewItemById($item_id) {
if(Auth::user()->hasPermission('view_all')) {
return true;
}
return static::whereId($item_id)->first()->user_id == Auth::user()->id;
}
public static function canViewItemByOwner($user_id) {
if(Auth::user()->hasPermission('view_all')) {
return true;
}
return Auth::user()->id == $user_id;
}
}

View File

@ -22,8 +22,4 @@ class Product extends EntityModel
{
return $this->belongsTo('App\Models\TaxRate');
}
public function canEdit() {
return Auth::user()->hasPermission('admin');
}
}

View File

@ -17,8 +17,4 @@ class TaxRate extends EntityModel
{
return ENTITY_TAX_RATE;
}
public function canEdit() {
return Auth::user()->hasPermission('admin');
}
}

View File

@ -7,20 +7,22 @@ use App\Libraries\Utils;
use App\Events\UserSettingsChanged;
use App\Events\UserSignedUp;
use Illuminate\Auth\Authenticatable;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Auth\Passwords\CanResetPassword;
use Illuminate\Contracts\Auth\Authenticatable as AuthenticatableContract;
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Database\Eloquent\SoftDeletes;
class User extends Model implements AuthenticatableContract, CanResetPasswordContract {
class User extends Model implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract {
public static $all_permissions = array(
'create_all' => 0b0001,
'view_all' => 0b0010,
'edit_all' => 0b0100,
);
use Authenticatable, CanResetPassword;
use Authenticatable, Authorizable, CanResetPassword;
/**
* The database table used by the model.
@ -326,6 +328,10 @@ class User extends Model implements AuthenticatableContract, CanResetPasswordCon
return false;
}
public function owns($entity) {
return !empty($entity->user_id) && $entity->user_id == $this->id;
}
}
User::updating(function ($user) {

View File

@ -2,6 +2,7 @@
use DB;
use Utils;
use Auth;
use App\Models\Expense;
use App\Models\Vendor;
use App\Models\Document;
@ -159,14 +160,14 @@ class ExpenseRepository extends BaseRepository
$document_ids = !empty($input['document_ids'])?array_map('intval', $input['document_ids']):array();;
foreach ($document_ids as $document_id){
$document = Document::scope($document_id)->first();
if($document && !$checkSubPermissions || $document->canEdit()){
if($document && !$checkSubPermissions || Auth::user()->can('edit', $document)){
$document->invoice_id = null;
$document->expense_id = $expense->id;
$document->save();
}
}
if(!empty($input['documents']) && Document::canCreate()){
if(!empty($input['documents']) && Auth::user()->can('create', ENTITY_DOCUMENT)){
// Fallback upload
$doc_errors = array();
foreach($input['documents'] as $upload){

View File

@ -3,6 +3,7 @@
use DB;
use Utils;
use Session;
use Auth;
use App\Models\Invoice;
use App\Models\InvoiceItem;
use App\Models\Invitation;
@ -475,7 +476,7 @@ class InvoiceRepository extends BaseRepository
$document_ids = !empty($data['document_ids'])?array_map('intval', $data['document_ids']):array();;
foreach ($document_ids as $document_id){
$document = Document::scope($document_id)->first();
if($document && !$checkSubPermissions || $document->canEdit()){
if($document && !$checkSubPermissions || Auth::user()->can('edit', $document)){
if($document->invoice_id && $document->invoice_id != $invoice->id){
// From a clone
@ -489,7 +490,7 @@ class InvoiceRepository extends BaseRepository
}
}
if(!empty($data['documents']) && Document::canCreate()){
if(!empty($data['documents']) && Auth::user()->can('create', ENTITY_DOCUMENT)){
// Fallback upload
$doc_errors = array();
foreach($data['documents'] as $upload){
@ -528,7 +529,7 @@ class InvoiceRepository extends BaseRepository
$task = false;
if (isset($item['task_public_id']) && $item['task_public_id']) {
$task = Task::scope($item['task_public_id'])->where('invoice_id', '=', null)->firstOrFail();
if(!$checkSubPermissions || $task->canEdit()){
if(!$checkSubPermissions || Auth::user()->can('edit', $task)){
$task->invoice_id = $invoice->id;
$task->client_id = $invoice->client_id;
$task->save();
@ -538,7 +539,7 @@ class InvoiceRepository extends BaseRepository
$expense = false;
if (isset($item['expense_public_id']) && $item['expense_public_id']) {
$expense = Expense::scope($item['expense_public_id'])->where('invoice_id', '=', null)->firstOrFail();
if(!$checkSubPermissions || $expense->canEdit()){
if(!$checkSubPermissions || Auth::user()->can('edit', $expense)){
$expense->invoice_id = $invoice->id;
$expense->client_id = $invoice->client_id;
$expense->save();
@ -549,7 +550,7 @@ class InvoiceRepository extends BaseRepository
if (\Auth::user()->account->update_products && ! strtotime($productKey)) {
$product = Product::findProductByKey($productKey);
if (!$product) {
if(!$checkSubPermissions || Product::canCreate()){
if(!$checkSubPermissions || Auth::user()->can('create', ENTITY_PRODUCT)){
$product = Product::createNew();
$product->product_key = trim($item['product_key']);
}
@ -557,7 +558,7 @@ class InvoiceRepository extends BaseRepository
$product = null;
}
}
if($product && (!$checkSubPermissions || $product->canEdit())){
if($product && (!$checkSubPermissions || Auth::user()->can('edit', $product))){
$product->notes = ($task || $expense) ? '' : $item['notes'];
$product->cost = $expense ? 0 : $item['cost'];
$product->save();

View File

@ -0,0 +1,5 @@
<?php
namespace App\Policies;
class ClientPolicy extends EntityPolicy {}

View File

@ -0,0 +1,5 @@
<?php
namespace App\Policies;
class CreditPolicy extends EntityPolicy {}

View File

@ -0,0 +1,20 @@
<?php
namespace App\Policies;
class DocumentPolicy extends EntityPolicy {
public static function create($user){
return !empty($user);
}
public static function view($user, $document) {
if($user->hasPermission('view_all'))return true;
if($document->expense){
if($document->expense->invoice)return $user->can('view', $document->expense->invoice);
return $user->can('view', $document->expense);
}
if($document->invoice)return $user->can('view', $document->invoice);
return $user->owns($item);
}
}

View File

@ -0,0 +1,33 @@
<?php
namespace App\Policies;
use App\Models\User;
use App\Models\EntityModel;
use Illuminate\Auth\Access\HandlesAuthorization;
class EntityPolicy
{
use HandlesAuthorization;
public static function create($user) {
return $user->hasPermission('create_all');
}
public static function edit($user, $item) {
return $user->hasPermission('edit_all') || $user->owns($item);
}
public static function view($user, $item) {
return $user->hasPermission('view_all') || $user->owns($item);
}
public static function viewByOwner($user, $ownerUserId) {
return $user->hasPermission('view_all') || $user->id == $ownerUserId;
}
public static function editByOwner($user, $ownerUserId) {
return $user->hasPermission('edit_all') || $user->id == $ownerUserId;
}
}

View File

@ -0,0 +1,5 @@
<?php
namespace App\Policies;
class ExpensePolicy extends EntityPolicy {}

View File

@ -0,0 +1,40 @@
<?php
namespace App\Policies;
use App\Models\User;
use Utils;
use Illuminate\Auth\Access\HandlesAuthorization;
class GenericEntityPolicy
{
use HandlesAuthorization;
public static function editByOwner($user, $itemType, $ownerUserId) {
$itemType = Utils::getEntityName($itemType);
if (method_exists("App\\Policies\\{$itemType}Policy", 'editByOwner')) {
return call_user_func(array("App\\Policies\\{$itemType}Policy", 'editByOwner'), $user, $ownerUserId);
}
return false;
}
public static function viewByOwner($user, $itemType, $ownerUserId) {
$itemType = Utils::getEntityName($itemType);
if (method_exists("App\\Policies\\{$itemType}Policy", 'viewByOwner')) {
return call_user_func(array("App\\Policies\\{$itemType}Policy", 'viewByOwner'), $user, $ownerUserId);
}
return false;
}
public static function create($user, $itemType) {
$itemType = Utils::getEntityName($itemType);
if (method_exists("App\\Policies\\{$itemType}Policy", 'create')) {
return call_user_func(array("App\\Policies\\{$itemType}Policy", 'create'), $user);
}
return false;
}
}

View File

@ -0,0 +1,5 @@
<?php
namespace App\Policies;
class InvoicePolicy extends EntityPolicy {}

View File

@ -0,0 +1,5 @@
<?php
namespace App\Policies;
class PaymentPolicy extends EntityPolicy {}

View File

@ -0,0 +1,9 @@
<?php
namespace App\Policies;
class VendorPolicy extends EntityPolicy {
public static function edit($user, $item) {
return $user->hasPermission('admin');
}
}

View File

@ -0,0 +1,5 @@
<?php
namespace App\Policies;
class TaskPolicy extends EntityPolicy {}

View File

@ -0,0 +1,9 @@
<?php
namespace App\Policies;
class TaxRatePolicy extends EntityPolicy {
public static function edit($user, $item) {
return $user->hasPermission('admin');
}
}

View File

@ -0,0 +1,5 @@
<?php
namespace App\Policies;
class VendorPolicy extends EntityPolicy {}

View File

@ -54,33 +54,32 @@ class AppServiceProvider extends ServiceProvider {
$Type = ucfirst($type);
$Types = ucfirst($types);
$class = ( Request::is($types) || Request::is('*'.$type.'*')) && !Request::is('*settings*') ? ' active' : '';
$user = Auth::user();
$str = '<li class="dropdown '.$class.'">
<a href="'.URL::to($types).'" class="dropdown-toggle">'.trans("texts.$types").'</a>';
$items = [];
if(Auth::user()->hasPermission('create_all')){
$items[] = '<li><a href="'.URL::to($types.'/create').'">'.trans("texts.new_$type").'</a></li>';
}
if($user->can('create', $type))$items[] = '<li><a href="'.URL::to($types.'/create').'">'.trans("texts.new_$type").'</a></li>';
if ($type == ENTITY_INVOICE) {
if(!empty($items))$items[] = '<li class="divider"></li>';
$items[] = '<li><a href="'.URL::to('recurring_invoices').'">'.trans("texts.recurring_invoices").'</a></li>';
if(Invoice::canCreate())$items[] = '<li><a href="'.URL::to('recurring_invoices/create').'">'.trans("texts.new_recurring_invoice").'</a></li>';
if (Auth::user()->hasFeature(FEATURE_QUOTES)) {
if($user->can('create', ENTITY_INVOICE))$items[] = '<li><a href="'.URL::to('recurring_invoices/create').'">'.trans("texts.new_recurring_invoice").'</a></li>';
if ($user->hasFeature(FEATURE_QUOTES)) {
$items[] = '<li class="divider"></li>';
$items[] = '<li><a href="'.URL::to('quotes').'">'.trans("texts.quotes").'</a></li>';
if(Invoice::canCreate())$items[] = '<li><a href="'.URL::to('quotes/create').'">'.trans("texts.new_quote").'</a></li>';
if($user->can('create', ENTITY_INVOICE))$items[] = '<li><a href="'.URL::to('quotes/create').'">'.trans("texts.new_quote").'</a></li>';
}
} else if ($type == ENTITY_CLIENT) {
if(!empty($items))$items[] = '<li class="divider"></li>';
$items[] = '<li><a href="'.URL::to('credits').'">'.trans("texts.credits").'</a></li>';
if(Credit::canCreate())$items[] = '<li><a href="'.URL::to('credits/create').'">'.trans("texts.new_credit").'</a></li>';
if($user->can('create', ENTITY_CREDIT))$items[] = '<li><a href="'.URL::to('credits/create').'">'.trans("texts.new_credit").'</a></li>';
} else if ($type == ENTITY_EXPENSE) {
if(!empty($items))$items[] = '<li class="divider"></li>';
$items[] = '<li><a href="'.URL::to('vendors').'">'.trans("texts.vendors").'</a></li>';
if(Vendor::canCreate())$items[] = '<li><a href="'.URL::to('vendors/create').'">'.trans("texts.new_vendor").'</a></li>';
if($user->can('create', ENTITY_VENDOR))$items[] = '<li><a href="'.URL::to('vendors/create').'">'.trans("texts.new_vendor").'</a></li>';
}
if(!empty($items)){

View File

@ -0,0 +1,40 @@
<?php
namespace App\Providers;
use Illuminate\Contracts\Auth\Access\Gate as GateContract;
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
class AuthServiceProvider extends ServiceProvider
{
/**
* The policy mappings for the application.
*
* @var array
*/
protected $policies = [
\App\Models\Client::class => \App\Policies\ClientPolicy::class,
\App\Models\Credit::class => \App\Policies\CreditPolicy::class,
\App\Models\Document::class => \App\Policies\DocumentPolicy::class,
\App\Models\Expense::class => \App\Policies\ExpensePolicy::class,
\App\Models\Invoice::class => \App\Policies\InvoicePolicy::class,
\App\Models\Payment::class => \App\Policies\PaymentPolicy::class,
\App\Models\Task::class => \App\Policies\TaskPolicy::class,
\App\Models\Vendor::class => \App\Policies\VendorPolicy::class,
];
/**
* Register any application authentication / authorization services.
*
* @param \Illuminate\Contracts\Auth\Access\Gate $gate
* @return void
*/
public function boot(GateContract $gate)
{
foreach (get_class_methods(new \App\Policies\GenericEntityPolicy) as $method) {
$gate->define($method, "App\Policies\GenericEntityPolicy@{$method}");
}
$this->registerPolicies($gate);
}
}

View File

@ -21,7 +21,7 @@ class BaseService
$entities = $this->getRepo()->findByPublicIdsWithTrashed($ids);
foreach ($entities as $entity) {
if($entity->canEdit()){
if(Auth::user()->can('edit', $entity)){
$this->getRepo()->$action($entity);
}
}

View File

@ -101,13 +101,14 @@ class ClientService extends BaseService
return URL::to("clients/{$model->public_id}/edit");
},
function ($model) {
return Client::canEditItem($model);
return Auth::user()->can('editByOwner', [ENTITY_CLIENT, $model->user_id]);
}
],
[
'--divider--', function(){return false;},
function ($model) {
return Client::canEditItem($model) && (Task::canCreate() || Invoice::canCreate());
$user = Auth::user();
return $user->can('editByOwner', [ENTITY_CLIENT, $model->user_id]) && ($user->can('create', ENTITY_TASK) || $user->can('create', ENTITY_INVOICE));
}
],
[
@ -116,7 +117,7 @@ class ClientService extends BaseService
return URL::to("tasks/create/{$model->public_id}");
},
function ($model) {
return Task::canCreate();
return Auth::user()->can('create', ENTITY_TASK);
}
],
[
@ -125,7 +126,7 @@ class ClientService extends BaseService
return URL::to("invoices/create/{$model->public_id}");
},
function ($model) {
return Invoice::canCreate();
return Auth::user()->can('create', ENTITY_INVOICE);
}
],
[
@ -134,13 +135,14 @@ class ClientService extends BaseService
return URL::to("quotes/create/{$model->public_id}");
},
function ($model) {
return Auth::user()->hasFeature(FEATURE_QUOTES) && Invoice::canCreate();
return Auth::user()->hasFeature(FEATURE_QUOTES) && Auth::user()->can('create', ENTITY_INVOICE);
}
],
[
'--divider--', function(){return false;},
function ($model) {
return (Task::canCreate() || Invoice::canCreate()) && (Payment::canCreate() || Credit::canCreate() || Expense::canCreate());
$user = Auth::user();
return ($user->can('create', ENTITY_TASK) || $user->can('create', ENTITY_INVOICE)) && ($user->can('create', ENTITY_PAYMENT) || $user->can('create', ENTITY_CREDIT) || $user->can('create', ENTITY_EXPENSE));
}
],
[
@ -149,7 +151,7 @@ class ClientService extends BaseService
return URL::to("payments/create/{$model->public_id}");
},
function ($model) {
return Payment::canCreate();
return Auth::user()->can('create', ENTITY_PAYMENT);
}
],
[
@ -158,7 +160,7 @@ class ClientService extends BaseService
return URL::to("credits/create/{$model->public_id}");
},
function ($model) {
return Credit::canCreate();
return Auth::user()->can('create', ENTITY_CREDIT);
}
],
[
@ -167,7 +169,7 @@ class ClientService extends BaseService
return URL::to("expenses/create/0/{$model->public_id}");
},
function ($model) {
return Expense::canCreate();
return Auth::user()->can('create', ENTITY_EXPENSE);
}
]
];

View File

@ -47,7 +47,7 @@ class CreditService extends BaseService
[
'client_name',
function ($model) {
if(!Client::canViewItemByOwner($model->client_user_id)){
if(!Auth::user()->can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])){
return Utils::getClientDisplayName($model);
}
@ -91,7 +91,7 @@ class CreditService extends BaseService
return URL::to("payments/create/{$model->client_public_id}") . '?paymentTypeId=1';
},
function ($model) {
return Payment::canCreate();
return Auth::user()->can('create', ENTITY_PAYMENT);
}
]
];

View File

@ -70,7 +70,7 @@ class ExpenseService extends BaseService
function ($model)
{
if ($model->vendor_public_id) {
if(!Vendor::canViewItemByOwner($model->vendor_user_id)){
if(!Auth::user()->can('viewByOwner', [ENTITY_VENDOR, $model->vendor_user_id])){
return $model->vendor_name;
}
@ -85,7 +85,7 @@ class ExpenseService extends BaseService
function ($model)
{
if ($model->client_public_id) {
if(!Client::canViewItemByOwner($model->client_user_id)){
if(!Auth::user()->can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])){
return Utils::getClientDisplayName($model);
}
@ -98,7 +98,7 @@ class ExpenseService extends BaseService
[
'expense_date',
function ($model) {
if(!Expense::canEditItemByOwner($model->user_id)){
if(!Auth::user()->can('editByOwner', [ENTITY_EXPENSE, $model->user_id])){
return Utils::fromSqlDate($model->expense_date);
}
@ -172,7 +172,7 @@ class ExpenseService extends BaseService
return URL::to("expenses/{$model->public_id}/edit") ;
},
function ($model) {
return Expense::canEditItem($model);
return Auth::user()->can('editByOwner', [ENTITY_EXPENSE, $model->user_id]);
}
],
[
@ -181,7 +181,7 @@ class ExpenseService extends BaseService
return URL::to("/invoices/{$model->invoice_public_id}/edit");
},
function ($model) {
return $model->invoice_public_id && Invoice::canEditItemByOwner($model->invoice_user_id);
return $model->invoice_public_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->invoice_user_id]);
}
],
[
@ -190,7 +190,7 @@ class ExpenseService extends BaseService
return "javascript:invoiceEntity({$model->public_id})";
},
function ($model) {
return ! $model->invoice_id && (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Invoice::canCreate();
return ! $model->invoice_id && (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Auth::user()->can('create', ENTITY_INVOICE);
}
],
];

View File

@ -37,9 +37,9 @@ class InvoiceService extends BaseService
if( ! $canSaveClient){
$clientPublicId = array_get($data, 'client.public_id') ?: array_get($data, 'client.id');
if (empty($clientPublicId) || $clientPublicId == '-1') {
$canSaveClient = Client::canCreate();
$canSaveClient = Auth::user()->can('create', ENTITY_CLIENT);
} else {
$canSaveClient = Client::scope($clientPublicId)->first()->canEdit();
$canSaveClient = Auth::user()->can('edit', Client::scope($clientPublicId)->first());
}
}
@ -137,7 +137,7 @@ class InvoiceService extends BaseService
[
'invoice_number',
function ($model) use ($entityType) {
if(!Invoice::canEditItem($model)){
if(!Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id])){
return $model->invoice_number;
}
@ -147,7 +147,7 @@ class InvoiceService extends BaseService
[
'client_name',
function ($model) {
if(!Client::canViewItemByOwner($model->client_user_id)){
if(!Auth::user()->can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])){
return Utils::getClientDisplayName($model);
}
return link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml();
@ -202,7 +202,7 @@ class InvoiceService extends BaseService
return URL::to("{$entityType}s/{$model->public_id}/edit");
},
function ($model) {
return Invoice::canEditItem($model);
return Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]);
}
],
[
@ -211,7 +211,7 @@ class InvoiceService extends BaseService
return URL::to("{$entityType}s/{$model->public_id}/clone");
},
function ($model) {
return Invoice::canCreate();
return Auth::user()->can('create', ENTITY_INVOICE);
}
],
[
@ -223,7 +223,7 @@ class InvoiceService extends BaseService
[
'--divider--', function(){return false;},
function ($model) {
return Invoice::canEditItem($model) || Payment::canCreate();
return Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]) || Auth::user()->can('create', ENTITY_PAYMENT);
}
],
[
@ -232,7 +232,7 @@ class InvoiceService extends BaseService
return "javascript:markEntity({$model->public_id})";
},
function ($model) {
return $model->invoice_status_id < INVOICE_STATUS_SENT && Invoice::canEditItem($model);
return $model->invoice_status_id < INVOICE_STATUS_SENT && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]);
}
],
[
@ -241,7 +241,7 @@ class InvoiceService extends BaseService
return URL::to("payments/create/{$model->client_public_id}/{$model->public_id}");
},
function ($model) use ($entityType) {
return $entityType == ENTITY_INVOICE && $model->balance > 0 && Payment::canCreate();
return $entityType == ENTITY_INVOICE && $model->balance > 0 && Auth::user()->can('create', ENTITY_PAYMENT);
}
],
[
@ -250,7 +250,7 @@ class InvoiceService extends BaseService
return URL::to("quotes/{$model->quote_id}/edit");
},
function ($model) use ($entityType) {
return $entityType == ENTITY_INVOICE && $model->quote_id && Invoice::canEditItem($model);
return $entityType == ENTITY_INVOICE && $model->quote_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]);
}
],
[
@ -259,7 +259,7 @@ class InvoiceService extends BaseService
return URL::to("invoices/{$model->quote_invoice_id}/edit");
},
function ($model) use ($entityType) {
return $entityType == ENTITY_QUOTE && $model->quote_invoice_id && Invoice::canEditItem($model);
return $entityType == ENTITY_QUOTE && $model->quote_invoice_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]);
}
],
[
@ -268,7 +268,7 @@ class InvoiceService extends BaseService
return "javascript:convertEntity({$model->public_id})";
},
function ($model) use ($entityType) {
return $entityType == ENTITY_QUOTE && ! $model->quote_invoice_id && Invoice::canEditItem($model);
return $entityType == ENTITY_QUOTE && ! $model->quote_invoice_id && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]);
}
]
];

View File

@ -632,7 +632,7 @@ class PaymentService extends BaseService
[
'invoice_number',
function ($model) {
if(!Invoice::canEditItemByOwner($model->invoice_user_id)){
if(!Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->invoice_user_id])){
return $model->invoice_number;
}
@ -642,7 +642,7 @@ class PaymentService extends BaseService
[
'client_name',
function ($model) {
if(!Client::canViewItemByOwner($model->client_user_id)){
if(!Auth::user()->can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])){
return Utils::getClientDisplayName($model);
}
@ -711,7 +711,7 @@ class PaymentService extends BaseService
return URL::to("payments/{$model->public_id}/edit");
},
function ($model) {
return Payment::canEditItem($model);
return Auth::user()->can('editByOwner', [ENTITY_PAYMENT, $model->user_id]);
}
],
[

View File

@ -74,7 +74,7 @@ class RecurringInvoiceService extends BaseService
return URL::to("invoices/{$model->public_id}/edit");
},
function ($model) {
return Invoice::canEditItem($model);
return Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->user_id]);
}
]
];

View File

@ -49,7 +49,7 @@ class TaskService extends BaseService
[
'client_name',
function ($model) {
if(!Client::canViewItemByOwner($model->client_user_id)){
if(!Auth::user()->can('viewByOwner', [ENTITY_CLIENT, $model->client_user_id])){
return Utils::getClientDisplayName($model);
}
@ -93,7 +93,7 @@ class TaskService extends BaseService
return URL::to('tasks/'.$model->public_id.'/edit');
},
function ($model) {
return (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Task::canEditItem($model);
return (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Auth::user()->can('editByOwner', [ENTITY_TASK, $model->user_id]);
}
],
[
@ -102,7 +102,7 @@ class TaskService extends BaseService
return URL::to("/invoices/{$model->invoice_public_id}/edit");
},
function ($model) {
return $model->invoice_number && Invoice::canEditItemByOwner($model->invoice_user_id);
return $model->invoice_number && Auth::user()->can('editByOwner', [ENTITY_INVOICE, $model->invoice_user_id]);
}
],
[
@ -111,7 +111,7 @@ class TaskService extends BaseService
return "javascript:stopTask({$model->public_id})";
},
function ($model) {
return $model->is_running && Task::canEditItem($model);
return $model->is_running && Auth::user()->can('editByOwner', [ENTITY_TASK, $model->user_id]);
}
],
[
@ -120,7 +120,7 @@ class TaskService extends BaseService
return "javascript:invoiceEntity({$model->public_id})";
},
function ($model) {
return ! $model->invoice_number && (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Invoice::canCreate();
return ! $model->invoice_number && (!$model->deleted_at || $model->deleted_at == '0000-00-00') && Auth::user()->can('create', ENTITY_INVOICE);
}
]
];

View File

@ -91,13 +91,13 @@ class VendorService extends BaseService
return URL::to("vendors/{$model->public_id}/edit");
},
function ($model) {
return Vendor::canEditItem($model);
return Auth::user()->can('editByOwner', [ENTITY_VENDOR, $model->user_id]);
}
],
[
'--divider--', function(){return false;},
function ($model) {
return Vendor::canEditItem($model) && Expense::canCreate();
return Auth::user()->can('editByOwner', [ENTITY_VENDOR, $model->user_id]) && Auth::user()->can('create', ENTITY_EXPENSE);
}
],
@ -107,7 +107,7 @@ class VendorService extends BaseService
return URL::to("expenses/create/{$model->public_id}");
},
function ($model) {
return Expense::canCreate();
return Auth::user()->can('create', ENTITY_EXPENSE);
}
]
];

View File

@ -157,6 +157,7 @@ return [
/*
* Application Service Providers...
*/
'App\Providers\AuthServiceProvider',
'App\Providers\AppServiceProvider',
//'App\Providers\BusServiceProvider',
'App\Providers\ConfigServiceProvider',
@ -194,6 +195,7 @@ return [
'Eloquent' => 'Illuminate\Database\Eloquent\Model',
'Event' => 'Illuminate\Support\Facades\Event',
'File' => 'Illuminate\Support\Facades\File',
'Gate' => 'Illuminate\Support\Facades\Gate',
'Hash' => 'Illuminate\Support\Facades\Hash',
'Input' => 'Illuminate\Support\Facades\Input',
'Lang' => 'Illuminate\Support\Facades\Lang',

View File

@ -43,11 +43,11 @@
@endif
@if ($client->trashed())
@if ($client->canEdit())
@can('edit', $client)
{!! Button::primary(trans('texts.restore_client'))->withAttributes(['onclick' => 'onRestoreClick()']) !!}
@endif
@endcan
@else
@if ($client->canEdit())
@can('edit', $client)
{!! DropdownButton::normal(trans('texts.edit_client'))
->withAttributes(['class'=>'normalDropDown'])
->withContents([
@ -55,12 +55,12 @@
['label' => trans('texts.delete_client'), 'url' => "javascript:onDeleteClick()"],
]
)->split() !!}
@endif
@if (\App\Models\Invoice::canCreate())
@endcan
@can('create', ENTITY_INVOICE)
{!! DropdownButton::primary(trans('texts.new_invoice'))
->withAttributes(['class'=>'primaryDropDown'])
->withContents($actionLinks)->split() !!}
@endif
@endcan
@endif
{!! Former::close() !!}

View File

@ -116,11 +116,11 @@
@foreach ($payments as $payment)
<tr>
<td>{!! \App\Models\Invoice::calcLink($payment) !!}</td>
@if (\App\Models\Client::canViewItemByOwner($payment->client_user_id))
@can('viewByOwner', [ENTITY_CLIENT, $payment->client_user_id])
<td>{!! link_to('/clients/'.$payment->client_public_id, trim($payment->client_name) ?: (trim($payment->first_name . ' ' . $payment->last_name) ?: $payment->email)) !!}</td>
@else
<td>{{ trim($payment->client_name) ?: (trim($payment->first_name . ' ' . $payment->last_name) ?: $payment->email) }}</td>
@endif
@endcan
<td>{{ Utils::fromSqlDate($payment->payment_date) }}</td>
<td>{{ Utils::formatMoney($payment->amount, $payment->currency_id ?: ($account->currency_id ?: DEFAULT_CURRENCY)) }}</td>
</tr>
@ -153,11 +153,11 @@
@if (!$invoice->is_quote)
<tr>
<td>{!! \App\Models\Invoice::calcLink($invoice) !!}</td>
@if (\App\Models\Client::canViewItemByOwner($invoice->client_user_id))
@can('viewByOwner', [ENTITY_CLIENT, $invoice->client_user_id])
<td>{!! link_to('/clients/'.$invoice->client_public_id, trim($invoice->client_name) ?: (trim($invoice->first_name . ' ' . $invoice->last_name) ?: $invoice->email)) !!}</td>
@else
<td>{{ trim($invoice->client_name) ?: (trim($invoice->first_name . ' ' . $invoice->last_name) ?: $invoice->email) }}</td>
@endif
@endcan
<td>{{ Utils::fromSqlDate($invoice->due_date) }}</td>
<td>{{ Utils::formatMoney($invoice->balance, $invoice->currency_id ?: ($account->currency_id ?: DEFAULT_CURRENCY)) }}</td>
</tr>
@ -188,11 +188,11 @@
@if (!$invoice->is_quote)
<tr>
<td>{!! \App\Models\Invoice::calcLink($invoice) !!}</td>
@if (\App\Models\Client::canViewItemByOwner($invoice->client_user_id))
@can('viewByOwner', [ENTITY_CLIENT, $invoice->client_user_id])
<td>{!! link_to('/clients/'.$invoice->client_public_id, trim($invoice->client_name) ?: (trim($invoice->first_name . ' ' . $invoice->last_name) ?: $invoice->email)) !!}</td>
@else
<td>{{ trim($invoice->client_name) ?: (trim($invoice->first_name . ' ' . $invoice->last_name) ?: $invoice->email) }}</td>
@endif
@endcan
<td>{{ Utils::fromSqlDate($invoice->due_date) }}</td>
<td>{{ Utils::formatMoney($invoice->balance, $invoice->currency_id ?: ($account->currency_id ?: DEFAULT_CURRENCY)) }}</td>
</tr>

View File

@ -75,12 +75,12 @@
<div class="col-lg-8 col-sm-8">
<h4><div data-bind="text: getClientDisplayName(ko.toJS(client()))"></div></h4>
@if($invoice->client->canView())
@if ($invoice->client->canEdit())
@can('view', $invoice->client)
@can('edit', $invoice->client)
<a id="editClientLink" class="pointer" data-bind="click: $root.showClientForm">{{ trans('texts.edit_client') }}</a> |
@endif
@endcan
{!! link_to('/clients/'.$invoice->client->public_id, trans('texts.view_client'), ['target' => '_blank']) !!}
@endif
@endcan
</div>
</div>
<div style="display:none">

View File

@ -9,14 +9,14 @@
{!! Former::text('public_id') !!}
</div>
@if (\App\Models\Invoice::canCreate())
@can('create', 'invoice')
@if ($entityType == ENTITY_TASK)
{!! Button::primary(trans('texts.invoice'))->withAttributes(['class'=>'invoice', 'onclick' =>'submitForm("invoice")'])->appendIcon(Icon::create('check')) !!}
@endif
@if ($entityType == ENTITY_EXPENSE)
{!! Button::primary(trans('texts.invoice'))->withAttributes(['class'=>'invoice', 'onclick' =>'submitForm("invoice")'])->appendIcon(Icon::create('check')) !!}
@endif
@endif
@endcan
{!! DropdownButton::normal(trans('texts.archive'))->withContents([
['label' => trans('texts.archive_'.$entityType), 'url' => 'javascript:submitForm("archive")'],