feat: ✨ Added marketing role
This commit is contained in:
parent
6f40f7f3a7
commit
43d9d846cf
30 changed files with 1070 additions and 38 deletions
1
.gitignore
vendored
1
.gitignore
vendored
|
|
@ -18,3 +18,4 @@ yarn-error.log
|
||||||
/.idea
|
/.idea
|
||||||
/.vscode
|
/.vscode
|
||||||
auth.json
|
auth.json
|
||||||
|
.npmrc
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ enum RoleEnum: int
|
||||||
|
|
||||||
case conceptor = 1;
|
case conceptor = 1;
|
||||||
case admin = 2;
|
case admin = 2;
|
||||||
|
case marketing = 3;
|
||||||
case visitor = 99;
|
case visitor = 99;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
@ -20,6 +21,7 @@ enum RoleEnum: int
|
||||||
private const LABELS = [
|
private const LABELS = [
|
||||||
self::conceptor->name => 'enums.user-role.conceptor',
|
self::conceptor->name => 'enums.user-role.conceptor',
|
||||||
self::admin->name => 'enums.user-role.admin',
|
self::admin->name => 'enums.user-role.admin',
|
||||||
|
self::marketing->name => 'enums.user-role.marketing',
|
||||||
self::visitor->name => 'enums.user-role.visitor',
|
self::visitor->name => 'enums.user-role.visitor',
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -29,7 +29,9 @@ class StatsController extends Controller
|
||||||
*/
|
*/
|
||||||
public function index(StatsRequest $request): \Illuminate\Contracts\View\View
|
public function index(StatsRequest $request): \Illuminate\Contracts\View\View
|
||||||
{
|
{
|
||||||
$brandModels = Brand::all();
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth('backend')->user();
|
||||||
|
$brandModels = $user->getRelatedBrands();
|
||||||
|
|
||||||
// Check if it's a post request or not to get data.
|
// Check if it's a post request or not to get data.
|
||||||
if ($request->post()) {
|
if ($request->post()) {
|
||||||
|
|
|
||||||
|
|
@ -2,10 +2,10 @@
|
||||||
|
|
||||||
namespace App\Http\Controllers\Bo;
|
namespace App\Http\Controllers\Bo;
|
||||||
|
|
||||||
|
use App\Enums\Users\RoleEnum;
|
||||||
use App\Http\Controllers\Controller;
|
use App\Http\Controllers\Controller;
|
||||||
use App\Http\Requests\Bo\Urls\StoreUrlRequest;
|
use App\Http\Requests\Bo\Urls\StoreUrlRequest;
|
||||||
use App\Http\Requests\Bo\Urls\UpdateUrlRequest;
|
use App\Http\Requests\Bo\Urls\UpdateUrlRequest;
|
||||||
use App\Models\Brand;
|
|
||||||
use App\Models\Url;
|
use App\Models\Url;
|
||||||
use App\Models\UrlHistory;
|
use App\Models\UrlHistory;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
|
@ -24,8 +24,13 @@ class UrlController extends Controller
|
||||||
*/
|
*/
|
||||||
public function index(Request $request)
|
public function index(Request $request)
|
||||||
{
|
{
|
||||||
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth('backend')->user();
|
||||||
|
|
||||||
/** @var \Illuminate\Database\Eloquent\Builder $urls */
|
/** @var \Illuminate\Database\Eloquent\Builder $urls */
|
||||||
$urls = Url::query();
|
$urls = $user->role->equals(RoleEnum::conceptor) ?
|
||||||
|
Url::query() :
|
||||||
|
Url::query()->whereIn('brand_id', $user->brands->pluck('id'));
|
||||||
|
|
||||||
if ($request->search) {
|
if ($request->search) {
|
||||||
$this->searchQuery(
|
$this->searchQuery(
|
||||||
|
|
@ -55,8 +60,12 @@ class UrlController extends Controller
|
||||||
*/
|
*/
|
||||||
public function create(Url $url)
|
public function create(Url $url)
|
||||||
{
|
{
|
||||||
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth('backend')->user();
|
||||||
|
$brandModels = $user->getRelatedBrands();
|
||||||
|
|
||||||
return view('bo.pages.urls.create', [
|
return view('bo.pages.urls.create', [
|
||||||
'brands' => Brand::all(),
|
'brands' => $brandModels,
|
||||||
'urlModel' => $url
|
'urlModel' => $url
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
@ -118,9 +127,13 @@ class UrlController extends Controller
|
||||||
*/
|
*/
|
||||||
public function edit(Url $url)
|
public function edit(Url $url)
|
||||||
{
|
{
|
||||||
|
/** @var \App\Models\User $user */
|
||||||
|
$user = auth('backend')->user();
|
||||||
|
$brandModels = $user->getRelatedBrands();
|
||||||
|
|
||||||
return view('bo.pages.urls.edit', [
|
return view('bo.pages.urls.edit', [
|
||||||
'urlModel' => $url,
|
'urlModel' => $url,
|
||||||
'brands' => Brand::all()
|
'brands' => $brandModels
|
||||||
]);
|
]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
164
app/Http/Controllers/Bo/UserController.php
Normal file
164
app/Http/Controllers/Bo/UserController.php
Normal file
|
|
@ -0,0 +1,164 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Controllers\Bo;
|
||||||
|
|
||||||
|
use App\Http\Controllers\Controller;
|
||||||
|
use App\Http\Requests\Bo\Users\StoreUserRequest;
|
||||||
|
use App\Http\Requests\Bo\Users\UpdateUserRequest;
|
||||||
|
use App\Models\Brand;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Http\Request;
|
||||||
|
use Illuminate\Support\Facades\DB;
|
||||||
|
|
||||||
|
class UserController extends Controller
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Display a listing of the resource.
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Http\Request $request
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||||
|
*/
|
||||||
|
public function index(Request $request)
|
||||||
|
{
|
||||||
|
/** @var \Illuminate\Database\Eloquent\Builder $users */
|
||||||
|
$users = User::query();
|
||||||
|
|
||||||
|
if ($request->search) {
|
||||||
|
$this->searchQuery(
|
||||||
|
$users,
|
||||||
|
$request->search,
|
||||||
|
null,
|
||||||
|
'firstname',
|
||||||
|
'lastname',
|
||||||
|
'email'
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
$this->sortQuery($users);
|
||||||
|
$searchFields = \implode(', ', [
|
||||||
|
trans('validation.custom.firstname'),
|
||||||
|
trans('validation.custom.lastname'),
|
||||||
|
trans('validation.custom.email'),
|
||||||
|
]);
|
||||||
|
|
||||||
|
|
||||||
|
$users = $this->paginate($users);
|
||||||
|
|
||||||
|
return view('bo.pages.users.index', compact('users', 'searchFields'));
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for creating a new resource.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||||
|
*/
|
||||||
|
public function create()
|
||||||
|
{
|
||||||
|
$brandModels = Brand::query()->get();
|
||||||
|
return view('bo.pages.users.create', compact('brandModels'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Store a newly created resource in storage.
|
||||||
|
*
|
||||||
|
* @param \App\Http\Requests\Bo\Users\StoreUserRequest $request
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function store(StoreUserRequest $request)
|
||||||
|
{
|
||||||
|
return DB::transaction(function () use ($request) {
|
||||||
|
$user = new User();
|
||||||
|
$user->fill($request->validated());
|
||||||
|
|
||||||
|
if ($user->saveOrFail()) {
|
||||||
|
$user->brands()->sync(collect($request->brands)->pluck('id'));
|
||||||
|
return redirect()
|
||||||
|
->route('bo.users.edit', $user)
|
||||||
|
->with('success', trans(
|
||||||
|
':model a été créé',
|
||||||
|
['model' => trans('models.classes.user')]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->with('error', trans(
|
||||||
|
':model n\'a pas été créé',
|
||||||
|
['model' => trans('models.classes.user')]
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Show the form for editing the specified resource.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @return \Illuminate\Contracts\View\Factory|\Illuminate\Contracts\View\View
|
||||||
|
*/
|
||||||
|
public function edit(User $user)
|
||||||
|
{
|
||||||
|
$brandModels = Brand::query()->get();
|
||||||
|
return view('bo.pages.users.edit', [
|
||||||
|
'userModel' => $user,
|
||||||
|
'brandModels' => $brandModels
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Update the specified resource in storage.
|
||||||
|
*
|
||||||
|
* @param \App\Http\Requests\Bo\Users\UpdateUserRequest $request
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function update(UpdateUserRequest $request, User $user)
|
||||||
|
{
|
||||||
|
return DB::transaction(function () use ($request, $user) {
|
||||||
|
$user->fill($request->validated());
|
||||||
|
$user->brands()->sync(collect($request->brands)->pluck('id'));
|
||||||
|
if ($user->saveOrFail()) {
|
||||||
|
return redirect()
|
||||||
|
->route('bo.users.edit', $user)
|
||||||
|
->with('success', trans(
|
||||||
|
':model a été mis à jour',
|
||||||
|
['model' => trans('models.classes.user')]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->with('error', trans(
|
||||||
|
':model n\'a pas été mis à jour',
|
||||||
|
['model' => trans('models.classes.user')]
|
||||||
|
));
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Remove the specified resource from storage.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $user
|
||||||
|
* @return \Illuminate\Http\RedirectResponse
|
||||||
|
*/
|
||||||
|
public function destroy(User $user)
|
||||||
|
{
|
||||||
|
if ($user->deleteOrFail()) {
|
||||||
|
return redirect()
|
||||||
|
->route('bo.users.index')
|
||||||
|
->with('warning', trans(
|
||||||
|
':model a bien été supprimé',
|
||||||
|
['model' => trans('models.classes.user')]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
|
||||||
|
return redirect()
|
||||||
|
->back()
|
||||||
|
->with('error', trans(
|
||||||
|
':model n\'a pas été supprimé',
|
||||||
|
['model' => trans('models.classes.user')]
|
||||||
|
));
|
||||||
|
}
|
||||||
|
}
|
||||||
55
app/Http/Requests/Bo/Users/StoreUserRequest.php
Normal file
55
app/Http/Requests/Bo/Users/StoreUserRequest.php
Normal file
|
|
@ -0,0 +1,55 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Bo\Users;
|
||||||
|
|
||||||
|
use App\Enums\Users\RoleEnum;
|
||||||
|
use App\Models\User;
|
||||||
|
use Illuminate\Foundation\Http\FormRequest;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
use Illuminate\Validation\Rules\Enum;
|
||||||
|
|
||||||
|
class StoreUserRequest extends FormRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function authorize()
|
||||||
|
{
|
||||||
|
return Gate::check('create', User::class);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'firstname' => 'required|string|min:3|max:255',
|
||||||
|
'lastname' => 'required|string|min:3|max:255',
|
||||||
|
'email' => 'required|email:rfc,strict,dns,spoof,filter|unique:users,email',
|
||||||
|
'role' => ['required', new Enum(RoleEnum::class)],
|
||||||
|
'brands' => 'nullable|array|min:1',
|
||||||
|
'brands.*' => 'nullable|array',
|
||||||
|
'brands.*.id' => 'nullable|exists:\App\Models\Brand,id',
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get custom attributes for validator errors.
|
||||||
|
*
|
||||||
|
* @return array<string, string>
|
||||||
|
*/
|
||||||
|
public function attributes(): array
|
||||||
|
{
|
||||||
|
return [
|
||||||
|
'first_name' => trans('validation.attributes.first_name'),
|
||||||
|
'last_name' => trans('validation.attributes.last_name'),
|
||||||
|
'email' => trans('validation.attributes.email'),
|
||||||
|
'role' => trans('validation.attributes.role'),
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
52
app/Http/Requests/Bo/Users/UpdateUserRequest.php
Normal file
52
app/Http/Requests/Bo/Users/UpdateUserRequest.php
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Http\Requests\Bo\Users;
|
||||||
|
|
||||||
|
use App\Enums\Users\RoleEnum;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
|
|
||||||
|
class UpdateUserRequest extends StoreUserRequest
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine if the user is authorized to make this request.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function authorize(): bool
|
||||||
|
{
|
||||||
|
return Gate::check('update', $this->route('user'));
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Prepare the data for validation.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
protected function prepareForValidation(): void
|
||||||
|
{
|
||||||
|
/** @var \App\Models\User $user */
|
||||||
|
$user = $this->route('user');
|
||||||
|
if (!$user->role->equals(RoleEnum::conceptor)) {
|
||||||
|
$this->merge(['email' => $user->email]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the validation rules that apply to the request.
|
||||||
|
*
|
||||||
|
* @return array
|
||||||
|
*/
|
||||||
|
public function rules()
|
||||||
|
{
|
||||||
|
/** @var \App\Models\User $user */
|
||||||
|
$user = $this->route('user');
|
||||||
|
return array_merge(parent::rules(), [
|
||||||
|
'email' => [
|
||||||
|
'required',
|
||||||
|
'email:rfc,strict,dns,spoof,filter',
|
||||||
|
Rule::unique('users', 'email')->ignore($user->getRouteKey()),
|
||||||
|
]
|
||||||
|
]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -4,6 +4,7 @@ namespace App\Models;
|
||||||
|
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
|
|
||||||
class Brand extends Model
|
class Brand extends Model
|
||||||
{
|
{
|
||||||
|
|
@ -39,4 +40,16 @@ class Brand extends Model
|
||||||
{
|
{
|
||||||
return $this->hasMany(Service::class);
|
return $this->hasMany(Service::class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The users that belong to the brand.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\User,
|
||||||
|
* $this,
|
||||||
|
* \Illuminate\Database\Eloquent\Relations\Pivot>
|
||||||
|
*/
|
||||||
|
public function users(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(User::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -2,6 +2,7 @@
|
||||||
|
|
||||||
namespace App\Models;
|
namespace App\Models;
|
||||||
|
|
||||||
|
use App\Traits\Models\ActivityLog;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
use Illuminate\Database\Eloquent\Model;
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Uwil\LaravelCommon\Helpers\FileHelper;
|
use Uwil\LaravelCommon\Helpers\FileHelper;
|
||||||
|
|
@ -9,6 +10,7 @@ use Uwil\LaravelCommon\Helpers\FileHelper;
|
||||||
class Url extends Model
|
class Url extends Model
|
||||||
{
|
{
|
||||||
use HasFactory;
|
use HasFactory;
|
||||||
|
use ActivityLog;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The attributes that are mass assignable.
|
* The attributes that are mass assignable.
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@ namespace App\Models;
|
||||||
use App\Enums\Users\RoleEnum;
|
use App\Enums\Users\RoleEnum;
|
||||||
use Illuminate\Auth\Access\AuthorizationException;
|
use Illuminate\Auth\Access\AuthorizationException;
|
||||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||||
|
use Illuminate\Database\Eloquent\Relations\BelongsToMany;
|
||||||
use Illuminate\Foundation\Auth\User as Authenticatable;
|
use Illuminate\Foundation\Auth\User as Authenticatable;
|
||||||
use Illuminate\Notifications\Notifiable;
|
use Illuminate\Notifications\Notifiable;
|
||||||
|
|
||||||
|
|
@ -72,4 +73,33 @@ class User extends Authenticatable
|
||||||
AuthorizationException::class
|
AuthorizationException::class
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get related brands or all the brands if the user is consceptor.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Collection<int, \App\Models\Brand>|
|
||||||
|
* \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\Brand,
|
||||||
|
* $this,
|
||||||
|
* \Illuminate\Database\Eloquent\Relations\Pivot>
|
||||||
|
*/
|
||||||
|
public function getRelatedBrands()
|
||||||
|
{
|
||||||
|
return $this->role->equals(RoleEnum::conceptor) ?
|
||||||
|
Brand::all() :
|
||||||
|
$this->brands;
|
||||||
|
}
|
||||||
|
|
||||||
|
// * RELATIONSHIPS
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The brands that belong to the user.
|
||||||
|
*
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany<\App\Models\Brand,
|
||||||
|
* $this,
|
||||||
|
* \Illuminate\Database\Eloquent\Relations\Pivot>
|
||||||
|
*/
|
||||||
|
public function brands(): BelongsToMany
|
||||||
|
{
|
||||||
|
return $this->belongsToMany(Brand::class);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
|
||||||
65
app/Policies/BrandPolicy.php
Normal file
65
app/Policies/BrandPolicy.php
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Enums\Users\RoleEnum;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Policies\Rules\UserStaticRules;
|
||||||
|
|
||||||
|
class BrandPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function viewAny(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function view(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create a new model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function create(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function update(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function delete(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
47
app/Policies/Rules/UserStaticRules.php
Normal file
47
app/Policies/Rules/UserStaticRules.php
Normal file
|
|
@ -0,0 +1,47 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies\Rules;
|
||||||
|
|
||||||
|
use App\Enums\Users\RoleEnum;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Userlevel Policiy Static Rules
|
||||||
|
*
|
||||||
|
* @codeCoverageIgnore
|
||||||
|
*/
|
||||||
|
abstract class UserStaticRules
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Allow everyone.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function everyOne(): bool
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Allow no one.
|
||||||
|
*
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function noOne(): bool
|
||||||
|
{
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* At least a minimum role
|
||||||
|
*
|
||||||
|
* @param \Illuminate\Database\Eloquent\Model $authModel
|
||||||
|
* @param \App\Enums\Users\RoleEnum $minRole
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public static function atLeastRole(Model $authModel, RoleEnum $minRole): bool
|
||||||
|
{
|
||||||
|
// phpcs:enable
|
||||||
|
return isset($authModel->role) && $authModel->role->value() <= $minRole->value();
|
||||||
|
}
|
||||||
|
}
|
||||||
65
app/Policies/ServicePolicy.php
Normal file
65
app/Policies/ServicePolicy.php
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Enums\Users\RoleEnum;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Policies\Rules\UserStaticRules;
|
||||||
|
|
||||||
|
class ServicePolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function viewAny(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function view(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create a new model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function create(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function update(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function delete(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
72
app/Policies/UrlPolicy.php
Normal file
72
app/Policies/UrlPolicy.php
Normal file
|
|
@ -0,0 +1,72 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Enums\Users\RoleEnum;
|
||||||
|
use App\Models\Url;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Policies\Rules\UserStaticRules;
|
||||||
|
|
||||||
|
class UrlPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function viewAny(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @param \App\Models\Url $url
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function view(User $authUser, Url $url): bool
|
||||||
|
{
|
||||||
|
return (UserStaticRules::atLeastRole($authUser, RoleEnum::marketing) &&
|
||||||
|
\collect($authUser->brands->pluck('id'))->contains($url->brand->id)) ||
|
||||||
|
UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create a new model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function create(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @param \App\Models\Url $url
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function update(User $authUser, Url $url): bool
|
||||||
|
{
|
||||||
|
return (UserStaticRules::atLeastRole($authUser, RoleEnum::marketing) &&
|
||||||
|
\collect($authUser->brands->pluck('id'))->contains($url->brand->id)) ||
|
||||||
|
UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function delete(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
65
app/Policies/UserPolicy.php
Normal file
65
app/Policies/UserPolicy.php
Normal file
|
|
@ -0,0 +1,65 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
namespace App\Policies;
|
||||||
|
|
||||||
|
use App\Enums\Users\RoleEnum;
|
||||||
|
use App\Models\User;
|
||||||
|
use App\Policies\Rules\UserStaticRules;
|
||||||
|
|
||||||
|
class UserPolicy
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view any models.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function viewAny(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can view the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function view(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can create a new model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function create(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can update the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function update(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Determine whether the user can delete the model.
|
||||||
|
*
|
||||||
|
* @param \App\Models\User $authUser
|
||||||
|
* @return boolean
|
||||||
|
*/
|
||||||
|
public function delete(User $authUser): bool
|
||||||
|
{
|
||||||
|
return UserStaticRules::atLeastRole($authUser, RoleEnum::conceptor);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -2,11 +2,14 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Enums\Users\RoleEnum;
|
||||||
use App\Models\Service;
|
use App\Models\Service;
|
||||||
|
use Illuminate\Database\Eloquent\Model;
|
||||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||||
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
|
use Illuminate\Support\Facades\Gate;
|
||||||
|
|
||||||
class AuthServiceProvider extends ServiceProvider
|
class AuthServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
|
|
@ -19,6 +22,10 @@ class AuthServiceProvider extends ServiceProvider
|
||||||
{
|
{
|
||||||
$this->registerPolicies();
|
$this->registerPolicies();
|
||||||
|
|
||||||
|
Gate::define('isConceptor', function (Model $authModel) {
|
||||||
|
return isset($authModel->role) && $authModel->role === RoleEnum::conceptor;
|
||||||
|
});
|
||||||
|
|
||||||
Auth::viaRequest('api-hmac', function (Request $request) {
|
Auth::viaRequest('api-hmac', function (Request $request) {
|
||||||
$service = null;
|
$service = null;
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,27 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
return new class extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*/
|
||||||
|
public function up(): void
|
||||||
|
{
|
||||||
|
Schema::create('brand_user', function (Blueprint $table) {
|
||||||
|
$table->foreignId('brand_id')->constrained();
|
||||||
|
$table->foreignId('user_id')->constrained();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*/
|
||||||
|
public function down(): void
|
||||||
|
{
|
||||||
|
Schema::dropIfExists('brand_user');
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
@ -4,6 +4,7 @@ return [
|
||||||
'user-role' => [
|
'user-role' => [
|
||||||
"conceptor" => "conceptor",
|
"conceptor" => "conceptor",
|
||||||
"admin" => "admin",
|
"admin" => "admin",
|
||||||
|
"marketing" => "marketing",
|
||||||
"visitor" => "visitor",
|
"visitor" => "visitor",
|
||||||
],
|
],
|
||||||
'draft' => 'Draft',
|
'draft' => 'Draft',
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,8 @@ return [
|
||||||
'timeslots' => 'Collection time slots',
|
'timeslots' => 'Collection time slots',
|
||||||
'orders' => 'Orders',
|
'orders' => 'Orders',
|
||||||
'contacts' => 'Contact messages',
|
'contacts' => 'Contact messages',
|
||||||
|
'user' => 'user',
|
||||||
|
'brand' => 'brand',
|
||||||
'activity_log' => 'activity log|activity logs'
|
'activity_log' => 'activity log|activity logs'
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -4,6 +4,7 @@ return [
|
||||||
'user-role' => [
|
'user-role' => [
|
||||||
"conceptor" => "concepteur",
|
"conceptor" => "concepteur",
|
||||||
"admin" => "administrateur",
|
"admin" => "administrateur",
|
||||||
|
"marketing" => "marketing",
|
||||||
"visitor" => "visiteur",
|
"visitor" => "visiteur",
|
||||||
],
|
],
|
||||||
'draft' => 'Brouillon',
|
'draft' => 'Brouillon',
|
||||||
|
|
|
||||||
|
|
@ -22,6 +22,8 @@ return [
|
||||||
'brands' => 'Marques',
|
'brands' => 'Marques',
|
||||||
'urls' => 'URLs',
|
'urls' => 'URLs',
|
||||||
'services' => 'Services',
|
'services' => 'Services',
|
||||||
|
'user' => 'utilisateur',
|
||||||
|
'brand' => 'marque',
|
||||||
'activity_log' => 'journal d\'activité|journaux d\'activité'
|
'activity_log' => 'journal d\'activité|journaux d\'activité'
|
||||||
]
|
]
|
||||||
];
|
];
|
||||||
|
|
|
||||||
|
|
@ -117,7 +117,11 @@ return [
|
||||||
'uploaded' => 'Le fichier du champ :attribute n\'a pu être téléversé.',
|
'uploaded' => 'Le fichier du champ :attribute n\'a pu être téléversé.',
|
||||||
'url' => 'Le format de l\'URL de :attribute n\'est pas valide.',
|
'url' => 'Le format de l\'URL de :attribute n\'est pas valide.',
|
||||||
'uuid' => 'Le champ :attribute doit être un UUID valide',
|
'uuid' => 'Le champ :attribute doit être un UUID valide',
|
||||||
'custom' => [],
|
'custom' => [
|
||||||
|
'firstname' => 'Prénom',
|
||||||
|
'lastname' => 'Nom',
|
||||||
|
'email' => 'Adresse email',
|
||||||
|
],
|
||||||
'phone' => 'Le champ :attribute n\'est pas un numéro de téléphone valide.',
|
'phone' => 'Le champ :attribute n\'est pas un numéro de téléphone valide.',
|
||||||
'color' => ':attribute doit être un code couleur valide (hexadecimal, RGB, RGBA ou un nom de couleur CSS)',
|
'color' => ':attribute doit être un code couleur valide (hexadecimal, RGB, RGBA ou un nom de couleur CSS)',
|
||||||
'color_hex' => ':attribute doit être un code couleur hexadecimal valide',
|
'color_hex' => ':attribute doit être un code couleur hexadecimal valide',
|
||||||
|
|
|
||||||
|
|
@ -6,29 +6,55 @@
|
||||||
{{ __('Dashboard') }}
|
{{ __('Dashboard') }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
|
@can('isConceptor')
|
||||||
|
<li class="nav-item">
|
||||||
|
<a @class([
|
||||||
|
'nav-link d-flex align-items-center h-100',
|
||||||
|
'active' => request()->routeIs('bo.activity_logs.*'),
|
||||||
|
])
|
||||||
|
data-bs-toggle="tooltip" href="{{ route('bo.activity_logs.index') }}"
|
||||||
|
title="{{ __('crud.helpers.list_all', ['model' => trans_choice('models.classes.activity_log', \INF)]) }}">
|
||||||
|
{{ str(trans_choice('models.classes.activity_log', \INF))->ucfirst() }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
@endcan
|
||||||
<li class="nav-item">
|
<li class="nav-item">
|
||||||
<a class="nav-link @if (request()->routeIs('bo.stats.*')) active @endif" data-bs-toggle="tooltip" href="{{ route('bo.stats.index') }}"
|
<a class="nav-link @if (request()->routeIs('bo.stats.*')) active @endif" data-bs-toggle="tooltip" href="{{ route('bo.stats.index') }}"
|
||||||
title="{{ __('Accéder aux statistiques') }}">
|
title="{{ __('Accéder aux statistiques') }}">
|
||||||
{{ __('Stats') }}
|
{{ __('Stats') }}
|
||||||
</a>
|
</a>
|
||||||
</li>
|
</li>
|
||||||
<li class="nav-item">
|
@canAny(['viewAny', 'create', 'update', 'delete'], \App\Models\Brand::class)
|
||||||
<a class="nav-link @if (request()->routeIs('bo.brands.*')) active @endif" data-bs-toggle="tooltip" href="{{ route('bo.brands.index') }}"
|
<li class="nav-item">
|
||||||
title="{{ __('Accéder à la liste des marques') }}">
|
<a class="nav-link @if (request()->routeIs('bo.brands.*')) active @endif" data-bs-toggle="tooltip" href="{{ route('bo.brands.index') }}"
|
||||||
{{ __('models.classes.brands') }}
|
title="{{ __('Accéder à la liste des marques') }}">
|
||||||
</a>
|
{{ __('models.classes.brands') }}
|
||||||
</li>
|
</a>
|
||||||
<li class="nav-item">
|
</li>
|
||||||
<a class="nav-link @if (request()->routeIs('bo.urls.*')) active @endif" data-bs-toggle="tooltip" href="{{ route('bo.urls.index') }}"
|
@endcan
|
||||||
title="{{ __('Accéder à la liste des urls') }}">
|
@canAny(['viewAny', 'create', 'update', 'delete'], \App\Models\Brand::class)
|
||||||
{{ __('models.classes.urls') }}
|
<li class="nav-item">
|
||||||
</a>
|
<a class="nav-link @if (request()->routeIs('bo.urls.*')) active @endif" data-bs-toggle="tooltip" href="{{ route('bo.urls.index') }}"
|
||||||
</li>
|
title="{{ __('Accéder à la liste des urls') }}">
|
||||||
<li class="nav-item">
|
{{ __('models.classes.urls') }}
|
||||||
<a class="nav-link @if (request()->routeIs('bo.services.*')) active @endif" data-bs-toggle="tooltip"
|
</a>
|
||||||
href="{{ route('bo.services.index') }}" title="{{ __('Accéder à la liste des services') }}">
|
</li>
|
||||||
{{ __('models.classes.services') }}
|
@endcan
|
||||||
</a>
|
@canAny(['viewAny', 'create', 'update', 'delete'], \App\Models\Service::class)
|
||||||
</li>
|
<li class="nav-item">
|
||||||
|
<a class="nav-link @if (request()->routeIs('bo.services.*')) active @endif" data-bs-toggle="tooltip"
|
||||||
|
href="{{ route('bo.services.index') }}" title="{{ __('Accéder à la liste des services') }}">
|
||||||
|
{{ __('models.classes.services') }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
@endcan
|
||||||
|
@canAny(['viewAny', 'create', 'update', 'delete'], \App\Models\User::class)
|
||||||
|
<li class="nav-item">
|
||||||
|
<a class="nav-link @if (request()->routeIs('bo.users.*')) active @endif" data-bs-toggle="tooltip"
|
||||||
|
href="{{ route('bo.users.index') }}" title="{{ __('Accéder à la liste des users') }}">
|
||||||
|
{{ str(__('models.classes.user'))->plural()->ucfirst() }}
|
||||||
|
</a>
|
||||||
|
</li>
|
||||||
|
@endcan
|
||||||
</ul>
|
</ul>
|
||||||
@endauth
|
@endauth
|
||||||
|
|
|
||||||
31
resources/views/bo/pages/users/create.blade.php
Normal file
31
resources/views/bo/pages/users/create.blade.php
Normal file
|
|
@ -0,0 +1,31 @@
|
||||||
|
@extends('bo.layout')
|
||||||
|
|
||||||
|
@section('title', sprintf('%s - %s', str(__('models.classes.user'))->plural()->ucfirst(), Str::ucfirst(__('création'))))
|
||||||
|
|
||||||
|
@section('breadcrumb', request()->route()->getName())
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="row">
|
||||||
|
<h1 class="col h4">
|
||||||
|
<a href="{{ route('bo.users.index') }}" class="text-decoration-none btn btn-sm btn-primary" role="button" aria-roledescription="{{ __('Revenir en arrière') }}"><i class="fa-solid fa-arrow-left-long"></i></a>
|
||||||
|
<span> {{ str(__('models.classes.user'))->plural()->ucfirst() }} {{ __('création') }}</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form action="{{ route('bo.users.store') }}" method="POST">
|
||||||
|
@csrf
|
||||||
|
@include('bo.pages.users.form')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col text-center text-md-end">
|
||||||
|
<button type="submit" class="btn btn-primary" title="{{ __('Enregister :model', [
|
||||||
|
'model' => str(__('models.classes.user'))->ucfirst(),
|
||||||
|
]) }}" data-bs-toggle="tooltip">{{ __('Enregister') }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
58
resources/views/bo/pages/users/edit.blade.php
Normal file
58
resources/views/bo/pages/users/edit.blade.php
Normal file
|
|
@ -0,0 +1,58 @@
|
||||||
|
@extends('bo.layout', ['brParam' => $userModel])
|
||||||
|
|
||||||
|
@section('title', sprintf('%s - %s %s', str(__('models.classes.user'))->plural()->ucfirst(), Str::ucfirst(__('édition')), $userModel->lastname))
|
||||||
|
|
||||||
|
@section('breadcrumb', request()->route()->getName())
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h1 class="col h4">
|
||||||
|
<a href="{{ route('bo.users.index') }}" class="text-decoration-none btn btn-sm btn-primary" role="button" aria-roledescription="{{ __('Revenir en arrière') }}">
|
||||||
|
<i class="fa-solid fa-arrow-left-long"></i>
|
||||||
|
</a>
|
||||||
|
<span> {{ str(__('models.classes.user'))->plural()->ucfirst() }} {{ __('édition') }}</span>
|
||||||
|
</h1>
|
||||||
|
</div>
|
||||||
|
<div class="col text-end">
|
||||||
|
<form action="{{ route('bo.users.destroy', $userModel->id) }}" method="POST" class="d-inline confirmDeleteJS">
|
||||||
|
@method('DELETE')
|
||||||
|
@csrf
|
||||||
|
<div class="btn-group" role="group">
|
||||||
|
<button class="btn btn-danger" title="{{ __('Supprimer :model', [
|
||||||
|
'model' => str(__('models.classes.user'))->ucfirst(),
|
||||||
|
]) }}" data-bs-toggle="tooltip">
|
||||||
|
<i class="fa-solid fa-trash"></i>
|
||||||
|
</button>
|
||||||
|
<a id="formSubmitClone" class="btn btn-primary" role="button" title="{{ __('Enregistrer :model', [
|
||||||
|
'model' => str(__('models.classes.user'))->ucfirst(),
|
||||||
|
]) }}" data-bs-toggle="tooltip">{{ __('Enregistrer') }}</a>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
<form id="formSubmit" action="{{ route('bo.users.update', $userModel->id) }}" method="POST">
|
||||||
|
@csrf
|
||||||
|
@method('PUT')
|
||||||
|
@include('bo.pages.users.form', compact('userModel'))
|
||||||
|
|
||||||
|
<div class="row my-3">
|
||||||
|
<div class="col text-center">
|
||||||
|
<strong>* {{ __('champs obligatoires') }}</strong>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col text-center text-md-end">
|
||||||
|
<button type="submit" class="btn btn-primary" title="{{ __('Enregister :model', [
|
||||||
|
'model' => str(__('models.classes.user'))->ucfirst(),
|
||||||
|
]) }}" data-bs-toggle="tooltip">{{ __('Enregister') }}</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
108
resources/views/bo/pages/users/form.blade.php
Normal file
108
resources/views/bo/pages/users/form.blade.php
Normal file
|
|
@ -0,0 +1,108 @@
|
||||||
|
<div class="row">
|
||||||
|
{{-- LASTNAME --}}
|
||||||
|
<div class="col-12 col-md-6 mb-3">
|
||||||
|
<fieldset class="border p-3">
|
||||||
|
<legend>{{ __('validation.custom.lastname') }} </legend>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mb-3">
|
||||||
|
@include('bo.partials.inputs.varchar', [
|
||||||
|
'id' => 'userLastname',
|
||||||
|
'hasWordCounter' => true,
|
||||||
|
'name' => 'lastname',
|
||||||
|
'required' => true,
|
||||||
|
'model' => $userModel ?? null,
|
||||||
|
'helper' => __('Nom (3 caractères minimum, 255 maximum).'),
|
||||||
|
'placeholder' => "Dupont"
|
||||||
|
])
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
{{-- FIRSTNAME --}}
|
||||||
|
<div class="col-12 col-md-6 mb-3">
|
||||||
|
<fieldset class="border p-3">
|
||||||
|
<legend>{{ __('validation.custom.firstname') }} </legend>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mb-3">
|
||||||
|
@include('bo.partials.inputs.varchar', [
|
||||||
|
'id' => 'userFirstname',
|
||||||
|
'hasWordCounter' => true,
|
||||||
|
'name' => 'firstname',
|
||||||
|
'required' => true,
|
||||||
|
'model' => $userModel ?? null,
|
||||||
|
'helper' => __('Prénom (3 caractères minimum, 255 maximum).'),
|
||||||
|
'placeholder' => "Jean"
|
||||||
|
])
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
{{-- EMAIL --}}
|
||||||
|
<div class="col-12 col-md-6">
|
||||||
|
<fieldset class="border p-3">
|
||||||
|
<legend>{{ __('validation.custom.email') }} </legend>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mb-3">
|
||||||
|
@include('bo.partials.inputs.varchar-email', [
|
||||||
|
'id' => 'userEmail',
|
||||||
|
'name' => 'email',
|
||||||
|
'required' => true,
|
||||||
|
'model' => $userModel ?? null,
|
||||||
|
'helper' => __('Adresse email valide.'),
|
||||||
|
'placeholder' => "jean.dupont@ldc.fr"
|
||||||
|
])
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
{{-- ROLE --}}
|
||||||
|
<div class="col-12 col-md-6 mb-3">
|
||||||
|
<fieldset class="h-100 border p-3">
|
||||||
|
<legend>{{ __('Rôle') }}</legend>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12">
|
||||||
|
@include('bo.partials.inputs.tinyint-enum', [
|
||||||
|
'id' => 'userRole',
|
||||||
|
'label' => __('Associer un rôle'),
|
||||||
|
'name' => 'role',
|
||||||
|
'model' => $userModel ?? null,
|
||||||
|
'required' => true,
|
||||||
|
'associatedModels' => Arr::where(
|
||||||
|
\App\Enums\Users\RoleEnum::toArray(),
|
||||||
|
fn(object $role) => $role->value >= auth('backend')->user()->role->value()),
|
||||||
|
'helper' => __('Sélectionnez un rôle dans la liste déroulante.'),
|
||||||
|
])
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
{{-- BRANDS --}}
|
||||||
|
<div class="col-12 col-md-6 mb-3">
|
||||||
|
<fieldset class="h-100 mb-3 border bg-white p-3">
|
||||||
|
<legend>{{ str(__('models.classes.brand'))->plural()->ucFirst() }}</legend>
|
||||||
|
<div class="row">
|
||||||
|
<div class="col-12 mb-3">
|
||||||
|
@include('bo.partials.inputs.pivot-belongsToMany', [
|
||||||
|
'id' => 'productRecipes',
|
||||||
|
'label' => __(':field associées au :model', [
|
||||||
|
'field' => str(__('models.classes.brand'))->plural()->ucFirst(),
|
||||||
|
'model' => __('models.classes.user'),
|
||||||
|
]),
|
||||||
|
'name' => 'brands',
|
||||||
|
'model' => $userModel ?? null,
|
||||||
|
'itemsList' => $brandModels,
|
||||||
|
'itemLimit' => [0, 8],
|
||||||
|
'placeholder' => __('Rechercher une :model', [
|
||||||
|
'model' => __('models.classes.brand')
|
||||||
|
]),
|
||||||
|
'helper' => __('Séléctionnez les :field associer à cet :model', [
|
||||||
|
'field' => str(__('models.classes.brand'))->plural(),
|
||||||
|
'model' => __('models.classes.user'),
|
||||||
|
]),
|
||||||
|
'required' => false,
|
||||||
|
])
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
37
resources/views/bo/pages/users/index.blade.php
Normal file
37
resources/views/bo/pages/users/index.blade.php
Normal file
|
|
@ -0,0 +1,37 @@
|
||||||
|
@extends('bo.layout')
|
||||||
|
|
||||||
|
@section('title', sprintf('%s - %s', str(__('models.classes.user'))->plural()->ucfirst(), Str::ucfirst(__('liste'))))
|
||||||
|
|
||||||
|
@section('breadcrumb', request()->route()->getName())
|
||||||
|
|
||||||
|
@section('content')
|
||||||
|
<div class="card">
|
||||||
|
<div class="card-header">
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
<h1 class="h3">{{ str(__('models.classes.user'))->plural()->ucfirst() }} {{ Str::ucfirst(__('liste')) }}</h1>
|
||||||
|
</div>
|
||||||
|
<div class="col-md-3">
|
||||||
|
<div class="input-group justify-content-end">
|
||||||
|
<a href="{{ route('bo.users.create') }}" class="btn btn-primary" title="{{ __('Ajouter un :model', [
|
||||||
|
'model' => str(__('models.classes.user'))->ucfirst(),
|
||||||
|
]) }}" data-bs-toggle="tooltip"><i class="fa-solid fa-plus"></i></a>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="card-body">
|
||||||
|
@include('modules.searchBar')
|
||||||
|
<div class="row">
|
||||||
|
<div class="col">
|
||||||
|
@include('bo.pages.users.indexList')
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="row justify-content-center">
|
||||||
|
<div class="col-12 col-md-6 p-0 p-md-3">
|
||||||
|
{{ $users->links() }}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
@endsection
|
||||||
52
resources/views/bo/pages/users/indexList.blade.php
Normal file
52
resources/views/bo/pages/users/indexList.blade.php
Normal file
|
|
@ -0,0 +1,52 @@
|
||||||
|
<div class="table-responsive">
|
||||||
|
<table class="table fix-action">
|
||||||
|
<thead>
|
||||||
|
@php
|
||||||
|
$cols = [
|
||||||
|
'firstname' => __('validation.custom.firstname'),
|
||||||
|
'lastname' => __('validation.custom.lastname'),
|
||||||
|
'email' => __('validation.custom.email'),
|
||||||
|
];
|
||||||
|
$routeName = request()->route()->getName();
|
||||||
|
$rst = !is_null(request()->rst) || !Session::has("$routeName.sorted");
|
||||||
|
$noOrder = Session::get("$routeName.sort_col") !== 'order' and (Session::has("$routeName.sort_col") or Session::has("$routeName.sort_way"));
|
||||||
|
$noOrder = Session::get("$routeName.sort_col") !== '' and (Session::has("$routeName.sort_col") or Session::has("$routeName.sort_way"));
|
||||||
|
@endphp
|
||||||
|
@include('modules.tableColSorter', [
|
||||||
|
'cols' => $cols,
|
||||||
|
'mobileHide' => [],
|
||||||
|
])
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
@if ($users->count())
|
||||||
|
@foreach ($users as $usersModel)
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<span>{{ $usersModel->firstname }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span>{{ $usersModel->lastname }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<span>{{ $usersModel->email }}</span>
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
<div class="btn-group">
|
||||||
|
<a class="btn btn-sm btn-primary" href="{{ route('bo.users.edit', $usersModel) }}" title="{{ __('Modifier :model', [
|
||||||
|
'model' => str(__('models.classes.user'))->ucfirst(),
|
||||||
|
]) }}" data-bs-toggle="tooltip"><i class="fa-solid fa-pencil"></i></a>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endforeach
|
||||||
|
@else
|
||||||
|
<tr>
|
||||||
|
<td colspan="5" class="text-center">
|
||||||
|
<span class="h3">{{ __('Aucun résultat pour les :models', ['models' => str(__('models.classes.user'))->plural()->ucfirst()]) }}
|
||||||
|
</span>
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
@endif
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
|
@ -1,18 +1,42 @@
|
||||||
<label for="{{ $id }}" class="col-form-label"><b>{{ $label }} @if(!empty($required))*@endif</b></label>
|
{{-- blade-formatter-disable --}}
|
||||||
<select id="{{ $id }}" class="form-select" name="{{ $name }}" aria-describedby="{{ $id }}Help" @if(empty($notSized)) size="{{ count($enumClass::toArray()) }}" @endif @if(!empty($required))required @endif>
|
{{--
|
||||||
@if(!empty($placeholder))
|
VARIABLE || COMMENT || TYPE || REQUIRED || DEFAULT
|
||||||
<option value="" @if(is_null(old($name, $shopModel->{$name}->value ?? null))) selected @endif disabled>
|
|
||||||
{{ $placeholder }}
|
$id || The id of the select tag. || string || REQUIRED ||
|
||||||
</option>
|
$name || The name of the select tag. || string || REQUIRED ||
|
||||||
@endif
|
$helper || The helper of the input. || string || REQUIRED ||
|
||||||
@foreach ($enumValues ?? $enumClass::toArray() as $enum)
|
$associatedModels || The enum to associate. || Enum || REQUIRED ||
|
||||||
<option value="{{ $enum->value }}" @if (old($name, $model->{$name}->value ?? null) == $enum->value) selected @endif>
|
$label || The text displayed as a label. || string || OPTIONNAL || null
|
||||||
{{ $enum->label }}
|
$disabled || Is the field disabled ? || boolean || OPTIONNAL || false
|
||||||
|
$required || Is the field required ? || boolean || OPTIONNAL || false
|
||||||
|
$value || The default selected option. || integer || OPTIONNAL || 1
|
||||||
|
$model || The model we're creating/editing || Model class || OPTIONNAL || null
|
||||||
|
--}}
|
||||||
|
|
||||||
|
@if(!empty($label))
|
||||||
|
<label for="{{ $name }}" class="col-form-label"><b>{{ $label }}@if(!empty($required)) * @endif</b></label>
|
||||||
|
@endif
|
||||||
|
<select
|
||||||
|
id="{{ $name }}"
|
||||||
|
@class([
|
||||||
|
'form-select',
|
||||||
|
'is-invalid' => $errors->has($name)
|
||||||
|
])
|
||||||
|
name="{{ $name }}"
|
||||||
|
aria-describedby="{{ $id }}Help"
|
||||||
|
@disabled(!empty($disabled))
|
||||||
|
@required(!empty($required))
|
||||||
|
role="button">
|
||||||
|
@foreach ($associatedModels as $associatedModel)
|
||||||
|
<option
|
||||||
|
value="{{ $associatedModel->value}}"
|
||||||
|
@selected(old($name, $model->{$name}->value ?? $value ?? 1) == $associatedModel->value)>
|
||||||
|
{{ $associatedModel->label }}
|
||||||
</option>
|
</option>
|
||||||
@endforeach
|
@endforeach
|
||||||
</select>
|
</select>
|
||||||
@include('modules.input-error', [
|
@include('modules.input-error', [
|
||||||
'inputName' => $name,
|
'inputName' => $name,
|
||||||
'helperId' => "{$id}Help",
|
'helperId' => "{$id}Help",
|
||||||
'helper' => $helper,
|
'helper' => $helper
|
||||||
])
|
])
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ use App\Http\Controllers\Bo\DashboardController;
|
||||||
use App\Http\Controllers\Bo\ServiceController;
|
use App\Http\Controllers\Bo\ServiceController;
|
||||||
use App\Http\Controllers\Bo\StatsController;
|
use App\Http\Controllers\Bo\StatsController;
|
||||||
use App\Http\Controllers\Bo\UrlController;
|
use App\Http\Controllers\Bo\UrlController;
|
||||||
|
use App\Http\Controllers\Bo\UserController;
|
||||||
use Illuminate\Support\Facades\Auth;
|
use Illuminate\Support\Facades\Auth;
|
||||||
use Illuminate\Support\Facades\Route;
|
use Illuminate\Support\Facades\Route;
|
||||||
|
|
||||||
|
|
@ -51,6 +52,9 @@ Route::prefix('bo')
|
||||||
Route::post('/services/{service}/token/generate', [ServiceController::class, 'generateServicePassword'])
|
Route::post('/services/{service}/token/generate', [ServiceController::class, 'generateServicePassword'])
|
||||||
->name('generate-token-service');
|
->name('generate-token-service');
|
||||||
|
|
||||||
|
// * USERS
|
||||||
|
Route::resource('users', UserController::class);
|
||||||
|
|
||||||
Route::middleware('can:isConceptor')->group(function () {
|
Route::middleware('can:isConceptor')->group(function () {
|
||||||
// * ACTIVITY LOGS.
|
// * ACTIVITY LOGS.
|
||||||
Route::resource('activity_logs', ActivityLogController::class)->only(['index', 'show']);
|
Route::resource('activity_logs', ActivityLogController::class)->only(['index', 'show']);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue