From 1ac87290fabe4a5f7400fe5d9645d2e9c32cbe9d Mon Sep 17 00:00:00 2001 From: Vincent BRIDIER Date: Mon, 28 Mar 2022 17:43:52 +0200 Subject: [PATCH] ticket 369 --- app/Http/Controllers/UserController.php | 430 ++++++++++-------- app/Http/Requests/DestroyUserRequest.php | 49 ++ app/Rules/HasMinimumRole.php | 89 ++++ app/Rules/IsValidRole.php | 34 ++ app/User.php | 233 ++++++---- config/roles.php | 24 +- resources/documents/arcadiar_roles.png | Bin 0 -> 36317 bytes resources/js/admin.js | 39 +- resources/sass/partials/form.scss | 1 + .../views/modules/flashMessage.blade.php | 43 ++ resources/views/users/create.blade.php | 27 +- resources/views/users/edit.blade.php | 54 +-- resources/views/users/index.blade.php | 1 + resources/views/users/show.blade.php | 1 + 14 files changed, 661 insertions(+), 364 deletions(-) create mode 100644 app/Http/Requests/DestroyUserRequest.php create mode 100644 app/Rules/HasMinimumRole.php create mode 100644 app/Rules/IsValidRole.php create mode 100644 resources/documents/arcadiar_roles.png create mode 100644 resources/views/modules/flashMessage.blade.php diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 6abfc82..84b820e 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -5,10 +5,11 @@ namespace App\Http\Controllers; use App\User; use App\Models\Marque; use App\Models\Sujet; -use App\Models\Dossier; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Auth; use Adldap\Laravel\Facades\Adldap; +use App\Http\Requests\DestroyUserRequest; +use App\Models\Media; +use Illuminate\Support\Facades\DB; class UserController extends Controller { @@ -19,10 +20,15 @@ class UserController extends Controller */ public function index() { - Auth::user()->authorizeRoles(config('roles.const.ADMIN')); - $users = User::all(); - $sujets = Sujet::where('sujet_dam', 1)->get(); - return view('users.index')->with(['users'=> $users, 'sujets'=> $sujets]); + /** @var \App\User $localUser */ + $localUser = auth()->user(); + $localUser->authorizeRoles(config('roles.const.ADMIN')); + $users = User::all(); + $sujets = Sujet::where('sujet_dam', 1)->get(); + return view('users.index')->with([ + 'users' => $users, + 'sujets' => $sujets + ]); } /** @@ -32,244 +38,306 @@ class UserController extends Controller */ public function create() { - Auth::user()->authorizeRoles(config('roles.const.ADMIN')); - $roles = config('roles.label'); - $marques = Marque::orderBy('libMarq', 'asc')->get(); - $sujets = Sujet::where('sujet_dam', 1)->orderBy('libelle', 'asc')->get(); - return view('users.create')->with(['roles'=> $roles, 'marques'=> $marques, 'sujets'=> $sujets]); + /** @var \App\User $localUser */ + $localUser = auth()->user(); + $localUser->authorizeRoles(config('roles.const.ADMIN')); + $roles = config('roles.label'); + $marques = Marque::orderBy('libMarq', 'asc')->get(); + $sujets = Sujet::where('sujet_dam', 1)->orderBy('libelle', 'asc')->get(); + return view('users.create')->with([ + 'roles' => $roles, 'marques' => $marques, + 'sujets' => $sujets + ]); } /** * Store a newly created resource in storage. * - * @param \Illuminate\Http\Request $request + * @param \Illuminate\Http\Request $request * @return \Illuminate\Http\Response */ public function store(Request $request) { - Auth::user()->authorizeRoles(config('roles.const.ADMIN')); - $validatedData = $request->validate([ - 'matricule' => 'required', - 'firstname' => 'required', - 'lastname' => 'required', - 'email' => 'email', - 'role' => 'required' - ]); + /** @var \App\User $localUser */ + $localUser = auth()->user(); + $localUser->authorizeRoles(config('roles.const.ADMIN')); + $validatedData = $request->validate([ + 'matricule' => 'required', + 'firstname' => 'required', + 'lastname' => 'required', + 'email' => 'email', + 'role' => 'required' + ]); - $user = User::where('matricule', $request->matricule)->first(); - if($user){ - session()->flash('error', "Ce matricule est déjà présent dans l'application. Ajout impossible."); - return redirect()->route('user.create'); - }else{ - // ---- L'utilisateur - $user = new User(); - $user->matricule = $request->matricule; - $user->firstname = $request->firstname; - $user->lastname = $request->lastname; - $user->email = $request->email; - $user->role = $request->role; + $user = User::where('matricule', $request->matricule)->first(); + if ($user) { + session()->flash('error', "Ce matricule est déjà présent dans l'application. Ajout impossible."); + return redirect()->route('user.create'); + } else { + // ---- L'utilisateur + $user = new User(); + $user->matricule = $request->matricule; + $user->firstname = $request->firstname; + $user->lastname = $request->lastname; + $user->email = $request->email; + $user->role = $request->role; - if ($user->save()){ + if ($user->save()) { + // ---- Les marques + $sMarques = $request->marques; + if ($sMarques != "") { + $marques = explode(",", $sMarques); + foreach ($marques as $marqueId) { + $user->marques()->attach($marqueId); + } + } - // ---- Les marques - $sMarques = $request->marques; - if($sMarques != ""){ - $marques = explode(",", $sMarques); - foreach($marques as $marqueId){ - $user->marques()->attach($marqueId); - } - } + // ---- Les sujets + $sSujets = $request->sujets; + if ($sSujets != "") { + $sujets = explode(",", $sSujets); + foreach ($sujets as $sujetId) { + $user->sujets()->attach($sujetId); + } + } else { + session()->flash('error', "Vous devez ajouter au moins un sujet."); + return redirect()->route('user.create'); + } - // ---- Les sujets - $sSujets = $request->sujets; - if($sSujets != ""){ - $sujets = explode(",", $sSujets); - foreach($sujets as $sujetId){ - $user->sujets()->attach($sujetId); - } - }else{ - session()->flash('error', "Vous devez ajouter au moins un sujet."); - return redirect()->route('user.create'); - } - - session()->flash('message', "L'utilisateur a été enregistré"); - return redirect()->route('user.edit', ['user' => $user]); - }else{ - session()->flash('error', "Une erreur s'est produite, ajout impossible"); - return redirect()->route('user.create'); - } - } + session()->flash('success', "L'utilisateur a été enregistré"); + return redirect()->route( + 'user.edit', + ['user' => $user] + ); + } else { + session()->flash('error', "Une erreur s'est produite, ajout impossible"); + return redirect()->route('user.create'); + } //end if + }//end if } - /** - * Check le matricule avant ajout de l'utilisateur - * - */ - public function checkMatricule(Request $request) - { - Auth::user()->authorizeRoles(config('roles.const.ADMIN')); - $response = array(); - $response["exist_bdd"] = false; - $response["exist_ldap"] = false; + /** + * Check le matricule avant ajout de l'utilisateur + * + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function checkMatricule(Request $request) + { + /** @var \App\User $localUser */ + $localUser = auth()->user(); + $localUser->authorizeRoles(config('roles.const.ADMIN')); + $response = []; + $response["exist_bdd"] = false; + $response["exist_ldap"] = false; - $data = $request->all(); // This will get all the request data. - $matricule = $request->input('matricule'); + // This will get all the request data. + $data = $request->all(); + $matricule = $request->input('matricule'); - // ---- Ctrl de la présence du matricule en base - $user = User::where('matricule', $request->matricule)->first(); - if($user){ - $response["exist_bdd"] = true; - } + // ---- Ctrl de la présence du matricule en base + $user = User::where('matricule', $request->matricule)->first(); + if ($user) { + $response["exist_bdd"] = true; + } - $adldap = Adldap::getFacadeRoot(); - $results = $adldap->search()->where('uid', '=', $matricule)->first(); + $adldap = Adldap::getFacadeRoot(); + $results = $adldap->search()->where('uid', '=', $matricule)->first(); - if($results){ - $response["exist_ldap"] = true; - $ldap_user = array(); - $ldap_user['firstname'] = $results->getAttribute('givenname')[0]; - $ldap_user['lastname'] = $results->getAttribute('sn')[0]; - $ldap_user['email'] = $results->getAttribute('mail')[0]; - $response["ldap_user"] = $ldap_user; - } + if ($results) { + $response["exist_ldap"] = true; + $ldap_user = []; + $ldap_user['firstname'] = $results->getAttribute('givenname')[0]; + $ldap_user['lastname'] = $results->getAttribute('sn')[0]; + $ldap_user['email'] = $results->getAttribute('mail')[0]; + $response["ldap_user"] = $ldap_user; + } - return json_encode($response); - } + return response()->json($response); + } /** * Display the specified resource. * - * @param \App\User $user + * @param \App\User $user * @return \Illuminate\Http\Response */ public function show(User $user) { - $roles = config('roles.label'); - $marques = $user->marques; - $sujets = $user->sujets; - return view('users.show')->with(['user'=> $user, 'roles'=> $roles, 'marques' => $marques, 'sujets' => $sujets]); + $roles = config('roles.label'); + $marques = $user->marques; + $sujets = $user->sujets; + return view('users.show')->with([ + 'user' => $user, 'roles' => $roles, + 'marques' => $marques, + 'sujets' => $sujets + ]); } /** * Show the form for editing the specified resource. * - * @param \App\User $user + * @param \App\User $user * @return \Illuminate\Http\Response */ public function edit(User $user) { - Auth::user()->authorizeRoles(config('roles.const.ADMIN')); - $roles = config('roles.label'); - $userMarques = $user->marques; - $marques = Marque::orderBy('libMarq', 'asc')->get(); - $userSujets = $user->sujets; - $sujets = Sujet::where('sujet_dam', 1)->orderBy('libelle', 'asc')->get(); - return view('users.edit')->with(['user'=> $user, 'roles'=> $roles, 'userMarques' => $userMarques, 'marques' => $marques, 'userSujets' => $userSujets, 'sujets'=> $sujets]); + /** @var \App\User $localUser */ + $localUser = auth()->user(); + $localUser->authorizeRoles(config('roles.const.ADMIN')); + + $roles = config('roles.label'); + $userMarques = $user->marques; + $marques = Marque::orderBy('libMarq', 'asc')->get(); + $userSujets = $user->sujets; + $sujets = Sujet::where('sujet_dam', 1)->orderBy('libelle', 'asc')->get(); + $users = User::select(['id', 'email'])->whereIn('role', [ + config('roles.const.ADMIN'), config('roles.const.CONTRIBUTEUR'), + config('roles.const.REDACTEUR') + ])->where('id', '!=', $user->id)->get(); + return view('users.edit')->with([ + 'user' => $user, 'roles' => $roles, 'users' => $users, + 'userMarques' => $userMarques, 'marques' => $marques, + 'userSujets' => $userSujets, 'sujets' => $sujets + ]); } /** * Update the specified resource in storage. * - * @param \Illuminate\Http\Request $request - * @param \App\User $user + * @param \Illuminate\Http\Request $request + * @param \App\User $user * @return \Illuminate\Http\Response */ public function update(Request $request, User $user) { - Auth::user()->authorizeRoles(config('roles.const.ADMIN')); - $validatedData = $request->validate([ - 'firstname' => 'required', - 'lastname' => 'required', - 'email' => 'email', - 'role' => 'required' - ]); + /** @var \App\User $localUser */ + $localUser = auth()->user(); + $localUser->authorizeRoles(config('roles.const.ADMIN')); + $validatedData = $request->validate([ + 'firstname' => 'required', + 'lastname' => 'required', + 'email' => 'email', + 'role' => 'required' + ]); - // ---- L'utilisateur - $user->firstname = $request->firstname; - $user->lastname = $request->lastname; - $user->email = $request->email; - $user->role = $request->role; - $user->save(); + // ---- L'utilisateur + $user->firstname = $request->firstname; + $user->lastname = $request->lastname; + $user->email = $request->email; + $user->role = $request->role; + $user->save(); - // ---- Les marques - $user->marques()->detach(); - $sMarques = $request->marques; - if($sMarques != ""){ - $marques = explode(",", $sMarques); - foreach($marques as $marqueId){ - $user->marques()->attach($marqueId); - } - } + // ---- Les marques + $user->marques()->detach(); + $sMarques = $request->marques; + if ($sMarques != "") { + $marques = explode(",", $sMarques); + foreach ($marques as $marqueId) { + $user->marques()->attach($marqueId); + } + } - // ---- Les Sujets - $user->sujets()->detach(); - $sSujets = $request->sujets; - if($sSujets != ""){ - $sujets = explode(",", $sSujets); - foreach($sujets as $sujetId){ - $user->sujets()->attach($sujetId); - } - }else{ - session()->flash('error', "Vous devez ajouter au moins un sujet."); - return redirect()->route('user.edit', ['user' => $user]); - } + // ---- Les Sujets + $user->sujets()->detach(); + $sSujets = $request->sujets; + if ($sSujets != "") { + $sujets = explode(",", $sSujets); + foreach ($sujets as $sujetId) { + $user->sujets()->attach($sujetId); + } + } else { + session()->flash('error', "Vous devez ajouter au moins un sujet."); + return redirect()->route('user.edit', ['user' => $user]); + } - session()->flash('message', "L'utilisateur a été mis à jour"); - return redirect()->route('user.edit', ['user' => $user]); + session()->flash('success', "L'utilisateur a été mis à jour"); + return redirect()->route('user.edit', ['user' => $user]); } /** * Remove the specified resource from storage. * - * @param \App\User $user + * @param \App\Http\Requests\DestroyUserRequest $request + * @param \App\User $user * @return \Illuminate\Http\Response */ - public function destroy(User $user) + public function destroy(DestroyUserRequest $request, User $user) { - Auth::user()->authorizeRoles(config('roles.const.ADMIN')); - if ($user->delete()) { - return redirect(route('user.index')); - } else { - session()->flash('error', 'Erreur lors de la suppression'); - return redirect()->route('user.edit', ['user' => $user]); - } + /** @var \App\Models\User $localUser */ + $localUser = auth()->user(); + $localUser->authorizeRoles(config('roles.const.ADMIN')); + + /** @var \App\User */ + $userPourRemplacer = User::whereId($request->created_by)->firstOrFail(); + + try { + return DB::transaction(function () use ($user, $userPourRemplacer) { + Media::whereCreatedBy($user->id)->get() + ->map(function (Media $media) use ($userPourRemplacer) { + $media->owner()->associate($userPourRemplacer); + $media->saveOrFail(); + }); + // TODO: use deleteOrFail after upgrate to laravel 8. + if ($user->delete()) { + session()->flash('success', trans('L\'utilisateur à été supprimé')); + return redirect(route('user.index')); + } + session()->flash('error', 'Erreur lors de la suppression'); + return redirect()->back(); + }); + } catch (\Exception $e) { + report($e); + session()->flash('error', 'Erreur lors de la suppression'); + return redirect()->back(); + }//end try } - /** - * ajouter un dossier en favoris - * - */ - public function favorisFolder(Request $request) - { - $dossier_id = $request->input('dossier_id'); - $favoris = $request->input('favoris'); + /** + * Ajouter un dossier en favoris + * + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function favorisFolder(Request $request) + { + /** @var \App\Models\User $localUser */ + $localUser = auth()->user(); - $dossierFav = Auth::user()->dossiers()->where('id', $dossier_id)->first(); + $dossier_id = $request->input('dossier_id'); + $favoris = $request->input('favoris'); - if($favoris === false && $dossierFav){ - Auth::user()->dossiers()->detach($dossier_id); - }elseif ($favoris === true && !$dossierFav) { - Auth::user()->dossiers()->attach($dossier_id); - } - return json_encode(true); - } + $dossierFav = $localUser->dossiers()->where('id', $dossier_id)->first(); - /** - * ajouter un panier en favoris - * - */ - public function favorisBasket(Request $request) - { - $basket_id = $request->input('basket_id'); - $favoris = $request->input('favoris'); + if ($favoris === false && $dossierFav) { + $localUser->dossiers()->detach($dossier_id); + } elseif ($favoris === true && !$dossierFav) { + $localUser->dossiers()->attach($dossier_id); + } + return response()->json(); + } - $basketFav = Auth::user()->paniersFavoris()->where('id', $basket_id)->first(); + /** + * Ajouter un panier en favoris + * + * @param Request $request + * @return \Illuminate\Http\JsonResponse + */ + public function favorisBasket(Request $request) + { + /** @var \App\Models\User $localUser */ + $localUser = auth()->user(); - if($favoris == "false" && $basketFav){ - Auth::user()->paniersFavoris()->detach($basket_id); - }elseif ($favoris == "true" && !$basketFav) { - Auth::user()->paniersFavoris()->attach($basket_id); - } - return json_encode(true); - } + $basket_id = $request->input('basket_id'); + $favoris = $request->input('favoris'); + + $basketFav = $localUser->paniersFavoris()->where('id', $basket_id)->first(); + + if ($favoris == "false" && $basketFav) { + $localUser->paniersFavoris()->detach($basket_id); + } elseif ($favoris == "true" && !$basketFav) { + $localUser->paniersFavoris()->attach($basket_id); + } + return response()->json(); + } } diff --git a/app/Http/Requests/DestroyUserRequest.php b/app/Http/Requests/DestroyUserRequest.php new file mode 100644 index 0000000..d44ae91 --- /dev/null +++ b/app/Http/Requests/DestroyUserRequest.php @@ -0,0 +1,49 @@ +merge([ + 'minimumrole' => optional(User::whereId($this->created_by)->first())->role ?? null + ]); + return auth()->check(); + } + + /** + * Get the validation rules that apply to the request. + * + * @return array + */ + public function rules() + { + return [ + 'created_by' => 'required|exists:users,id', + 'minimumrole' => [new IsValidRole(), new HasMinimumRole('CONTRIBUTEUR')] + ]; + } + + /** + * Get custom attributes for validator errors. + * + * @return array + */ + public function attributes() + { + return [ + 'minimumrole' => trans('rôle') + ]; + } +} diff --git a/app/Rules/HasMinimumRole.php b/app/Rules/HasMinimumRole.php new file mode 100644 index 0000000..94cc932 --- /dev/null +++ b/app/Rules/HasMinimumRole.php @@ -0,0 +1,89 @@ + 1, 'REDACTEUR' => 2, + 'CONTRIBUTEUR' => 3, 'LECTEUR' => 4 + ]; + + /** + * Create a new rule instance. + * + * @param string $role + * @throws \ErrorException If role is unknown. + */ + public function __construct(string $role) + { + if (!in_array(\intval($role), \array_keys($this->roles))) { + throw new \ErrorException("Unknown role $role"); + } + + $this->minimumRole = \intval($this->roles[$role]); + } + + /** + * Convert Arcadia role to usable roles + * + * 1 (ADMIN) => 1 + * 2 (LECTEUR) => 4 + * 3 (ADMIN) => 3 + * 4 (REDACTEUR) => 2 + * + * Donc : + * 1 (ADMIN) + * 2 (REDACTEUR) + * 3 (ADMIN) + * 4 (LECTEUR) + * + * @param integer $value + * @return integer + */ + private function translateRoleValue(int $value): int + { + $translation = [2 => 4, 4 => 2]; + return in_array($value, $translation) ? $translation[$value] : $value; + } + + /** + * Determine if the validation rule passes. + * + * @param mixed $attribute + * @param mixed $value + * @return boolean + * @phpcs:disable Generic.CodeAnalysis.UnusedFunctionParameter.FoundInImplementedInterfaceBeforeLastUsed + */ + public function passes($attribute, $value) + { + if (!\ctype_digit(strval($value))) { + return false; + }; + return $this->translateRoleValue(\intval($value)) <= $this->minimumRole; + } + + /** + * Get the validation error message. + * + * @return string + */ + public function message() + { + return 'L\'attribut :attribute :input n\'est pas suffisament élevé.'; + } +} diff --git a/app/Rules/IsValidRole.php b/app/Rules/IsValidRole.php new file mode 100644 index 0000000..78ab780 --- /dev/null +++ b/app/Rules/IsValidRole.php @@ -0,0 +1,34 @@ + 'datetime', ]; - /** - * @param string|array $roles - */ - public function authorizeRoles($roles){ - if (is_array($roles)) { - return in_array($this->role, $roles) || - abort(401, 'Cette action n\'est pas autorisée.'); - } - return $this->role == $roles || - abort(401, 'Cette action n\'est pas autorisée.'); - } + // * METHODS - /** - * Check one role - * @param string $role - */ - public function hasRole($roles) { - if (is_array($roles)) { - return in_array($this->role, $roles); - } - return $this->role == $roles; - } - - /** - * get one role label - * @param string $role - */ - public function getRoleLabel() { - return config('roles.label.'.$this->role); - } - - /** - * The marques that belong to the user. - */ - public function marques() - { - return $this->belongsToMany('App\Models\Marque', 'marques_users', 'user_id', 'marque_id'); - } - - /** - * The dossiers that belong to the user. - */ - public function dossiers() - { - return $this->belongsToMany('App\Models\Dossier', 'dossiers_users', 'user_id', 'dossier_id'); - } - - /** - * The sujet that belong to the user. - */ - public function sujets() - { - return $this->belongsToMany('App\Models\Sujet', 'sujets_users', 'user_id', 'sujet_id'); - } - - /** - * Get the medias for the user. - */ - public function medias() - { - return $this->hasMany('App\Models\Media'); - } - - /** - * Get the historiques for the user. - */ - public function historiques() - { - return $this->hasMany('App\Models\Historique'); - } - - /** - * Get the recherches for the user. - */ - public function recherches() + /** + * Authorize role + * + * @param string|array $roles + * @return boolean + */ + public function authorizeRoles($roles): bool { - return $this->hasMany('App\Models\Recherche'); + if (is_array($roles) and in_array($this->role, $roles)) { + return true; + } + if (is_string($roles) and $this->role == $roles) { + return true; + } + abort(401, 'Cette action n\'est pas autorisée.'); } - /** - * Get the paniers for the user. - */ - public function paniersOwner() - { - return $this->hasMany('App\Models\Panier', 'owner')->with('medias'); - } + /** + * Check one role + * + * @param array|string $roles + * @return boolean + */ + public function hasRole($roles): bool + { + if (is_array($roles)) { + return in_array($this->role, $roles); + } + return $this->role == $roles; + } - /** - * The paniers that belong to the user. - */ - public function paniersFavoris() - { - return $this->belongsToMany('App\Models\Panier', 'paniers_users', 'user_id', 'panier_id'); - } + /** + * Get role label + * + * @return string|null + */ + public function getRoleLabel(): ?string + { + return config('roles.label.' . $this->role); + } + + // * RELATIONSHIPS + + /** + * BelongsToMany marque relation + * The marques that belong to the user. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + */ + public function marques() + { + return $this->belongsToMany(Marque::class, 'marques_users', 'user_id', 'marque_id'); + } + + /** + * BelongsToMany dossier relation + * The dossiers that belong to the user. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + */ + public function dossiers() + { + return $this->belongsToMany(Dossier::class, 'dossiers_users', 'user_id', 'dossier_id'); + } + + /** + * BelongsToMany sujet relation + * The sujet that belong to the user. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + */ + public function sujets() + { + return $this->belongsToMany(Sujet::class, 'sujets_users', 'user_id', 'sujet_id'); + } + + /** + * HasMany medias relation + * Get the medias for the user. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function medias() + { + return $this->hasMany(Media::class); + } + + /** + * HasMany historiques relation + * Get the historiques for the user. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function historiques() + { + return $this->hasMany(Historique::class); + } + + /** + * HasMany recherches relation + * Get the recherches for the user. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function recherches() + { + return $this->hasMany(Recherche::class); + } + + /** + * HasMany paniers relation + * Get the paniers for the user. + * + * @return \Illuminate\Database\Eloquent\Relations\HasMany + */ + public function paniersOwner() + { + return $this->hasMany(Panier::class, 'owner')->with('medias'); + } + + /** + * BelongsToMany paniers relation + * The paniers that belong to the user. + * + * @return \Illuminate\Database\Eloquent\Relations\BelongsToMany + */ + public function paniersFavoris() + { + return $this->belongsToMany(Panier::class, 'paniers_users', 'user_id', 'panier_id'); + } } diff --git a/config/roles.php b/config/roles.php index 802a2b6..b9c4b89 100644 --- a/config/roles.php +++ b/config/roles.php @@ -1,16 +1,16 @@ [ - 'ADMIN' => '1', - 'LECTEUR' => '2', - 'CONTRIBUTEUR' => '3', - 'REDACTEUR' => '4', - ], - 'label' => [ - '1' => 'Administrateur', - '2' => 'Lecteur', - '3' => 'Contributeur', - '4' => 'Rédacteur', - ], + 'const' => [ + 'ADMIN' => '1', + 'LECTEUR' => '2', + 'CONTRIBUTEUR' => '3', + 'REDACTEUR' => '4', + ], + 'label' => [ + '1' => 'Administrateur', + '2' => 'Lecteur', + '3' => 'Contributeur', + '4' => 'Rédacteur', + ] ]; diff --git a/resources/documents/arcadiar_roles.png b/resources/documents/arcadiar_roles.png new file mode 100644 index 0000000000000000000000000000000000000000..63cef364530d91644970d4b198c5786bcc2609a0 GIT binary patch literal 36317 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 Z+Q#Li+gO&C9Rl!AMnX}%TGS}`{{xwvKt})o literal 0 HcmV?d00001 diff --git a/resources/js/admin.js b/resources/js/admin.js index 7c2db86..481d528 100644 --- a/resources/js/admin.js +++ b/resources/js/admin.js @@ -33,21 +33,36 @@ $(document).ready(function() { tableGlobalSearch('.datatable tr.data_row', search, [1]); }); + // ---- Edition des utilisateurs : validation formulaire + $('#submitEdit').on('click', () => { + $('.dataform').trigger('submit') + }) + // ---- Edition des utilisateurs : suppression d'utilisateur $(".btn_delete_user").on('click', function(event) { event.preventDefault(); - var form = $(".deleteform"); - $.fancyConfirm({ - title : "Suppression d'un utilisateur", - message : "Êtes-vous sûr de vouloir supprimer cet utilisateur ?", - okButton : 'Supprimer', - noButton : 'Annuler', - callback : function (value) { - if (value) { - form.submit(); - } - } - }); + let form = $('.deleteform'), created_by = $('select[name="created_by"]').val(), + created_by_text = $('select[name="created_by"] option:selected').text() + if (!created_by.length) { + $.fancyConfirm({ + title: 'Impossible de lancer cet action.', + message: 'Vous devez choisir autre un utilisateur à qui assigner les fiches.', + okButton: 'Compris', + noButton: 'Retour' + }) + return; + } + $.fancyConfirm({ + title: 'Suppression d\'un utilisateur', + message: 'Les média seront assignés à ' + created_by_text + '. Êtes-vous sûr de vouloir supprimer cet utilisateur ?', + okButton: 'Supprimer', + noButton: 'Annuler', + callback: function (value) { + if (value) { + form.trigger('submit') + } + } + }) }); // ---- Edition des dossiers : suppression d'un dossier diff --git a/resources/sass/partials/form.scss b/resources/sass/partials/form.scss index 3dae079..cd3ea3d 100644 --- a/resources/sass/partials/form.scss +++ b/resources/sass/partials/form.scss @@ -70,6 +70,7 @@ input[type="submit"].btn, button.btn, a.btn{ } } +.mt-10{margin-top: 10px; } .ml-10{margin-left: 10px; } .mr-10{margin-right: 10px; } .floatr{float: right;} diff --git a/resources/views/modules/flashMessage.blade.php b/resources/views/modules/flashMessage.blade.php new file mode 100644 index 0000000..fc5592b --- /dev/null +++ b/resources/views/modules/flashMessage.blade.php @@ -0,0 +1,43 @@ +@if ($message = Session::get('success')) + +@endif + +@if ($message = Session::get('error')) + +@endif + + +@if ($message = Session::get('warning')) + +@endif + + +@if ($message = Session::get('info')) + +@endif + + +@if ($errors->any()) + +@endif diff --git a/resources/views/users/create.blade.php b/resources/views/users/create.blade.php index 5a43b4f..3acb2d7 100644 --- a/resources/views/users/create.blade.php +++ b/resources/views/users/create.blade.php @@ -9,32 +9,7 @@ Anomalies du lien Arcadia
- @if ($errors->any()) -
- -
    - @foreach ($errors->all() as $error) -
  • {{ __($error) }}
  • - @endforeach -
-
- @endif - @if (session()->has('error')) -
- -
    -
  • {{ Session::get('error') }}
  • -
-
- @endif - @if (session()->has('message')) -
- -
    -
  • {{ Session::get('message') }}
  • -
-
- @endif + @include('modules.flashMessage')

Ajouter un utilisateur

diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php index 78a99c3..4dd142a 100644 --- a/resources/views/users/edit.blade.php +++ b/resources/views/users/edit.blade.php @@ -9,32 +9,7 @@ Anomalies du lien Arcadia
- @if ($errors->any()) -
- -
    - @foreach ($errors->all() as $error) -
  • {{ __($error) }}
  • - @endforeach -
-
- @endif - @if (session()->has('error')) -
- -
    -
  • {{ Session::get('error') }}
  • -
-
- @endif - @if (session()->has('message')) -
- -
    -
  • {{ Session::get('message') }}
  • -
-
- @endif + @include('modules.flashMessage')

Edition d'un utilisateur

@@ -61,7 +36,11 @@
{!! Form::label("", "") !!} - {!! Form::select('role', $roles) !!} +
{!! Form::label('marques', 'Marques associées') !!} @@ -108,15 +87,22 @@
+ {!! Form::close() !!} -
- {!! Form::submit('Enregistrer', [ 'class' => 'btn']) !!} Annuler - Supprimer cet utilisateur +
+ {!! Form::submit('Enregistrer', [ 'class' => 'btn', 'id' => 'submitEdit']) !!} + Annuler + {!! Form::model($user, ['route' => ['user.destroy', $user], 'enctype' => 'multipart/form-data', 'class' => 'deleteform floatr']) !!} + @method('DELETE') + + + {!! Form::close() !!}
- {!! Form::close() !!} - {!! Form::model($user, ['route' => ['user.destroy', $user], 'enctype' => 'multipart/form-data', 'class' => 'deleteform']) !!} - @method('DELETE') - {!! Form::close() !!}
@endsection diff --git a/resources/views/users/index.blade.php b/resources/views/users/index.blade.php index 655e770..2466741 100644 --- a/resources/views/users/index.blade.php +++ b/resources/views/users/index.blade.php @@ -9,6 +9,7 @@ Anomalies du lien Arcadia
+ @include('modules.flashMessage')

Gestion des utilisateurs

Ajouter diff --git a/resources/views/users/show.blade.php b/resources/views/users/show.blade.php index d5db720..f8ae48e 100644 --- a/resources/views/users/show.blade.php +++ b/resources/views/users/show.blade.php @@ -6,6 +6,7 @@ Mes informations
+ @include('modules.flashMessage')

Mes informations