Improve user permission support

* Hide links based on permissions
* Restrict editing/creating within other UI
This commit is contained in:
Joshua Dwire 2016-03-15 22:07:11 -04:00
parent 0148d06205
commit 90e1f6695c
21 changed files with 182 additions and 33 deletions

View File

@ -345,10 +345,16 @@ class InvoiceController extends BaseController
*/
public function store(SaveInvoiceWithClientRequest $request)
{
$data = $request->input();
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$action = Input::get('action');
$entityType = Input::get('entityType');
$invoice = $this->invoiceService->save($request->input());
$invoice = $this->invoiceService->save($data, true);
$entityType = $invoice->getEntityType();
$message = trans("texts.created_{$entityType}");
@ -379,10 +385,16 @@ class InvoiceController extends BaseController
*/
public function update(SaveInvoiceWithClientRequest $request)
{
$data = $request->input();
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$action = Input::get('action');
$entityType = Input::get('entityType');
$invoice = $this->invoiceService->save($request->input());
$invoice = $this->invoiceService->save($data, true);
$entityType = $invoice->getEntityType();
$message = trans("texts.updated_{$entityType}");
Session::flash('message', $message);

View File

@ -584,6 +584,11 @@ class PaymentController extends BaseController
public function store(CreatePaymentRequest $request)
{
$input = $request->input();
if(!$this->checkUpdatePermission($input, $response)){
return $response;
}
$input['invoice_id'] = Invoice::getPrivateId($input['invoice']);
$input['client_id'] = Client::getPrivateId($input['client']);
$payment = $this->paymentRepo->save($input);
@ -601,6 +606,11 @@ class PaymentController extends BaseController
public function update(UpdatePaymentRequest $request)
{
$input = $request->input();
if(!$this->checkUpdatePermission($input, $response)){
return $response;
}
$payment = $this->paymentRepo->save($input);
Session::flash('message', trans('texts.updated_payment'));

View File

@ -68,10 +68,6 @@ class TaskController extends BaseController
*/
public function store()
{
if(!$this->checkCreatePermission($response)){
return $response;
}
return $this->save();
}
@ -188,6 +184,12 @@ class TaskController extends BaseController
{
$action = Input::get('action');
$input = $request->input();
if(!$this->checkUpdatePermission($input, $response)){
return $response;
}
if (in_array($action, ['archive', 'delete', 'restore'])) {
return self::bulk();
}

View File

@ -77,7 +77,13 @@ class VendorController extends BaseController
*/
public function store(CreateVendorRequest $request)
{
$vendor = $this->vendorService->save($request->input());
$data = $request->input();
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$vendor = $this->vendorService->save($data);
Session::flash('message', trans('texts.created_vendor'));
@ -195,7 +201,13 @@ class VendorController extends BaseController
*/
public function update(UpdateVendorRequest $request)
{
$vendor = $this->vendorService->save($request->input());
$data = $request->input();
if(!$this->checkUpdatePermission($data, $response)){
return $response;
}
$vendor = $this->vendorService->save($data);
Session::flash('message', trans('texts.updated_vendor'));

View File

@ -134,8 +134,16 @@ class EntityModel extends Eloquent
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::canEdit($this);
return static::canViewItem($this);
}
public static function canViewItem($item) {
@ -149,4 +157,12 @@ class EntityModel extends Eloquent
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

@ -1,5 +1,6 @@
<?php namespace App\Models;
use Auth;
use Illuminate\Database\Eloquent\SoftDeletes;
class Product extends EntityModel

View File

@ -29,6 +29,7 @@ class CreditRepository extends BaseRepository
'credits.public_id',
'clients.name as client_name',
'clients.public_id as client_public_id',
'clients.user_id as client_user_id',
'credits.amount',
'credits.balance',
'credits.credit_date',

View File

@ -81,11 +81,15 @@ class ExpenseRepository extends BaseRepository
'expenses.vendor_id',
'expenses.expense_currency_id',
'expenses.invoice_currency_id',
'expenses.user_id',
'invoices.public_id as invoice_public_id',
'invoices.user_id as invoice_user_id',
'vendors.name as vendor_name',
'vendors.public_id as vendor_public_id',
'vendors.user_id as vendor_user_id',
'clients.name as client_name',
'clients.public_id as client_public_id',
'clients.user_id as client_user_id',
'contacts.first_name',
'contacts.email',
'contacts.last_name',

View File

@ -49,6 +49,7 @@ class InvoiceRepository extends BaseRepository
DB::raw('COALESCE(clients.currency_id, accounts.currency_id) currency_id'),
DB::raw('COALESCE(clients.country_id, accounts.country_id) country_id'),
'clients.public_id as client_public_id',
'clients.user_id as client_user_id',
'invoice_number',
'invoice_status_id',
'clients.name as client_name',
@ -190,7 +191,7 @@ class InvoiceRepository extends BaseRepository
->make();
}
public function save($data)
public function save($data, $checkSubPermissions = false)
{
$account = \Auth::user()->account;
$publicId = isset($data['public_id']) ? $data['public_id'] : false;
@ -406,31 +407,42 @@ 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()){
$task->invoice_id = $invoice->id;
$task->client_id = $invoice->client_id;
$task->save();
}
}
$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()){
$expense->invoice_id = $invoice->id;
$expense->client_id = $invoice->client_id;
$expense->save();
}
}
if ($productKey = trim($item['product_key'])) {
if (\Auth::user()->account->update_products && ! strtotime($productKey)) {
$product = Product::findProductByKey($productKey);
if (!$product) {
if(!$checkSubPermissions || Product::canCreate()){
$product = Product::createNew();
$product->product_key = trim($item['product_key']);
}
else{
$product = null;
}
}
if($product && (!$checkSubPermissions || $product->canEdit())){
$product->notes = ($task || $expense) ? '' : $item['notes'];
$product->cost = $expense ? 0 : $item['cost'];
$product->save();
}
}
}
$invoiceItem = InvoiceItem::createNew();
$invoiceItem->product_id = isset($product) ? $product->id : null;

View File

@ -36,9 +36,11 @@ class PaymentRepository extends BaseRepository
'payments.transaction_reference',
'clients.name as client_name',
'clients.public_id as client_public_id',
'clients.user_id as client_user_id',
'payments.amount',
'payments.payment_date',
'invoices.public_id as invoice_public_id',
'invoices.user_id as invoice_user_id',
'invoices.invoice_number',
'contacts.first_name',
'contacts.last_name',

View File

@ -27,6 +27,7 @@ class TaskRepository
'tasks.public_id',
'clients.name as client_name',
'clients.public_id as client_public_id',
'clients.user_id as client_user_id',
'contacts.first_name',
'contacts.email',
'contacts.last_name',
@ -36,6 +37,7 @@ class TaskRepository
'tasks.deleted_at',
'invoices.invoice_number',
'invoices.public_id as invoice_public_id',
'invoices.user_id as invoice_user_id',
'tasks.is_running',
'tasks.time_log',
'tasks.created_at',

View File

@ -5,6 +5,8 @@ use App\Services\DatatableService;
class BaseService
{
public static $bulk_actions = array('archive', 'restore', 'delete');
use DispatchesJobs;
protected function getRepo()
@ -14,15 +16,17 @@ class BaseService
public function bulk($ids, $action)
{
if ( ! $ids) {
if ( ! $ids || ! in_array($action, static::$bulk_actions) ) {
return 0;
}
$entities = $this->getRepo()->findByPublicIdsWithTrashed($ids);
foreach ($entities as $entity) {
if($entity->canEdit()){
$this->getRepo()->$action($entity);
}
}
return count($entities);
}

View File

@ -3,6 +3,8 @@
use Utils;
use URL;
use App\Services\BaseService;
use App\Models\Client;
use App\Models\Payment;
use App\Ninja\Repositories\CreditRepository;
@ -31,6 +33,10 @@ class CreditService extends BaseService
{
$query = $this->creditRepo->find($clientPublicId, $search);
if(!Utils::hasPermission('view_all')){
$query->where('expenses.user_id', '=', Auth::user()->id);
}
return $this->createDatatable(ENTITY_CREDIT, $query, !$clientPublicId);
}
@ -40,6 +46,10 @@ class CreditService extends BaseService
[
'client_name',
function ($model) {
if(!Client::canViewItemByOwner($model->client_user_id)){
return Utils::getClientDisplayName($model);
}
return $model->client_public_id ? link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml() : '';
},
! $hideClient
@ -78,6 +88,9 @@ class CreditService extends BaseService
trans('texts.apply_credit'),
function ($model) {
return URL::to("payments/create/{$model->client_public_id}") . '?paymentTypeId=1';
},
function ($model) {
return Payment::canCreate();
}
]
];

View File

@ -14,7 +14,9 @@ class DatatableService
if ($actions && $showCheckbox) {
$table->addColumn('checkbox', function ($model) {
return '<input type="checkbox" name="ids[]" value="' . $model->public_id
$can_edit = Auth::user()->hasPermission('edit_all') || (isset($model->user_id) && Auth::user()->id == $model->user_id);
return !$can_edit?'':'<input type="checkbox" name="ids[]" value="' . $model->public_id
. '" ' . Utils::getEntityRowClass($model) . '>';
});
}

View File

@ -70,6 +70,10 @@ class ExpenseService extends BaseService
function ($model)
{
if ($model->vendor_public_id) {
if(!Vendor::canViewItemByOwner($model->vendor_user_id)){
return $model->vendor_name;
}
return link_to("vendors/{$model->vendor_public_id}", $model->vendor_name)->toHtml();
} else {
return '';
@ -81,6 +85,10 @@ class ExpenseService extends BaseService
function ($model)
{
if ($model->client_public_id) {
if(!Client::canViewItemByOwner($model->client_user_id)){
return Utils::getClientDisplayName($model);
}
return link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml();
} else {
return '';
@ -90,6 +98,10 @@ class ExpenseService extends BaseService
[
'expense_date',
function ($model) {
if(!Expense::canEditItemByOwner($model->user_id)){
return Utils::fromSqlDate($model->expense_date);
}
return link_to("expenses/{$model->public_id}/edit", Utils::fromSqlDate($model->expense_date))->toHtml();
}
],
@ -169,7 +181,7 @@ class ExpenseService extends BaseService
return URL::to("/invoices/{$model->invoice_public_id}/edit");
},
function ($model) {
return $model->invoice_public_id && Invoice::canEditItemById($model->invoice_public_id);
return $model->invoice_public_id && Invoice::canEditItemByOwner($model->invoice_user_id);
}
],
[

View File

@ -9,6 +9,7 @@ use App\Ninja\Repositories\ClientRepository;
use App\Events\QuoteInvitationWasApproved;
use App\Models\Invitation;
use App\Models\Invoice;
use App\Models\Client;
use App\Models\Payment;
class InvoiceService extends BaseService
@ -29,14 +30,26 @@ class InvoiceService extends BaseService
return $this->invoiceRepo;
}
public function save($data)
public function save($data, $checkSubPermissions = false)
{
if (isset($data['client'])) {
$can_save_client = !$checkSubPermissions;
if(!$can_save_client){
if(empty($data['client']['public_id']) || $data['client']['public_id']=='-1'){
$can_save_client = Client::canCreate();
}
else{
$can_save_client = Client::wherePublicId($data['client']['public_id'])->first()->canEdit();
}
}
if($can_save_client){
$client = $this->clientRepo->save($data['client']);
$data['client_id'] = $client->id;
}
}
$invoice = $this->invoiceRepo->save($data);
$invoice = $this->invoiceRepo->save($data, $checkSubPermissions);
$client = $invoice->client;
$client->load('contacts');
@ -124,12 +137,19 @@ class InvoiceService extends BaseService
[
'invoice_number',
function ($model) use ($entityType) {
if(!Invoice::canEditItem($model)){
return $model->invoice_number;
}
return link_to("{$entityType}s/{$model->public_id}/edit", $model->invoice_number, ['class' => Utils::getEntityRowClass($model)])->toHtml();
}
],
[
'client_name',
function ($model) {
if(!Client::canViewItemByOwner($model->client_user_id)){
return Utils::getClientDisplayName($model);
}
return link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml();
},
! $hideClient

View File

@ -11,6 +11,8 @@ use CreditCard;
use App\Models\Payment;
use App\Models\Account;
use App\Models\Country;
use App\Models\Client;
use App\Models\Invoice;
use App\Models\AccountGatewayToken;
use App\Ninja\Repositories\PaymentRepository;
use App\Ninja\Repositories\AccountRepository;
@ -300,12 +302,20 @@ class PaymentService extends BaseService
[
'invoice_number',
function ($model) {
if(!Invoice::canEditItemByOwner($model->invoice_user_id)){
return $model->invoice_number;
}
return link_to("invoices/{$model->invoice_public_id}/edit", $model->invoice_number, ['class' => Utils::getEntityRowClass($model)])->toHtml();
}
],
[
'client_name',
function ($model) {
if(!Client::canViewItemByOwner($model->client_user_id)){
return Utils::getClientDisplayName($model);
}
return $model->client_public_id ? link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml() : '';
},
! $hideClient

View File

@ -5,6 +5,7 @@ use URL;
use Utils;
use App\Models\Task;
use App\Models\Invoice;
use App\Models\Client;
use App\Ninja\Repositories\TaskRepository;
use App\Services\BaseService;
@ -48,6 +49,10 @@ class TaskService extends BaseService
[
'client_name',
function ($model) {
if(!Client::canViewItemByOwner($model->client_user_id)){
return Utils::getClientDisplayName($model);
}
return $model->client_public_id ? link_to("clients/{$model->client_public_id}", Utils::getClientDisplayName($model))->toHtml() : '';
},
! $hideClient
@ -97,7 +102,7 @@ class TaskService extends BaseService
return URL::to("/invoices/{$model->invoice_public_id}/edit");
},
function ($model) {
return $model->invoice_number && Invoice::canEditItemById($model->invoice_number);
return $model->invoice_number && Invoice::canEditItemByOwner($model->invoice_user_id);
}
],
[

View File

@ -39,6 +39,10 @@ class VendorService extends BaseService
{
$query = $this->vendorRepo->find($search);
if(!Utils::hasPermission('view_all')){
$query->where('vendors.user_id', '=', Auth::user()->id);
}
return $this->createDatatable(ENTITY_VENDOR, $query);
}

View File

@ -1068,7 +1068,7 @@ $LANG = array(
'administrator' => 'Administrator',
'administrator_help' => 'Allow user to manage users, change settings, and view and modify all data',
'user_create_all' => 'Create clients, invoices, etc.',
'user_view_all' => 'View All clients, invoices, etc.',
'user_view_all' => 'View all clients, invoices, etc.',
'user_edit_all' => 'Edit all clients, invoices, etc.',
);

View File

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