diff --git a/app/Events/Auth/ApiPermissionsAssigning.php b/app/Events/Auth/ApiPermissionsAssigning.php new file mode 100644 index 000000000..c65d76a50 --- /dev/null +++ b/app/Events/Auth/ApiPermissionsAssigning.php @@ -0,0 +1,28 @@ +permission = $permission; + $this->table = $table; + $this->type = $type; + } +} diff --git a/app/Http/Controllers/Api/Common/Contacts.php b/app/Http/Controllers/Api/Common/Contacts.php index 4387dd874..b8ea62159 100644 --- a/app/Http/Controllers/Api/Common/Contacts.php +++ b/app/Http/Controllers/Api/Common/Contacts.php @@ -15,18 +15,6 @@ class Contacts extends ApiController { use Uploads; - /** - * Instantiate a new controller instance. - */ - public function __construct() - { - // Add CRUD permission check - $this->middleware('permission:create-sales-customers')->only('create', 'store', 'duplicate', 'import'); - $this->middleware('permission:read-sales-customers')->only('index', 'show', 'edit', 'export'); - $this->middleware('permission:update-sales-customers')->only('update', 'enable', 'disable'); - $this->middleware('permission:delete-sales-customers')->only('destroy'); - } - /** * Display a listing of the resource. * diff --git a/app/Listeners/Auth/SetPermissionControllerForCommonApiEndpoints.php b/app/Listeners/Auth/SetPermissionControllerForCommonApiEndpoints.php new file mode 100644 index 000000000..c04d50b4a --- /dev/null +++ b/app/Listeners/Auth/SetPermissionControllerForCommonApiEndpoints.php @@ -0,0 +1,54 @@ +table, ['contacts', 'documents', 'transactions'])) { + return; + } + + if ($event->table == 'contacts') { + switch ($event->type) { + case 'customer': + $event->permission->controller = 'sales-customers'; + break; + case 'vendor': + $event->permission->controller = 'purchases-vendors'; + break; + } + } + + if ($event->table == 'documents') { + switch ($event->type) { + case 'invoice': + $event->permission->controller = 'sales-invoices'; + break; + case 'bill': + $event->permission->controller = 'purchases-bills'; + break; + } + } + + if ($event->table == 'transactions') { + switch ($event->type) { + case 'income': + $event->permission->controller = 'sales-revenues'; + break; + case 'expense': + $event->permission->controller = 'purchases-payments'; + break; + } + } + } +} diff --git a/app/Models/Banking/Transaction.php b/app/Models/Banking/Transaction.php index 4fb5a9265..64b8b27df 100644 --- a/app/Models/Banking/Transaction.php +++ b/app/Models/Banking/Transaction.php @@ -4,6 +4,7 @@ namespace App\Models\Banking; use App\Abstracts\Model; use App\Models\Setting\Category; +use App\Scopes\Transaction as Scope; use App\Traits\Currencies; use App\Traits\DateTime; use App\Traits\Media; @@ -52,6 +53,18 @@ class Transaction extends Model */ public $cloneable_relations = ['recurring']; + /** + * The "booting" method of the model. + * + * @return void + */ + protected static function boot() + { + parent::boot(); + + static::addGlobalScope(new Scope); + } + public function account() { return $this->belongsTo('App\Models\Banking\Account')->withDefault(['name' => trans('general.na')]); diff --git a/app/Models/Common/Contact.php b/app/Models/Common/Contact.php index f9e2608d2..0d84f9f68 100644 --- a/app/Models/Common/Contact.php +++ b/app/Models/Common/Contact.php @@ -4,11 +4,12 @@ namespace App\Models\Common; use App\Abstracts\Model; use App\Models\Document\Document; -use Bkwld\Cloner\Cloneable; +use App\Scopes\Contact as Scope; use App\Traits\Contacts; use App\Traits\Currencies; use App\Traits\Media; use App\Traits\Transactions; +use Bkwld\Cloner\Cloneable; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Notifications\Notifiable; @@ -41,6 +42,18 @@ class Contact extends Model */ public $sortable = ['name', 'email', 'phone', 'enabled']; + /** + * The "booting" method of the model. + * + * @return void + */ + protected static function boot() + { + parent::boot(); + + static::addGlobalScope(new Scope); + } + public function documents() { return $this->hasMany('App\Models\Document\Document'); diff --git a/app/Models/Document/Document.php b/app/Models/Document/Document.php index 2b3a9fc85..e56806cad 100644 --- a/app/Models/Document/Document.php +++ b/app/Models/Document/Document.php @@ -3,8 +3,8 @@ namespace App\Models\Document; use App\Abstracts\Model; -use App\Scopes\Document as Scope; use App\Models\Setting\Tax; +use App\Scopes\Document as Scope; use App\Traits\Currencies; use App\Traits\DateTime; use App\Traits\Documents; @@ -15,9 +15,6 @@ use Database\Factories\Document as DocumentFactory; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Factories\Factory; use Illuminate\Database\Eloquent\Factories\HasFactory; -use Illuminate\Database\Eloquent\Relations\BelongsTo; -use Illuminate\Database\Eloquent\Relations\HasMany; -use Illuminate\Database\Eloquent\Relations\MorphOne; class Document extends Model { diff --git a/app/Providers/Event.php b/app/Providers/Event.php index 7981a1051..dd2e3a375 100644 --- a/app/Providers/Event.php +++ b/app/Providers/Event.php @@ -36,6 +36,9 @@ class Event extends Provider 'App\Events\Auth\LandingPageShowing' => [ 'App\Listeners\Auth\AddLandingPages', ], + 'App\Events\Auth\ApiPermissionsAssigning' => [ + 'App\Listeners\Auth\SetPermissionControllerForCommonApiEndpoints', + ], 'App\Events\Document\DocumentCreated' => [ 'App\Listeners\Document\CreateDocumentCreatedHistory', 'App\Listeners\Document\IncreaseNextDocumentNumber', diff --git a/app/Scopes/Company.php b/app/Scopes/Company.php index 025dd9df7..9105f0554 100644 --- a/app/Scopes/Company.php +++ b/app/Scopes/Company.php @@ -2,12 +2,15 @@ namespace App\Scopes; +use App\Traits\Scopes; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Scope; class Company implements Scope { + use Scopes; + /** * Apply the scope to a given Eloquent query builder. * @@ -34,43 +37,11 @@ class Company implements Scope } // Skip if already exists - if ($this->exists($builder, 'company_id')) { + if ($this->scopeExists($builder, 'company_id')) { return; } // Apply company scope $builder->where($table . '.company_id', '=', session('company_id')); } - - /** - * Check if scope exists. - * - * @param \Illuminate\Database\Eloquent\Builder $builder - * @param $column - * @return boolean - */ - protected function exists($builder, $column) - { - $query = $builder->getQuery(); - - foreach ((array) $query->wheres as $key => $where) { - if (empty($where) || empty($where['column'])) { - continue; - } - - if (strstr($where['column'], '.')) { - $whr = explode('.', $where['column']); - - $where['column'] = $whr[1]; - } - - if ($where['column'] != $column) { - continue; - } - - return true; - } - - return false; - } } diff --git a/app/Scopes/Contact.php b/app/Scopes/Contact.php new file mode 100644 index 000000000..99bd2fe53 --- /dev/null +++ b/app/Scopes/Contact.php @@ -0,0 +1,25 @@ +applyTypeScope($builder, $model); + } +} diff --git a/app/Scopes/Document.php b/app/Scopes/Document.php index 59515e5f0..a3874613c 100644 --- a/app/Scopes/Document.php +++ b/app/Scopes/Document.php @@ -2,13 +2,15 @@ namespace App\Scopes; +use App\Traits\Scopes; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; use Illuminate\Database\Eloquent\Scope; -use Illuminate\Support\Str; class Document implements Scope { + use Scopes; + /** * Apply the scope to a given Eloquent query builder. * @@ -18,46 +20,6 @@ class Document implements Scope */ public function apply(Builder $builder, Model $model) { - // Skip if already exists - if ($this->exists($builder, 'type')) { - return; - } - - $type = Str::singular(request()->segment(2, '')); - - // Apply document scope - $builder->where($model->getTable() . '.type', '=', $type); - } - - /** - * Check if scope exists. - * - * @param \Illuminate\Database\Eloquent\Builder $builder - * @param $column - * @return boolean - */ - protected function exists($builder, $column) - { - $query = $builder->getQuery(); - - foreach ((array) $query->wheres as $key => $where) { - if (empty($where) || empty($where['column'])) { - continue; - } - - if (strstr($where['column'], '.')) { - $whr = explode('.', $where['column']); - - $where['column'] = $whr[1]; - } - - if ($where['column'] != $column) { - continue; - } - - return true; - } - - return false; + $this->applyTypeScope($builder, $model); } } diff --git a/app/Scopes/Transaction.php b/app/Scopes/Transaction.php new file mode 100644 index 000000000..1d8e7207c --- /dev/null +++ b/app/Scopes/Transaction.php @@ -0,0 +1,25 @@ +applyTypeScope($builder, $model); + } +} diff --git a/app/Traits/Permissions.php b/app/Traits/Permissions.php index ae34356be..83635e9cd 100644 --- a/app/Traits/Permissions.php +++ b/app/Traits/Permissions.php @@ -2,6 +2,7 @@ namespace App\Traits; +use App\Events\Auth\ApiPermissionsAssigning; use App\Models\Auth\Permission; use App\Models\Auth\Role; use App\Utilities\Reports; @@ -401,34 +402,46 @@ trait Permissions return; } - $route = app(Route::class); + $table = request()->is('api/*') ? request()->segment(2) : ''; - // Get the controller array - $arr = array_reverse(explode('\\', explode('@', $route->getAction()['uses'])[0])); + // Fire event to find the proper controller for common API endpoints + if (in_array($table, ['contacts', 'documents', 'transactions'])) { + $p = new \stdClass(); + $p->controller = ''; - $controller = ''; + event(new ApiPermissionsAssigning($p, $table, request()->get('type'))); - // Add module - if (isset($arr[3]) && isset($arr[4])) { - if (strtolower($arr[4]) == 'modules') { - $controller .= Str::kebab($arr[3]) . '-'; - } elseif (isset($arr[5]) && (strtolower($arr[5]) == 'modules')) { - $controller .= Str::kebab($arr[4]) . '-'; + $controller = $p->controller; + } else { + $route = app(Route::class); + + // Get the controller array + $arr = array_reverse(explode('\\', explode('@', $route->getAction()['uses'])[0])); + + $controller = ''; + + // Add module + if (isset($arr[3]) && isset($arr[4])) { + if (strtolower($arr[4]) == 'modules') { + $controller .= Str::kebab($arr[3]) . '-'; + } elseif (isset($arr[5]) && (strtolower($arr[5]) == 'modules')) { + $controller .= Str::kebab($arr[4]) . '-'; + } } - } - // Add folder - if (strtolower($arr[1]) != 'controllers') { - $controller .= Str::kebab($arr[1]) . '-'; - } + // Add folder + if (strtolower($arr[1]) != 'controllers') { + $controller .= Str::kebab($arr[1]) . '-'; + } - // Add file - $controller .= Str::kebab($arr[0]); + // Add file + $controller .= Str::kebab($arr[0]); - // Skip ACL - $skip = ['portal-dashboard']; - if (in_array($controller, $skip)) { - return; + // Skip ACL + $skip = ['portal-dashboard']; + if (in_array($controller, $skip)) { + return; + } } // App\Http\Controllers\FooBar -->> foo-bar diff --git a/app/Traits/Scopes.php b/app/Traits/Scopes.php new file mode 100644 index 000000000..c688f69d3 --- /dev/null +++ b/app/Traits/Scopes.php @@ -0,0 +1,62 @@ +scopeExists($builder, 'type')) { + return; + } + + $type = request()->get('type') ?: Str::singular(request()->segment(2, '')); + + // Apply type scope + $builder->where($model->getTable() . '.type', '=', $type); + } + + /** + * Check if scope exists. + * + * @param \Illuminate\Database\Eloquent\Builder $builder + * @param $column + * @return boolean + */ + public function scopeExists($builder, $column) + { + $query = $builder->getQuery(); + + foreach ((array) $query->wheres as $key => $where) { + if (empty($where) || empty($where['column'])) { + continue; + } + + if (strstr($where['column'], '.')) { + $whr = explode('.', $where['column']); + + $where['column'] = $whr[1]; + } + + if ($where['column'] != $column) { + continue; + } + + return true; + } + + return false; + } +}