From 901c5509903d5f35d732a2faf356905eb6375f98 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Mon, 28 Jun 2021 16:04:52 +0200 Subject: [PATCH 01/45] Update Crud --- app/Enums/CrudType.php | 15 ++++++----- app/Http/Controllers/CrudController.php | 23 +++++++++++++--- app/Http/Requests/CrudRequest.php | 12 +++++++-- app/Models/User.php | 1 + app/Traits/IsCrudModel.php | 16 ++++++++++++ resources/views/crud/create.blade.php | 2 +- resources/views/crud/edit.blade.php | 2 +- resources/views/crud/formfield.blade.php | 3 +++ .../views/crud/formfields/image.blade.php | 26 +++++++++++++++++++ resources/views/crud/printfield.blade.php | 9 +++++++ 10 files changed, 96 insertions(+), 13 deletions(-) create mode 100644 resources/views/crud/formfields/image.blade.php diff --git a/app/Enums/CrudType.php b/app/Enums/CrudType.php index b5f8301..f0b8a1f 100644 --- a/app/Enums/CrudType.php +++ b/app/Enums/CrudType.php @@ -10,6 +10,7 @@ use Kwaadpepper\Enum\BaseEnum; * @method static self string() * @method static self text() * @method static self json() + * @method static self image() * @method static self email() * @method static self password() * @method static self float() @@ -28,12 +29,13 @@ class CrudType extends BaseEnum 'string' => 2, 'text' => 3, 'json' => 4, - 'email' => 5, - 'password' => 6, - 'float' => 7, - 'enum' => 8, - 'belongsTo' => 9, - 'belongsToMany' => 10 + 'image' => 5, + 'email' => 6, + 'password' => 7, + 'float' => 8, + 'enum' => 9, + 'belongsTo' => 10, + 'belongsToMany' => 11 ]; } @@ -45,6 +47,7 @@ class CrudType extends BaseEnum 'string' => trans('Chaîne de charactères simple'), 'text' => trans('Texte'), 'json' => trans('Json'), + 'image' => trans('Image'), 'email' => trans('Chaîne de charactères email'), 'password' => trans('Mot de passe'), 'float' => trans('Nombre à virgule flotante'), diff --git a/app/Http/Controllers/CrudController.php b/app/Http/Controllers/CrudController.php index 238af0e..8eb8e1b 100644 --- a/app/Http/Controllers/CrudController.php +++ b/app/Http/Controllers/CrudController.php @@ -2,6 +2,7 @@ namespace App\Http\Controllers; +use App\Enums\CrudType; use App\Exceptions\CrudException; use App\Http\Requests\CrudIndexRequest; use App\Http\Requests\StoreCrudModel; @@ -67,6 +68,7 @@ class CrudController extends Controller if (!request()->ajax() and !app()->runningInConsole()) { self::shareCrudModelsClassesToView(); $this->shareModelClassToView(); + $this->shareModelHasImageToView(); $this->shareModelTableToView(); $this->shareModelPropsToView(); } @@ -142,7 +144,7 @@ class CrudController extends Controller $model->saveRelations($request); $this->storedModel($model); return \redirect()->route(sprintf('%s.edit', $model->getTable()), $model) - ->with('success', trans(':model à bien été enregisté.', ['model' => $model->getModelName()])); + ->with('success', trans(':model a bien été enregisté.', ['model' => $model->getModelName()])); } // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass @@ -159,7 +161,7 @@ class CrudController extends Controller $model->saveRelations($request); $this->updatedModel($model); return \redirect()->route(sprintf('%s.edit', $model->getTable()), $model) - ->with('success', trans(':model à bien été enregisté.', ['model' => $model->getModelName()])); + ->with('success', trans(':model a bien été enregisté.', ['model' => $model->getModelName()])); } public function destroy(Model $model) @@ -176,7 +178,7 @@ class CrudController extends Controller } if ($model->delete()) { return \redirect()->route(sprintf('%s.index', $model->getTable())) - ->with('warning', trans(':model à bien été supprimé.', ['model' => $model->getModelName()])); + ->with('warning', trans(':model a bien été supprimé.', ['model' => $model->getModelName()])); } else { return redirect()->back() ->with('error', trans(':model n\'as pas pu être supprimé', ['model' => $model->getModelName()])); @@ -215,6 +217,21 @@ class CrudController extends Controller View::share('modelClass', static::$modelClass); } + /** + * Get the current model class + * + * @return void + */ + private function shareModelHasImageToView(): void + { + /** @var \Illuminate\Database\Eloquent\Model $model */ + $model = static::$modelClass; + + View::share('hasImage', (bool)collect((new $model())->getEditableProperties())->filter(function ($prop) { + return $prop['type']->equals(CrudType::image()); + })->count()); + } + /** * Get the current model table * diff --git a/app/Http/Requests/CrudRequest.php b/app/Http/Requests/CrudRequest.php index f2d06f8..3ee5fd7 100644 --- a/app/Http/Requests/CrudRequest.php +++ b/app/Http/Requests/CrudRequest.php @@ -6,9 +6,8 @@ use App\Enums\CrudAction; use App\Enums\CrudType; use App\Exceptions\CrudException; use App\Http\Controllers\CrudController; -use Illuminate\Database\Eloquent\Model; +use Illuminate\Support\Str; use Illuminate\Foundation\Http\FormRequest; -use App\Traits\IsCrudModel; class CrudRequest extends FormRequest { @@ -24,6 +23,7 @@ class CrudRequest extends FormRequest */ public function getRulesForAction(CrudAction $action): array { + $model = $this->getCurrentModel(); $props = $this->getCurrentModel()::getEditableProperties(); $propsRules = []; foreach ($this->getCurrentModel()::getRules() as $k => $rules) { @@ -48,6 +48,14 @@ class CrudRequest extends FormRequest if ($props[$k]['type']->equals(CrudType::boolean())) { $this->merge([$k => $this->{$k} ? 1 : 0]); } + // handle image + if ($props[$k]['type']->equals(CrudType::image())) { + $tableName = Str::singular((new $model())->getTable()); + if ($this->{$tableName}) { + $i = array_search('required', $propsRules[$k]); + unset($propsRules[$k][$i]); + } + } // handle belongsToMany if ($props[$k]['type']->equals(CrudType::belongsToMany())) { $propsRules["$k.*"][0] = 'exists:' . diff --git a/app/Models/User.php b/app/Models/User.php index 76df3d3..7f85d51 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -108,6 +108,7 @@ class User extends Authenticatable 'type' => CrudType::belongsToMany(), 'belongsToMany' => Project::class, 'belongsToManyLabel' => 'name', + 'nullable' => true, 'readonly' => function () { return auth()->user()->role->equals(Role::admin()) ? false : true; }, diff --git a/app/Traits/IsCrudModel.php b/app/Traits/IsCrudModel.php index 3dcf992..70ccd5b 100644 --- a/app/Traits/IsCrudModel.php +++ b/app/Traits/IsCrudModel.php @@ -7,6 +7,7 @@ use App\Enums\CrudType; use App\Exceptions\CrudException; use App\Http\Requests\CrudRequest; use Illuminate\Database\Eloquent\Relations\Relation; +use Illuminate\Http\UploadedFile; use Illuminate\Support\Facades\DB; use Illuminate\Support\Str; use Kwaadpepper\Enum\BaseEnum; @@ -69,6 +70,9 @@ trait IsCrudModel ) { $this->{$k} = $attribute; } + if (\is_object($this->{$k}) and \get_class($this->{$k}) === UploadedFile::class) { + $this->moveUploadedFile($k, $this->{$k}); + } } } @@ -175,6 +179,9 @@ trait IsCrudModel case CrudType::boolean(): $defaultRules[] = 'boolean'; break; + case CrudType::image(): + $defaultRules[] = 'file'; + break; case CrudType::email(): $defaultRules[] = 'email:rfc,dns'; break; @@ -212,6 +219,15 @@ trait IsCrudModel return class_basename(get_class($this)); } + private function moveUploadedFile(string $propName, UploadedFile &$file): void + { + $this->{$propName} = $file->storePubliclyAs( + $this->getTable(), + $file->hashName(), + ['disk' => 'public'] + ); + } + /** * Get the Editable Properties * diff --git a/resources/views/crud/create.blade.php b/resources/views/crud/create.blade.php index ba950ff..9e17cea 100644 --- a/resources/views/crud/create.blade.php +++ b/resources/views/crud/create.blade.php @@ -18,7 +18,7 @@ @endcan
-
+ @csrf diff --git a/resources/views/crud/edit.blade.php b/resources/views/crud/edit.blade.php index 1698c41..c154980 100644 --- a/resources/views/crud/edit.blade.php +++ b/resources/views/crud/edit.blade.php @@ -30,7 +30,7 @@
- + @method('put') @csrf
diff --git a/resources/views/crud/formfield.blade.php b/resources/views/crud/formfield.blade.php index 5ec65d1..d38ead4 100644 --- a/resources/views/crud/formfield.blade.php +++ b/resources/views/crud/formfield.blade.php @@ -23,6 +23,9 @@ $readonly = is_callable($prop['readonly']) ? $prop['readonly']() : $prop['readon @case(CrudType::json()) @include('crud.formfields.json') @break + @case(CrudType::image()) + @include('crud.formfields.image') + @break @case(CrudType::enum()) @include('crud.formfields.enum') @break diff --git a/resources/views/crud/formfields/image.blade.php b/resources/views/crud/formfields/image.blade.php new file mode 100644 index 0000000..6362773 --- /dev/null +++ b/resources/views/crud/formfields/image.blade.php @@ -0,0 +1,26 @@ + + diff --git a/resources/views/crud/printfield.blade.php b/resources/views/crud/printfield.blade.php index 0975095..a9aff63 100644 --- a/resources/views/crud/printfield.blade.php +++ b/resources/views/crud/printfield.blade.php @@ -16,6 +16,9 @@ @case(CrudType::boolean()) @if($model->{$fieldName})OUI @else NON @endif @break + @case(CrudType::image()) + {{ sprintf('/storage/%s', $model->{$fieldName}) }} + @break @default {{ $field }} @endswitch @@ -29,9 +32,15 @@ @case(CrudType::enum()) {{ $model->{$fieldName}->label }} @break + @case(CrudType::json()) + @json($field) + @break @case(CrudType::boolean()) @if($model->{$fieldName})OUI @else NON @endif @break + @case(CrudType::image()) + {{ sprintf('/storage/%s', $model->{$fieldName}) }} + @break @case(CrudType::belongsTo()) {{ $prop['belongsTo']::find($model->{$fieldName})->{$model->crudLabelColumn} }} @break From 8f753cb3493d86645986b7d45fbed635c260b928 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Mon, 28 Jun 2021 17:04:15 +0200 Subject: [PATCH 02/45] Ticket 244 et ompagnie : permet un soft delete de user et projects --- app/Http/Controllers/CrudController.php | 6 +++- app/Http/Controllers/TicketController.php | 2 +- app/Http/Requests/CrudRequest.php | 3 ++ app/Models/Project.php | 7 ++-- app/Models/User.php | 35 ++++++++++++++++++- app/Providers/RouteServiceProvider.php | 4 +++ app/Traits/IsCrudModel.php | 6 ++-- ..._06_28_163754_add_soft_delete_on_users.php | 32 +++++++++++++++++ ..._28_163755_add_soft_delete_on_projects.php | 32 +++++++++++++++++ 9 files changed, 119 insertions(+), 8 deletions(-) create mode 100644 database/migrations/2021_06_28_163754_add_soft_delete_on_users.php create mode 100644 database/migrations/2021_06_28_163755_add_soft_delete_on_projects.php diff --git a/app/Http/Controllers/CrudController.php b/app/Http/Controllers/CrudController.php index 8eb8e1b..ec6e447 100644 --- a/app/Http/Controllers/CrudController.php +++ b/app/Http/Controllers/CrudController.php @@ -10,6 +10,7 @@ use App\Http\Requests\UpdateCrudModel; use App\Http\Resources\CrudResource; use Illuminate\Database\Eloquent\Builder; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Facades\File; use Illuminate\Support\Facades\Schema; use Illuminate\Support\Facades\Session; @@ -166,7 +167,10 @@ class CrudController extends Controller public function destroy(Model $model) { - if ($restrict = $model->gotHasManyRelationWithRestrictOnDelete()) { + if ( + !in_array(SoftDeletes::class, class_uses_recursive($model), true) and + $restrict = $model->gotHasManyRelationWithRestrictOnDelete() + ) { return redirect()->back() ->with('error', trans( ':model n\'as pas pu être supprimé car il est encore associé avec des :associated', diff --git a/app/Http/Controllers/TicketController.php b/app/Http/Controllers/TicketController.php index 329e216..d9fc380 100644 --- a/app/Http/Controllers/TicketController.php +++ b/app/Http/Controllers/TicketController.php @@ -39,7 +39,7 @@ class TicketController extends Controller { /** @var \App\Models\User */ $user = auth()->user(); - $tickets = Ticket::with('project'); + $tickets = Ticket::with('project')->has('project'); if (!$user->role->equals(Role::admin())) { $tickets = $tickets->whereHas('project', function ($q) use ($user) { $q->whereHas('users', function ($q) use ($user) { diff --git a/app/Http/Requests/CrudRequest.php b/app/Http/Requests/CrudRequest.php index 3ee5fd7..a7a3cbf 100644 --- a/app/Http/Requests/CrudRequest.php +++ b/app/Http/Requests/CrudRequest.php @@ -60,6 +60,9 @@ class CrudRequest extends FormRequest if ($props[$k]['type']->equals(CrudType::belongsToMany())) { $propsRules["$k.*"][0] = 'exists:' . (new $props[$k]['belongsToMany']())->getTable() . ',id'; + if (!isset($this->{$k})) { + $this->merge([$k => []]); + } } } } diff --git a/app/Models/Project.php b/app/Models/Project.php index 28a236a..58bff7c 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -8,6 +8,7 @@ use App\Enums\Role; use App\Traits\IsCrudModel; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Facades\File; use Illuminate\Support\Str; @@ -15,6 +16,7 @@ class Project extends Model { use HasFactory; use IsCrudModel; + use SoftDeletes; protected $crudLabelColumn = 'name'; @@ -46,6 +48,7 @@ class Project extends Model 'type' => CrudType::belongsToMany(), 'belongsToMany' => User::class, 'belongsToManyLabel' => 'name', + 'nullable' => true, 'readonly' => function () { return auth()->user()->role->equals(Role::admin()) ? false : true; }, @@ -65,7 +68,7 @@ class Project extends Model static::created(function (Project $project) { $path = Project::ticketAssetsFullPath($project->slug_name); if (!File::exists($path)) { - File::makeDirectory($path); + File::makeDirectory($path, 0755, true); } }); static::updating(function (Project $project) { @@ -75,7 +78,7 @@ class Project extends Model if (File::exists($oldPath)) { File::move($oldPath, $newPath); } else { - File::makeDirectory($newPath); + File::makeDirectory($newPath, 0755, true); } }); static::deleted(function (Project $project) { diff --git a/app/Models/User.php b/app/Models/User.php index 7f85d51..cbf45df 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -7,8 +7,11 @@ use App\Enums\CrudType; use App\Enums\Role; use App\Traits\IsCrudModel; use Illuminate\Database\Eloquent\Factories\HasFactory; +use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Foundation\Auth\User as Authenticatable; use Illuminate\Notifications\Notifiable; +use Illuminate\Support\Facades\Hash; +use Illuminate\Support\Str; use Kwaadpepper\Enum\Traits\CastsEnums; class User extends Authenticatable @@ -17,6 +20,7 @@ class User extends Authenticatable use Notifiable; use CastsEnums; use IsCrudModel; + use SoftDeletes; protected $enumCasts = [ 'role' => Role::class @@ -81,7 +85,19 @@ class User extends Authenticatable 'required' => true, 'nullable' => false, 'validate' => [ - 'max:255' + 'max:255', + // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed + function ($attribute, $value, $fail) { + $q = static::query(); + if (request()->user) { + $q = $q->where('id', '!=', $this->id); + } + if ($q->where('email', $value)->exists()) { + $fail(__(':attribute est déjà utilisé', [ + 'attribute' => $attribute + ])); + } + } ], 'actions' => [ CrudAction::viewAny(), @@ -123,6 +139,23 @@ class User extends Authenticatable parent::__construct($attributes); } + protected static function booted() + { + static::creating(function (User $user) { + if (\is_null($user->password)) { + $user->password = Str::random(10); + } + if (Hash::needsRehash($user->password)) { + $user->password = Hash::make($user->password); + } + }); + static::updating(function (User $user) { + if (Hash::needsRehash($user->password)) { + $user->password = Hash::make($user->password); + } + }); + } + public function tickets() { return $this->hasMany(Ticket::class, 'created_by'); diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index cd8fc15..2595412 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -3,6 +3,7 @@ namespace App\Providers; use App\Models\Project; +use App\Models\Ticket; use App\Models\User; use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; @@ -51,6 +52,9 @@ class RouteServiceProvider extends ServiceProvider }); Route::model('user', User::class); Route::model('project', Project::class); + Route::bind('ticket', function ($value) { + return Ticket::where('id', $value)->has('project')->firstOrFail(); + }); } /** diff --git a/app/Traits/IsCrudModel.php b/app/Traits/IsCrudModel.php index 70ccd5b..694d06e 100644 --- a/app/Traits/IsCrudModel.php +++ b/app/Traits/IsCrudModel.php @@ -168,11 +168,11 @@ trait IsCrudModel return collect(static::$editableProperties)->mapWithKeys(function ($item, $key) { $item = \array_merge(self::$schemaCrud, $item); $defaultRules = []; - if (!$item['nullable']) { + if (!$item['nullable'] === true) { $defaultRules[] = 'required'; - } elseif ($item['required']) { + } elseif ($item['required'] === true) { $defaultRules[] = 'required'; - } elseif ($item['readonly']) { + } elseif ($item['readonly'] === true) { $defaultRules[] = 'prohibited'; } switch ($item['type']) { diff --git a/database/migrations/2021_06_28_163754_add_soft_delete_on_users.php b/database/migrations/2021_06_28_163754_add_soft_delete_on_users.php new file mode 100644 index 0000000..cf19b99 --- /dev/null +++ b/database/migrations/2021_06_28_163754_add_soft_delete_on_users.php @@ -0,0 +1,32 @@ +softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropSoftDeletes(); + }); + } +} diff --git a/database/migrations/2021_06_28_163755_add_soft_delete_on_projects.php b/database/migrations/2021_06_28_163755_add_soft_delete_on_projects.php new file mode 100644 index 0000000..b58a5fe --- /dev/null +++ b/database/migrations/2021_06_28_163755_add_soft_delete_on_projects.php @@ -0,0 +1,32 @@ +softDeletes(); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('projects', function (Blueprint $table) { + $table->dropSoftDeletes(); + }); + } +} From 81ac71b9a9fe97198e5811f09359f0d1cb2a9948 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Mon, 28 Jun 2021 17:22:52 +0200 Subject: [PATCH 03/45] Handle multiple projects on tickets --- app/Http/Requests/StoreTicket.php | 19 ++++++++++++++++++- app/Http/Requests/UpdateTicket.php | 8 +++++++- resources/views/ticket/form-inputs.blade.php | 9 ++++++++- resources/views/ticket/index.blade.php | 4 +--- 4 files changed, 34 insertions(+), 6 deletions(-) diff --git a/app/Http/Requests/StoreTicket.php b/app/Http/Requests/StoreTicket.php index 4f73e40..306b01a 100644 --- a/app/Http/Requests/StoreTicket.php +++ b/app/Http/Requests/StoreTicket.php @@ -2,6 +2,7 @@ namespace App\Http\Requests; +use App\Enums\Role; use App\Enums\TicketStatus; use App\Enums\TicketType; use Illuminate\Foundation\Http\FormRequest; @@ -15,6 +16,11 @@ class StoreTicket extends FormRequest */ public function authorize() { + if (!auth()->user()->role->equals(Role::admin())) { + $this->merge([ + 'status' => TicketStatus::new()->value, + ]); + } return auth()->check(); } @@ -26,7 +32,18 @@ class StoreTicket extends FormRequest public function rules() { return [ - 'project_id' => 'required|exists:projects,id', + 'project_id' => [ + 'required', + 'exists:projects,id', + // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed + function ($attribute, $value, $fail) { + if (!in_array($value, auth()->user()->projects()->pluck('id')->all())) { + $fail(__('Veuillez choisir entre :values', [ + 'value' => auth()->user()->projects()->pluck('name')->implode(',') + ])); + } + } + ], 'type' => [ 'required', // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed diff --git a/app/Http/Requests/UpdateTicket.php b/app/Http/Requests/UpdateTicket.php index 203416a..040bde7 100644 --- a/app/Http/Requests/UpdateTicket.php +++ b/app/Http/Requests/UpdateTicket.php @@ -9,6 +9,12 @@ class UpdateTicket extends StoreTicket { public function authorize() { - return auth()->check() and (auth()->user()->role->equals(Role::admin())); + if (!auth()->user()->role->equals(Role::admin())) { + $this->merge([ + 'status' => $this->project->status->value, + ]); + } + return auth()->check() and (auth()->user()->role->equals(Role::admin()) or + request()->route()->ticket->created_by === auth()->user()->id); } } diff --git a/resources/views/ticket/form-inputs.blade.php b/resources/views/ticket/form-inputs.blade.php index 5f8c721..e015468 100644 --- a/resources/views/ticket/form-inputs.blade.php +++ b/resources/views/ticket/form-inputs.blade.php @@ -1,10 +1,17 @@ @include('modules.error-messages') +@php +$userPr = Auth::user()->projects; +@endphp
diff --git a/resources/views/ticket/index.blade.php b/resources/views/ticket/index.blade.php index 89c7e19..6d16a3e 100644 --- a/resources/views/ticket/index.blade.php +++ b/resources/views/ticket/index.blade.php @@ -16,16 +16,14 @@ @endif {{ __('Réinitialiser le tri') }}
- @if(auth()->user()->role->equals(Role::admin()))
- @endif
From 0636759eb82881aa1efffbb6e10b457b82079504 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Mon, 28 Jun 2021 17:42:31 +0200 Subject: [PATCH 04/45] fix ticket.index sort --- resources/views/ticket/index.blade.php | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/resources/views/ticket/index.blade.php b/resources/views/ticket/index.blade.php index 6d16a3e..78bb4b0 100644 --- a/resources/views/ticket/index.blade.php +++ b/resources/views/ticket/index.blade.php @@ -19,8 +19,12 @@
From 19e4bfc95a0b30bc0bf18052f22465ffc46459c2 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Tue, 29 Jun 2021 09:12:16 +0200 Subject: [PATCH 05/45] fix forgotten $userPr --- resources/views/ticket/form-inputs.blade.php | 2 +- resources/views/ticket/index.blade.php | 3 +++ 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/resources/views/ticket/form-inputs.blade.php b/resources/views/ticket/form-inputs.blade.php index e015468..9e5bded 100644 --- a/resources/views/ticket/form-inputs.blade.php +++ b/resources/views/ticket/form-inputs.blade.php @@ -1,6 +1,6 @@ @include('modules.error-messages') @php -$userPr = Auth::user()->projects; +$userPr = Auth::user()->projects ?? collect([]); @endphp
diff --git a/resources/views/ticket/index.blade.php b/resources/views/ticket/index.blade.php index 78bb4b0..157e169 100644 --- a/resources/views/ticket/index.blade.php +++ b/resources/views/ticket/index.blade.php @@ -1,6 +1,9 @@ @extends('layout.app') @section('content') +@php +$userPr = Auth::user()->projects ?? collect([]); +@endphp

Gestion des tickets @if(request()->status) (Archivés) @endif From e164f46221b29340cb291e9508581051bfbf2682 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Tue, 29 Jun 2021 09:12:35 +0200 Subject: [PATCH 06/45] send email with pwd to user on create --- app/Http/Controllers/UserController.php | 8 ++++ app/Jobs/SendUserCreatedEmail.php | 44 +++++++++++++++++++ app/Mail/UserCreatedMail.php | 37 ++++++++++++++++ app/Models/User.php | 10 +++++ .../views/emails/mail-created-plain.blade.php | 4 ++ resources/views/emails/mail-created.blade.php | 13 ++++++ 6 files changed, 116 insertions(+) create mode 100644 app/Jobs/SendUserCreatedEmail.php create mode 100644 app/Mail/UserCreatedMail.php create mode 100644 resources/views/emails/mail-created-plain.blade.php create mode 100644 resources/views/emails/mail-created.blade.php diff --git a/app/Http/Controllers/UserController.php b/app/Http/Controllers/UserController.php index 8e43ef0..54d1443 100644 --- a/app/Http/Controllers/UserController.php +++ b/app/Http/Controllers/UserController.php @@ -3,10 +3,18 @@ namespace App\Http\Controllers; use App\Models\User; +use Illuminate\Database\Eloquent\Model; class UserController extends CrudController { /** @var User */ protected static $modelClass = User::class; + + public function storedModel(Model &$model) + { + /** @var \App\Models\User */ + $model = $model; + $model->sendMailConfirm(); + } } diff --git a/app/Jobs/SendUserCreatedEmail.php b/app/Jobs/SendUserCreatedEmail.php new file mode 100644 index 0000000..d17c49c --- /dev/null +++ b/app/Jobs/SendUserCreatedEmail.php @@ -0,0 +1,44 @@ +user = $user->withoutRelations(); + } + + /** + * Execute the job. + * + * @return void + */ + public function handle() + { + Mail::to(['email' => $this->user->email]) + ->send(new UserCreatedMail($this->user)); + Log::debug(sprintf('Sent %s to %s', UserCreatedMail::class, $this->user->email)); + } +} diff --git a/app/Mail/UserCreatedMail.php b/app/Mail/UserCreatedMail.php new file mode 100644 index 0000000..41f59cd --- /dev/null +++ b/app/Mail/UserCreatedMail.php @@ -0,0 +1,37 @@ +user = $user; + } + + /** + * Build the message. + * + * @return $this + */ + public function build() + { + return $this + ->subject(sprintf('%s : Votre compte a été crée', config('app.name'))) + ->view('emails.mail-created') + ->text('emails.mail-created-plain') + ->with('user', $this->user) + ->with('pwd', $this->user->tmpPass); + } +} diff --git a/app/Models/User.php b/app/Models/User.php index cbf45df..8e0f7ef 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -5,6 +5,7 @@ namespace App\Models; use App\Enums\CrudAction; use App\Enums\CrudType; use App\Enums\Role; +use App\Jobs\SendUserCreatedEmail; use App\Traits\IsCrudModel; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\SoftDeletes; @@ -30,6 +31,9 @@ class User extends Authenticatable protected $crudValueColumn = 'id'; + // stores unhashed pwd + public $tmpPass = null; + /** * The attributes that are mass assignable. * @@ -144,6 +148,7 @@ class User extends Authenticatable static::creating(function (User $user) { if (\is_null($user->password)) { $user->password = Str::random(10); + $user->tmpPass = $user->password; } if (Hash::needsRehash($user->password)) { $user->password = Hash::make($user->password); @@ -175,4 +180,9 @@ class User extends Authenticatable { return $this->belongsToMany(Project::class); } + + public function sendMailConfirm() + { + dispatch(new SendUserCreatedEmail($this)); + } } diff --git a/resources/views/emails/mail-created-plain.blade.php b/resources/views/emails/mail-created-plain.blade.php new file mode 100644 index 0000000..af3eb5b --- /dev/null +++ b/resources/views/emails/mail-created-plain.blade.php @@ -0,0 +1,4 @@ +Bonjour {{ $user->name }}, +Votre compte {{ config('app.name') }} vient d'être créé. Votre identifiant est votre email. +Votre mot de passe est le suivant: {{$pwd }} +Merci d'enregistrer celui-ci dans un gestionnaire de mot de passe et de supprimer cet email au plus vite. diff --git a/resources/views/emails/mail-created.blade.php b/resources/views/emails/mail-created.blade.php new file mode 100644 index 0000000..0bf4f87 --- /dev/null +++ b/resources/views/emails/mail-created.blade.php @@ -0,0 +1,13 @@ + + + + {{ config('app.name') }} + + + +

Bonjour {{ $user->name }},

+

Votre compte {{ config('app.name') }} vient d'être créé. Votre identifiant est votre email.

+

Votre mot de passe est le suivant : {{$pwd }}

+

Merci d'enregistrer celui-ci dans un gestionnaire de mot de passe et de supprimer cet email au plus vite.

+ + From 2efd5f85c4c6cf185a822d9c4496f5b1223ba8bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Tue, 29 Jun 2021 10:17:43 +0200 Subject: [PATCH 07/45] submit ticket allow for admin --- app/Http/Requests/StoreTicket.php | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/app/Http/Requests/StoreTicket.php b/app/Http/Requests/StoreTicket.php index 306b01a..741d9e8 100644 --- a/app/Http/Requests/StoreTicket.php +++ b/app/Http/Requests/StoreTicket.php @@ -37,9 +37,12 @@ class StoreTicket extends FormRequest 'exists:projects,id', // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed function ($attribute, $value, $fail) { + if (auth()->user()->role->equals(Role::admin())) { + return; + } if (!in_array($value, auth()->user()->projects()->pluck('id')->all())) { $fail(__('Veuillez choisir entre :values', [ - 'value' => auth()->user()->projects()->pluck('name')->implode(',') + 'values' => auth()->user()->projects()->pluck('name')->implode(',') ])); } } From eb37318c29c4df4f883dfeec884311d0401cdbb5 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Wed, 30 Jun 2021 08:55:56 +0200 Subject: [PATCH 08/45] fix ticket bg color with links --- resources/views/ticket/show.blade.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/resources/views/ticket/show.blade.php b/resources/views/ticket/show.blade.php index 8de3b1e..25e700a 100644 --- a/resources/views/ticket/show.blade.php +++ b/resources/views/ticket/show.blade.php @@ -100,7 +100,7 @@ (Message système)

@elseif ($message->user_id === Auth::user()->id) -
+
{!! Utils::plainToHtml($message->message) !!} @if ($message->file !== null)
Ouvrir la pièce jointe
From 0afc9b71d3d079d125267f1e3d7a88ad1a62fd8d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Mon, 5 Jul 2021 18:35:59 +0200 Subject: [PATCH 09/45] Fix ticket.index sortby project --- app/Http/Controllers/TicketController.php | 2 +- resources/views/ticket/index.blade.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/TicketController.php b/app/Http/Controllers/TicketController.php index d9fc380..31604c4 100644 --- a/app/Http/Controllers/TicketController.php +++ b/app/Http/Controllers/TicketController.php @@ -88,7 +88,7 @@ class TicketController extends Controller Session::has('tickets.sort_col') and Session::has('tickets.sort_way') and in_array(Session::get('tickets.sort_col'), [ - 'id', 'project', 'created_at', 'created_by', + 'id', 'project_id', 'created_at', 'created_by', 'type', 'status' ]) ) { diff --git a/resources/views/ticket/index.blade.php b/resources/views/ticket/index.blade.php index 157e169..9147650 100644 --- a/resources/views/ticket/index.blade.php +++ b/resources/views/ticket/index.blade.php @@ -55,7 +55,7 @@ $userPr = Auth::user()->projects ?? collect([]);
- +
+ + + @if(strlen($prop['placeholder'])) +
+ @endif + {$fieldName}))required @endif> + @if(strlen($prop['placeholder'])) + +
+ @endif + @if(isset($model) and $model->{$fieldName}) + {{ sprintf('/storage/%s', $model->{$fieldName}) }} + @endif +
{{__('Projet') }}  - @include('modules.sorter', ['colname' => 'project']) + @include('modules.sorter', ['colname' => 'project_id']) {{__('Type') }}  From 62d2c0acf56b091bd1d2352b1bb65e00683ec6db Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Wed, 21 Jul 2021 09:44:29 +0200 Subject: [PATCH 10/45] Upgrade notification system on tickets --- app/Events/NotifySubscriptions.php | 7 +- app/Events/NotifyTicketCreator.php | 32 +++++++++ app/Events/TicketStatusChanged.php | 12 +++- app/Http/Controllers/TicketController.php | 34 +--------- app/Listeners/AddStatusMessages.php | 10 --- .../SendNotificationMailToTicketCreator.php | 26 ++++++++ ...=> SendSubscriptionsNotificationsMail.php} | 13 ++-- app/Models/Message.php | 65 ++++++++++++++++++- app/Providers/EventServiceProvider.php | 20 ++++-- 9 files changed, 163 insertions(+), 56 deletions(-) create mode 100644 app/Events/NotifyTicketCreator.php create mode 100644 app/Listeners/SendNotificationMailToTicketCreator.php rename app/Listeners/{SendNotificationMail.php => SendSubscriptionsNotificationsMail.php} (54%) diff --git a/app/Events/NotifySubscriptions.php b/app/Events/NotifySubscriptions.php index 1f60396..b2c15bd 100644 --- a/app/Events/NotifySubscriptions.php +++ b/app/Events/NotifySubscriptions.php @@ -6,6 +6,7 @@ use App\Models\Ticket; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; +use Illuminate\Support\Collection; class NotifySubscriptions { @@ -19,14 +20,18 @@ class NotifySubscriptions /** @var string */ public $corpsMaj; + /** @var Collection */ + public $ignoreUsers; + /** * Create a new event instance. * * @return void */ - public function __construct(Ticket $ticket, string $corpsMaj) + public function __construct(Ticket $ticket, string $corpsMaj, Collection $ignoreUsers = null) { $this->ticket = $ticket; $this->corpsMaj = $corpsMaj; + $this->ignoreUsers = $ignoreUsers; } } diff --git a/app/Events/NotifyTicketCreator.php b/app/Events/NotifyTicketCreator.php new file mode 100644 index 0000000..f2e8284 --- /dev/null +++ b/app/Events/NotifyTicketCreator.php @@ -0,0 +1,32 @@ +ticket = $ticket; + $this->corpsMaj = $corpsMaj; + } +} diff --git a/app/Events/TicketStatusChanged.php b/app/Events/TicketStatusChanged.php index 64a9e3a..804cb3b 100644 --- a/app/Events/TicketStatusChanged.php +++ b/app/Events/TicketStatusChanged.php @@ -2,22 +2,28 @@ namespace App\Events; +use App\Models\Ticket; use Illuminate\Broadcasting\InteractsWithSockets; use Illuminate\Foundation\Events\Dispatchable; use Illuminate\Queue\SerializesModels; class TicketStatusChanged { - use Dispatchable, InteractsWithSockets, SerializesModels; + use Dispatchable; + use InteractsWithSockets; + use SerializesModels; - public $ticket, $status; + /** @var Ticket */ + public $ticket; + + public $status; /** * Create a new event instance. * * @return void */ - public function __construct($ticket, $status) + public function __construct(Ticket $ticket, $status) { $this->ticket = $ticket; $this->status = $status; diff --git a/app/Http/Controllers/TicketController.php b/app/Http/Controllers/TicketController.php index 31604c4..b3dadab 100644 --- a/app/Http/Controllers/TicketController.php +++ b/app/Http/Controllers/TicketController.php @@ -5,21 +5,17 @@ namespace App\Http\Controllers; use App\Enums\Role; use App\Enums\TicketStatus; use App\Enums\TicketType; -use App\Events\NotifySubscriptions; use App\Http\Requests\ChangeTicketStatus; use App\Http\Requests\CreateMessage; use App\Http\Requests\SortTickets; use App\Http\Requests\StoreTicket; use App\Http\Requests\UpdateTicket; -use App\Jobs\SendTicketMentionMail; use App\Mail\NewTicket; -use App\Mail\TicketMention; use App\Models\Message; use App\Models\Project; use App\Models\Ticket; use App\Models\User; use Exception; -use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Database\Eloquent\Builder; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -237,11 +233,11 @@ class TicketController extends Controller $message = new Message($request->validated()); $message->user()->associate(auth()->user()); $message->ticket()->associate($ticket); - $message->saveOrFail(); /** @var \App\Models\User */ $user = auth()->user(); + // Toggle auth user subscription if ($request->subscribe) { if (!$user->subscriptions()->find($ticket->id)) { $user->subscriptions()->attach($ticket->id); @@ -257,35 +253,9 @@ class TicketController extends Controller $fileMessage->move(public_path('fichiers/' . $projectSlug . '/' . $ticket->id . '/'), $fileName); $filePath = 'fichiers/' . $projectSlug . '/' . $ticket->id . '/' . $fileName; $message->file = $filePath; - $message->save(); } - event(new NotifySubscriptions( - $message->ticket, - trans('Nouvelle réponse de :name :
:message', [ - 'name' => $message->user->name, - 'message' => $message->message - ]) - )); - - // find @user + send mail si un seul user est trouvé - $matches = []; - \preg_match_all('/@\w*/', $message->message, $matches); - $matches = collect($matches[0] ?? [])->unique(); - foreach ($matches as $pseudo_usertag) { - try { - $user = User::where('name', 'LIKE', '%' . ltrim($pseudo_usertag, '@') . '%') - ->whereDoesntHave('subscriptions', function ($q) use ($ticket) { - $q->where('id', $ticket->id); - })->firstOrFail(); - SendTicketMentionMail::dispatchAfterResponse( - $user, - new TicketMention($ticket, $message->message) - ); - } catch (ModelNotFoundException $e) { - continue; - } - } + $message->saveOrFail(); return back(); } diff --git a/app/Listeners/AddStatusMessages.php b/app/Listeners/AddStatusMessages.php index 1c05a72..fa71d25 100644 --- a/app/Listeners/AddStatusMessages.php +++ b/app/Listeners/AddStatusMessages.php @@ -7,16 +7,6 @@ use App\Models\Message; class AddStatusMessages { - /** - * Create the event listener. - * - * @return void - */ - public function __construct() - { - // - } - /** * Handle the event. * diff --git a/app/Listeners/SendNotificationMailToTicketCreator.php b/app/Listeners/SendNotificationMailToTicketCreator.php new file mode 100644 index 0000000..b7089bb --- /dev/null +++ b/app/Listeners/SendNotificationMailToTicketCreator.php @@ -0,0 +1,26 @@ +ticket; + Mail::to($ticket->user->email) + ->send(new TicketUpdate($ticket, $event->corpsMaj)); + } +} diff --git a/app/Listeners/SendNotificationMail.php b/app/Listeners/SendSubscriptionsNotificationsMail.php similarity index 54% rename from app/Listeners/SendNotificationMail.php rename to app/Listeners/SendSubscriptionsNotificationsMail.php index fc9531e..00fecff 100644 --- a/app/Listeners/SendNotificationMail.php +++ b/app/Listeners/SendSubscriptionsNotificationsMail.php @@ -4,13 +4,12 @@ namespace App\Listeners; use App\Events\NotifySubscriptions; use App\Mail\TicketUpdate; -use App\Models\User; use Illuminate\Contracts\Queue\ShouldQueue; use Illuminate\Queue\InteractsWithQueue; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\Mail; -class SendNotificationMail +class SendSubscriptionsNotificationsMail { /** * Handle the event. @@ -20,9 +19,15 @@ class SendNotificationMail */ public function handle(NotifySubscriptions $event) { + $ignoreConnectedUserEmail = Auth::user()->email ?? ''; + $ignoreUsers = $event->ignoreUsers ?? collect(); foreach ($event->ticket->subscriptions as $sub) { - if (Auth::user() and $sub->email !== Auth::user()->email) { - Mail::to($sub->email)->send(new TicketUpdate($event->ticket, $event->corpsMaj)); + if ( + $sub->email !== $ignoreConnectedUserEmail and + !$ignoreUsers->contains('email', $sub->email) + ) { + Mail::to($sub->email) + ->send(new TicketUpdate($event->ticket, $event->corpsMaj)); } } } diff --git a/app/Models/Message.php b/app/Models/Message.php index bf61f6c..eebe2d1 100644 --- a/app/Models/Message.php +++ b/app/Models/Message.php @@ -2,10 +2,14 @@ namespace App\Models; -use App\Enums\TicketType; +use App\Enums\Role; use App\Events\NotifySubscriptions; +use App\Events\NotifyTicketCreator; +use App\Jobs\SendTicketMentionMail; +use App\Mail\TicketMention; use Illuminate\Database\Eloquent\Factories\HasFactory; use Illuminate\Database\Eloquent\Model; +use Illuminate\Database\Eloquent\ModelNotFoundException; use Illuminate\Http\UploadedFile; class Message extends Model @@ -16,6 +20,65 @@ class Message extends Model 'message' ]; + protected static function booted() + { + static::created(function (Message $message) { + $ticket = $message->ticket; + if ($message->user) { + $ticket->load('user'); + if ($ticket->user !== $message->user) { + event(new NotifyTicketCreator( + $ticket, + trans('Nouvelle réponse de :name :
:message sur votre ticket', [ + 'name' => $message->user->name, + 'message' => $message->message + ]) + )); + } + // find @user + send mail si un seul user est trouvé + $usersNotified = collect([]); + $matches = []; + $ticket->load('project'); + \preg_match_all('/@\w*/', $message->message, $matches); + $matches = collect($matches[0] ?? [])->unique(); + foreach ($matches as $pseudo_usertag) { + try { + $user = User::where('name', 'LIKE', '%' . ltrim($pseudo_usertag, '@') . '%') + ->where('email', '!=', $ticket->user->email) + ->where(function ($q) use ($ticket) { + $q->whereHas('projects', function ($q) use ($ticket) { + $q->where('id', $ticket->project->id); + })->orWhere('role', Role::admin()->value); + })->firstOrFail(); + $usersNotified->add($user); + SendTicketMentionMail::dispatchAfterResponse( + $user, + new TicketMention($ticket, $message->message) + ); + } catch (ModelNotFoundException $e) { + continue; + } + } + + event(new NotifySubscriptions( + $message->ticket, + trans('Nouvelle réponse de :name :
:message', [ + 'name' => $message->user->name, + 'message' => $message->message + ]), + $usersNotified + )); + } else { + event(new NotifyTicketCreator( + $ticket, + trans('Votre ticket : :message', [ + 'message' => $message->message + ]) + )); + } + }); + } + public function ticket() { return $this->belongsTo(Ticket::class, 'ticket_id'); diff --git a/app/Providers/EventServiceProvider.php b/app/Providers/EventServiceProvider.php index 3b8ac12..de9563c 100644 --- a/app/Providers/EventServiceProvider.php +++ b/app/Providers/EventServiceProvider.php @@ -2,13 +2,20 @@ namespace App\Providers; +use App\Events\NotifySubscriptions; +use App\Events\NotifyTicketCreator; +use App\Events\TicketStatusChanged; +use App\Listeners\AddStatusMessages; +use App\Listeners\SendNotificationMail; +use App\Listeners\SendNotificationMailToTicketCreator; +use App\Listeners\SendSubscriptionsNotificationsMail; use Illuminate\Auth\Events\Registered; use Illuminate\Auth\Listeners\SendEmailVerificationNotification; use Illuminate\Foundation\Support\Providers\EventServiceProvider as ServiceProvider; -use Illuminate\Support\Facades\Event; class EventServiceProvider extends ServiceProvider { + /** * The event listener mappings for the application. * @@ -18,11 +25,14 @@ class EventServiceProvider extends ServiceProvider Registered::class => [ SendEmailVerificationNotification::class, ], - 'App\Events\TicketStatusChanged' => [ - 'App\Listeners\AddStatusMessages', + TicketStatusChanged::class => [ + AddStatusMessages::class ], - 'App\Events\NotifySubscriptions' => [ - 'App\Listeners\SendNotificationMail' + NotifySubscriptions::class => [ + SendSubscriptionsNotificationsMail::class + ], + NotifyTicketCreator::class => [ + SendNotificationMailToTicketCreator::class ], ]; From 3b0dade3462982509d74509d518776ac960930cc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Fri, 23 Jul 2021 10:17:18 +0200 Subject: [PATCH 11/45] Ticket 262 --- resources/views/emails/mail-created-plain.blade.php | 6 +++++- resources/views/emails/mail-created.blade.php | 4 +++- 2 files changed, 8 insertions(+), 2 deletions(-) diff --git a/resources/views/emails/mail-created-plain.blade.php b/resources/views/emails/mail-created-plain.blade.php index af3eb5b..b987446 100644 --- a/resources/views/emails/mail-created-plain.blade.php +++ b/resources/views/emails/mail-created-plain.blade.php @@ -1,4 +1,8 @@ Bonjour {{ $user->name }}, -Votre compte {{ config('app.name') }} vient d'être créé. Votre identifiant est votre email. +Votre compte {{ config('app.name') }} vient d'être créé. + +Vous pouvez vous y connecter sur {{ config('app.url') }} + +Votre identifiant est votre email. Votre mot de passe est le suivant: {{$pwd }} Merci d'enregistrer celui-ci dans un gestionnaire de mot de passe et de supprimer cet email au plus vite. diff --git a/resources/views/emails/mail-created.blade.php b/resources/views/emails/mail-created.blade.php index 0bf4f87..c60da03 100644 --- a/resources/views/emails/mail-created.blade.php +++ b/resources/views/emails/mail-created.blade.php @@ -6,7 +6,9 @@

Bonjour {{ $user->name }},

-

Votre compte {{ config('app.name') }} vient d'être créé. Votre identifiant est votre email.

+

Votre compte {{ config('app.name') }} vient d'être créé


+

Vous pouvez vous y connecter sur {{ config('app.url') }}


+

Votre identifiant est votre email.

Votre mot de passe est le suivant : {{$pwd }}

Merci d'enregistrer celui-ci dans un gestionnaire de mot de passe et de supprimer cet email au plus vite.

From 4e3a1635eec5333f5b5713cd1983e6a9466f2cc4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Fri, 23 Jul 2021 11:04:09 +0200 Subject: [PATCH 12/45] Add developper role --- app/Console/Commands/CreateUser.php | 10 ---------- app/Enums/Role.php | 3 +++ app/Http/Controllers/TicketController.php | 2 +- app/Http/Middleware/IsAdmin.php | 5 +++-- app/Http/Requests/ChangeTicketStatus.php | 5 +++-- app/Http/Requests/CreateMessage.php | 8 ++++++-- app/Http/Requests/StoreProject.php | 5 +++-- app/Http/Requests/StoreTicket.php | 12 ++++++++---- app/Http/Requests/UpdateTicket.php | 6 ++++-- app/Models/Message.php | 3 ++- app/Models/Project.php | 4 +++- app/Models/User.php | 15 ++++++++++++++- app/Policies/Rules/UserRoleRules.php | 2 +- app/Policies/TicketPolicy.php | 15 ++++++--------- resources/views/layout/app.blade.php | 2 +- resources/views/ticket/form-inputs.blade.php | 2 +- resources/views/ticket/index.blade.php | 4 ++-- 17 files changed, 61 insertions(+), 42 deletions(-) diff --git a/app/Console/Commands/CreateUser.php b/app/Console/Commands/CreateUser.php index 16c73ea..42a270f 100644 --- a/app/Console/Commands/CreateUser.php +++ b/app/Console/Commands/CreateUser.php @@ -52,16 +52,6 @@ class CreateUser extends Command $user->role = Role::admin(); } else { $user->role = Role::client(); - try { - $project = Project::where( - 'id', - $this->ask("What's the id of the project (s)he's working on?") - )->firstOrFail(); - $user->projects()->sync([$project->id]); - } catch (ModelNotFoundException $e) { - $this->error('The project does not exists'); - return -1; - } } $user->password = Hash::make($pwd); $user->save(); diff --git a/app/Enums/Role.php b/app/Enums/Role.php index 4bd4d9b..d4a65a0 100644 --- a/app/Enums/Role.php +++ b/app/Enums/Role.php @@ -5,6 +5,7 @@ namespace App\Enums; use Kwaadpepper\Enum\BaseEnum; /** + * @method static self developper() * @method static self admin() * @method static self client() */ @@ -14,6 +15,7 @@ class Role extends BaseEnum protected static function values(): array { return [ + 'developper' => 0, 'admin' => 1, 'client' => 2 ]; @@ -22,6 +24,7 @@ class Role extends BaseEnum protected static function labels(): array { return [ + 'developper' => trans('Developpeur'), 'admin' => trans('Administrateur'), 'client' => trans('Client') ]; diff --git a/app/Http/Controllers/TicketController.php b/app/Http/Controllers/TicketController.php index b3dadab..732806b 100644 --- a/app/Http/Controllers/TicketController.php +++ b/app/Http/Controllers/TicketController.php @@ -36,7 +36,7 @@ class TicketController extends Controller /** @var \App\Models\User */ $user = auth()->user(); $tickets = Ticket::with('project')->has('project'); - if (!$user->role->equals(Role::admin())) { + if (!$user->isAdmin()) { $tickets = $tickets->whereHas('project', function ($q) use ($user) { $q->whereHas('users', function ($q) use ($user) { $q->whereId($user->id); diff --git a/app/Http/Middleware/IsAdmin.php b/app/Http/Middleware/IsAdmin.php index 0e9a7de..138af08 100644 --- a/app/Http/Middleware/IsAdmin.php +++ b/app/Http/Middleware/IsAdmin.php @@ -5,7 +5,6 @@ namespace App\Http\Middleware; use App\Enums\Role; use Closure; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Auth; class IsAdmin { @@ -18,7 +17,9 @@ class IsAdmin */ public function handle(Request $request, Closure $next) { - if (Auth::user()->role->equals(Role::admin())) { + /** @var \App\Models\User */ + $user = auth()->user(); + if ($user->isAdmin()) { return $next($request); } return redirect()->route('home'); diff --git a/app/Http/Requests/ChangeTicketStatus.php b/app/Http/Requests/ChangeTicketStatus.php index 8386c9d..d60fdc4 100644 --- a/app/Http/Requests/ChangeTicketStatus.php +++ b/app/Http/Requests/ChangeTicketStatus.php @@ -15,8 +15,9 @@ class ChangeTicketStatus extends FormRequest */ public function authorize() { - return auth()->check() and - auth()->user()->role->equals(Role::admin()); + /** @var \App\Models\User */ + $user = auth()->user(); + return auth()->check() and $user->isAdmin(); } /** diff --git a/app/Http/Requests/CreateMessage.php b/app/Http/Requests/CreateMessage.php index cd9f9cd..301635e 100644 --- a/app/Http/Requests/CreateMessage.php +++ b/app/Http/Requests/CreateMessage.php @@ -14,10 +14,12 @@ class CreateMessage extends FormRequest */ public function authorize() { + /** @var \App\Models\User */ + $user = auth()->user(); $this->merge([ 'subscribe' => $this->subscribe ? true : false ]); - return auth()->check() and (auth()->user()->role->equals(Role::admin()) or + return auth()->check() and ($user->isAdmin() or auth()->user()->projects->contains(request()->route()->ticket->project_id)); } @@ -28,9 +30,11 @@ class CreateMessage extends FormRequest */ public function rules() { + /** @var \App\Models\User */ + $user = auth()->user(); return [ 'subscribe' => 'required|boolean', - 'message' => 'required|min:' . (auth()->user()->role->equals(Role::admin()) ? '5' : '20'), + 'message' => 'required|min:' . ($user->isAdmin() ? '5' : '20'), 'file_message' => 'sometimes|mimes:jpeg,jpg,png,pdf|max:2048' ]; } diff --git a/app/Http/Requests/StoreProject.php b/app/Http/Requests/StoreProject.php index 162b683..46fb91a 100644 --- a/app/Http/Requests/StoreProject.php +++ b/app/Http/Requests/StoreProject.php @@ -14,8 +14,9 @@ class StoreProject extends FormRequest */ public function authorize() { - return auth()->check() and - auth()->user()->role->equals(Role::admin()); + /** @var \App\Models\User */ + $user = auth()->user(); + return auth()->check() and $user->isAdmin(); } /** diff --git a/app/Http/Requests/StoreTicket.php b/app/Http/Requests/StoreTicket.php index 741d9e8..71f08a3 100644 --- a/app/Http/Requests/StoreTicket.php +++ b/app/Http/Requests/StoreTicket.php @@ -16,7 +16,9 @@ class StoreTicket extends FormRequest */ public function authorize() { - if (!auth()->user()->role->equals(Role::admin())) { + /** @var \App\Models\User */ + $user = auth()->user(); + if (!$user->isAdmin()) { $this->merge([ 'status' => TicketStatus::new()->value, ]); @@ -37,12 +39,14 @@ class StoreTicket extends FormRequest 'exists:projects,id', // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed function ($attribute, $value, $fail) { - if (auth()->user()->role->equals(Role::admin())) { + /** @var \App\Models\User */ + $user = auth()->user(); + if ($user->isAdmin()) { return; } - if (!in_array($value, auth()->user()->projects()->pluck('id')->all())) { + if (!in_array($value, $user->projects()->pluck('id')->all())) { $fail(__('Veuillez choisir entre :values', [ - 'values' => auth()->user()->projects()->pluck('name')->implode(',') + 'values' => $user->projects()->pluck('name')->implode(',') ])); } } diff --git a/app/Http/Requests/UpdateTicket.php b/app/Http/Requests/UpdateTicket.php index 040bde7..3dae5a1 100644 --- a/app/Http/Requests/UpdateTicket.php +++ b/app/Http/Requests/UpdateTicket.php @@ -9,12 +9,14 @@ class UpdateTicket extends StoreTicket { public function authorize() { - if (!auth()->user()->role->equals(Role::admin())) { + /** @var \App\Models\User */ + $user = auth()->user(); + if (!$user->isAdmin()) { $this->merge([ 'status' => $this->project->status->value, ]); } - return auth()->check() and (auth()->user()->role->equals(Role::admin()) or + return auth()->check() and ($user->isAdmin() or request()->route()->ticket->created_by === auth()->user()->id); } } diff --git a/app/Models/Message.php b/app/Models/Message.php index eebe2d1..f338502 100644 --- a/app/Models/Message.php +++ b/app/Models/Message.php @@ -48,7 +48,8 @@ class Message extends Model ->where(function ($q) use ($ticket) { $q->whereHas('projects', function ($q) use ($ticket) { $q->where('id', $ticket->project->id); - })->orWhere('role', Role::admin()->value); + })->orWhere('role', Role::admin()->value) + ->orWhere('role', Role::developper()->value); })->firstOrFail(); $usersNotified->add($user); SendTicketMentionMail::dispatchAfterResponse( diff --git a/app/Models/Project.php b/app/Models/Project.php index 58bff7c..e2946da 100644 --- a/app/Models/Project.php +++ b/app/Models/Project.php @@ -50,7 +50,9 @@ class Project extends Model 'belongsToManyLabel' => 'name', 'nullable' => true, 'readonly' => function () { - return auth()->user()->role->equals(Role::admin()) ? false : true; + /** @var \App\Models\User */ + $user = auth()->user(); + return $user->isAdmin(); }, 'actions' => [ CrudAction::viewAny(), diff --git a/app/Models/User.php b/app/Models/User.php index 8e0f7ef..0be8db9 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -130,7 +130,9 @@ class User extends Authenticatable 'belongsToManyLabel' => 'name', 'nullable' => true, 'readonly' => function () { - return auth()->user()->role->equals(Role::admin()) ? false : true; + /** @var \App\Models\User */ + $user = auth()->user(); + return $user->isAdmin(); }, 'actions' => [ CrudAction::viewAny(), @@ -185,4 +187,15 @@ class User extends Authenticatable { dispatch(new SendUserCreatedEmail($this)); } + + /** + * Is the user an admin or a developper ? + * + * @return boolean + */ + public function isAdmin(): bool + { + return ($this->role->equals(Role::developper()) or + $this->role->equals(Role::admin())); + } } diff --git a/app/Policies/Rules/UserRoleRules.php b/app/Policies/Rules/UserRoleRules.php index afbfd55..27010db 100644 --- a/app/Policies/Rules/UserRoleRules.php +++ b/app/Policies/Rules/UserRoleRules.php @@ -15,6 +15,6 @@ abstract class UserRoleRules extends StaticRules protected static function userIsAdmin(User $user) { - return $user->role->equals(Role::admin()); + return $user->isAdmin(); } } diff --git a/app/Policies/TicketPolicy.php b/app/Policies/TicketPolicy.php index c6b3e90..5372d80 100644 --- a/app/Policies/TicketPolicy.php +++ b/app/Policies/TicketPolicy.php @@ -60,7 +60,7 @@ class TicketPolicy */ public function update(User $user, Ticket $ticket) { - return Auth::user()->role->equals(Role::admin()) or $user->projects->contains($ticket->project_id); + return $user->isAdmin() or $user->projects->contains($ticket->project_id); } /** @@ -85,7 +85,7 @@ class TicketPolicy */ public function restore(User $user, Ticket $ticket) { - return Auth::user()->role->equals(Role::admin()) or $user->projects->contains($ticket->project_id); + return $user->isAdmin() or $user->projects->contains($ticket->project_id); } /** @@ -103,7 +103,9 @@ class TicketPolicy public function changeStatus(User $user) { - return $user->role->equals(Role::admin()); + /** @var \App\Models\User */ + $user = auth()->user(); + return $user->isAdmin(); } // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundBeforeLastUsed @@ -119,12 +121,7 @@ class TicketPolicy //role == 1 // OR project_id IN user->projects - if ( - !( - $user->role->equals(Role::admin()) - or $user->projects->contains($ticket->project_id) ) - ) - { + if (!($user->isAdmin() or $user->projects->contains($ticket->project_id))) { return Response::deny(trans('Vous ne pouvez modifier un ticket qui ne vous appartient pas.')); } return $ticket->status->equals(TicketStatus::archived()) ? diff --git a/resources/views/layout/app.blade.php b/resources/views/layout/app.blade.php index e611d89..61f020a 100644 --- a/resources/views/layout/app.blade.php +++ b/resources/views/layout/app.blade.php @@ -24,7 +24,7 @@ @auth
{{ __('Messages') }} - @if(auth()->user()->role->equals(Role::admin())) + @if(auth()->user()->isAdmin()) {{ __('Modifier') }} @endif @can('delete', $ticket) From ce461a403b64daa362a764784094568fa4e66ba3 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?J=C3=A9r=C3=A9my=20Munsch?= Date: Fri, 23 Jul 2021 11:34:16 +0200 Subject: [PATCH 13/45] Change projects table to sites table --- app/Console/Commands/CreateUser.php | 2 +- app/Http/Controllers/ProjectController.php | 12 ----- app/Http/Controllers/SiteController.php | 12 +++++ app/Http/Controllers/TicketController.php | 50 +++++++++---------- app/Http/Requests/CreateMessage.php | 2 +- app/Http/Requests/SortTickets.php | 2 +- .../{StoreProject.php => StoreSite.php} | 2 +- app/Http/Requests/StoreTicket.php | 8 +-- .../{UpdateProject.php => UpdateSite.php} | 2 +- app/Http/Requests/UpdateTicket.php | 3 +- app/Models/Message.php | 16 +++--- app/Models/{Project.php => Site.php} | 20 ++++---- app/Models/{ProjectUser.php => SiteUser.php} | 2 +- app/Models/Ticket.php | 16 +++--- app/Models/User.php | 8 +-- app/Policies/AppPolicies.php | 2 +- .../{ProjectPolicy.php => SitePolicy.php} | 2 +- app/Policies/TicketPolicy.php | 8 +-- app/Providers/AuthServiceProvider.php | 2 +- app/Providers/RouteServiceProvider.php | 6 +-- .../2020_11_13_152248_create_projects.php | 2 +- ...06_17_173912_create_project_user_table.php | 10 ++-- ..._28_163755_add_soft_delete_on_projects.php | 2 +- ...rename_projects_table_into_sites_table.php | 40 +++++++++++++++ resources/views/emails/new-ticket.blade.php | 2 +- .../views/emails/ticket-mention.blade.php | 2 +- .../views/emails/ticket-update.blade.php | 2 +- resources/views/layout/app.blade.php | 6 +-- resources/views/ticket/form-inputs.blade.php | 14 +++--- resources/views/ticket/index.blade.php | 16 +++--- resources/views/ticket/show.blade.php | 2 +- routes/web.php | 6 +-- 32 files changed, 160 insertions(+), 121 deletions(-) delete mode 100644 app/Http/Controllers/ProjectController.php create mode 100644 app/Http/Controllers/SiteController.php rename app/Http/Requests/{StoreProject.php => StoreSite.php} (93%) rename app/Http/Requests/{UpdateProject.php => UpdateSite.php} (50%) rename app/Models/{Project.php => Site.php} (82%) rename app/Models/{ProjectUser.php => SiteUser.php} (78%) rename app/Policies/{ProjectPolicy.php => SitePolicy.php} (78%) create mode 100644 database/migrations/2021_07_23_111336_rename_projects_table_into_sites_table.php diff --git a/app/Console/Commands/CreateUser.php b/app/Console/Commands/CreateUser.php index 42a270f..8003d3b 100644 --- a/app/Console/Commands/CreateUser.php +++ b/app/Console/Commands/CreateUser.php @@ -3,7 +3,7 @@ namespace App\Console\Commands; use App\Enums\Role; -use App\Models\Project; +use App\Models\Site; use App\Models\User; use Illuminate\Console\Command; use Illuminate\Database\Eloquent\ModelNotFoundException; diff --git a/app/Http/Controllers/ProjectController.php b/app/Http/Controllers/ProjectController.php deleted file mode 100644 index ab43dd2..0000000 --- a/app/Http/Controllers/ProjectController.php +++ /dev/null @@ -1,12 +0,0 @@ -user(); - $tickets = Ticket::with('project')->has('project'); + $tickets = Ticket::with('site')->has('site'); if (!$user->isAdmin()) { - $tickets = $tickets->whereHas('project', function ($q) use ($user) { + $tickets = $tickets->whereHas('site', function ($q) use ($user) { $q->whereHas('users', function ($q) use ($user) { $q->whereId($user->id); }); @@ -50,9 +50,9 @@ class TicketController extends Controller $tickets = $this->filterTickets($tickets, $request); $tickets = $tickets->paginate(); - $projects = Project::select('id', 'name')->orderBy('name')->get(); + $sites = Site::select('id', 'name')->orderBy('name')->get(); - return view('ticket.index', compact('tickets', 'projects')); + return view('ticket.index', compact('tickets', 'sites')); } private function filterTickets(Builder $tickets, Request $request): Builder @@ -77,14 +77,14 @@ class TicketController extends Controller Session::save(); if (Session::has('tickets.pr')) { - $tickets = $tickets->where('project_id', Session::get('tickets.pr')); + $tickets = $tickets->where('site_id', Session::get('tickets.pr')); } if ( Session::has('tickets.sort_col') and Session::has('tickets.sort_way') and in_array(Session::get('tickets.sort_col'), [ - 'id', 'project_id', 'created_at', 'created_by', + 'id', 'site_id', 'created_at', 'created_by', 'type', 'status' ]) ) { @@ -139,29 +139,29 @@ class TicketController extends Controller { $user = Auth::user(); if ($user->role->value === 1) { - $projects = Project::orderBy('name')->get(); + $sites = Site::orderBy('name')->get(); } else { - $projects = $user->projects; + $sites = $user->sites; } - if (!count($projects)) { - return redirect()->route('project.create') + if (!count($sites)) { + return redirect()->route('site.create') ->with('warning', 'Vous devez tout d\'abord créer un projet pour y ajouter un ticket'); } - return view('ticket.create', compact('projects')); + return view('ticket.create', compact('sites')); } public function store(StoreTicket $request) { - $project = Project::findOrFail($request->project_id); + $site = Site::findOrFail($request->site_id); $ticket = new Ticket($request->validated()); if ($request->file_ticket) { - $ticket->file = Ticket::saveFile($project, $ticket, $ticket->type, $request->file_ticket); + $ticket->file = Ticket::saveFile($site, $ticket, $ticket->type, $request->file_ticket); } if ($request->file_ticket2) { - $ticket->file2 = Ticket::saveFile($project, $ticket, $ticket->type, $request->file_ticket2); + $ticket->file2 = Ticket::saveFile($site, $ticket, $ticket->type, $request->file_ticket2); } if ($request->type === TicketType::evolution()) { @@ -188,29 +188,29 @@ class TicketController extends Controller { $user = Auth::user(); if ($user->role->value === 1) { - $projects = Project::orderBy('name')->get(); + $sites = Site::orderBy('name')->get(); } else { - $projects = $user->projects; + $sites = $user->sites; } - return view('ticket.edit', compact('ticket', 'projects')); + return view('ticket.edit', compact('ticket', 'sites')); } public function update(UpdateTicket $request, Ticket $ticket) { - $project = Project::findOrFail($request->project_id); + $site = Site::findOrFail($request->site_id); $ticket->fill($request->validated()); if ($request->file_ticket) { if (File::exists($ticket->file)) { File::delete($ticket->file); } - $ticket->file = Ticket::saveFile($project, $ticket, $ticket->type, $request->file_ticket); + $ticket->file = Ticket::saveFile($site, $ticket, $ticket->type, $request->file_ticket); } if ($request->file_ticket2) { if (File::exists($ticket->file2)) { File::delete($ticket->file2); } - $ticket->file2 = Ticket::saveFile($project, $ticket, $ticket->type, $request->file_ticket2); + $ticket->file2 = Ticket::saveFile($site, $ticket, $ticket->type, $request->file_ticket2); } $ticket->save(); @@ -247,11 +247,11 @@ class TicketController extends Controller } if ($request->file_message) { - $projectSlug = Str::slug($ticket->project->name); + $siteSlug = Str::slug($ticket->site->name); $fileMessage = $request->file_message; - $fileName = $projectSlug . '-ticket-' . $ticket->id . '-message-' . $message->id . '.' . $fileMessage->extension(); - $fileMessage->move(public_path('fichiers/' . $projectSlug . '/' . $ticket->id . '/'), $fileName); - $filePath = 'fichiers/' . $projectSlug . '/' . $ticket->id . '/' . $fileName; + $fileName = $siteSlug . '-ticket-' . $ticket->id . '-message-' . $message->id . '.' . $fileMessage->extension(); + $fileMessage->move(public_path('fichiers/' . $siteSlug . '/' . $ticket->id . '/'), $fileName); + $filePath = 'fichiers/' . $siteSlug . '/' . $ticket->id . '/' . $fileName; $message->file = $filePath; } diff --git a/app/Http/Requests/CreateMessage.php b/app/Http/Requests/CreateMessage.php index 301635e..71b5086 100644 --- a/app/Http/Requests/CreateMessage.php +++ b/app/Http/Requests/CreateMessage.php @@ -20,7 +20,7 @@ class CreateMessage extends FormRequest 'subscribe' => $this->subscribe ? true : false ]); return auth()->check() and ($user->isAdmin() or - auth()->user()->projects->contains(request()->route()->ticket->project_id)); + auth()->user()->sites->contains(request()->route()->ticket->site_id)); } /** diff --git a/app/Http/Requests/SortTickets.php b/app/Http/Requests/SortTickets.php index d60352f..a70b880 100644 --- a/app/Http/Requests/SortTickets.php +++ b/app/Http/Requests/SortTickets.php @@ -38,7 +38,7 @@ class SortTickets extends FormRequest } } ], - 'pr' => 'sometimes|int|exists:projects,id' + 'pr' => 'sometimes|int|exists:sites,id' ]; } } diff --git a/app/Http/Requests/StoreProject.php b/app/Http/Requests/StoreSite.php similarity index 93% rename from app/Http/Requests/StoreProject.php rename to app/Http/Requests/StoreSite.php index 46fb91a..e8a5fa2 100644 --- a/app/Http/Requests/StoreProject.php +++ b/app/Http/Requests/StoreSite.php @@ -5,7 +5,7 @@ namespace App\Http\Requests; use App\Enums\Role; use Illuminate\Foundation\Http\FormRequest; -class StoreProject extends FormRequest +class StoreSite extends FormRequest { /** * Determine if the user is authorized to make this request. diff --git a/app/Http/Requests/StoreTicket.php b/app/Http/Requests/StoreTicket.php index 71f08a3..7ea4ea8 100644 --- a/app/Http/Requests/StoreTicket.php +++ b/app/Http/Requests/StoreTicket.php @@ -34,9 +34,9 @@ class StoreTicket extends FormRequest public function rules() { return [ - 'project_id' => [ + 'site_id' => [ 'required', - 'exists:projects,id', + 'exists:sites,id', // @phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed function ($attribute, $value, $fail) { /** @var \App\Models\User */ @@ -44,9 +44,9 @@ class StoreTicket extends FormRequest if ($user->isAdmin()) { return; } - if (!in_array($value, $user->projects()->pluck('id')->all())) { + if (!in_array($value, $user->sites()->pluck('id')->all())) { $fail(__('Veuillez choisir entre :values', [ - 'values' => $user->projects()->pluck('name')->implode(',') + 'values' => $user->sites()->pluck('name')->implode(',') ])); } } diff --git a/app/Http/Requests/UpdateProject.php b/app/Http/Requests/UpdateSite.php similarity index 50% rename from app/Http/Requests/UpdateProject.php rename to app/Http/Requests/UpdateSite.php index 2cc5353..350d7a8 100644 --- a/app/Http/Requests/UpdateProject.php +++ b/app/Http/Requests/UpdateSite.php @@ -2,6 +2,6 @@ namespace App\Http\Requests; -class UpdateProject extends StoreProject +class UpdateSite extends StoreSite { } diff --git a/app/Http/Requests/UpdateTicket.php b/app/Http/Requests/UpdateTicket.php index 3dae5a1..0833698 100644 --- a/app/Http/Requests/UpdateTicket.php +++ b/app/Http/Requests/UpdateTicket.php @@ -12,8 +12,7 @@ class UpdateTicket extends StoreTicket /** @var \App\Models\User */ $user = auth()->user(); if (!$user->isAdmin()) { - $this->merge([ - 'status' => $this->project->status->value, + $this->merge(['status' => $this->site->status->value, ]); } return auth()->check() and ($user->isAdmin() or diff --git a/app/Models/Message.php b/app/Models/Message.php index f338502..3af559f 100644 --- a/app/Models/Message.php +++ b/app/Models/Message.php @@ -38,7 +38,7 @@ class Message extends Model // find @user + send mail si un seul user est trouvé $usersNotified = collect([]); $matches = []; - $ticket->load('project'); + $ticket->load('site'); \preg_match_all('/@\w*/', $message->message, $matches); $matches = collect($matches[0] ?? [])->unique(); foreach ($matches as $pseudo_usertag) { @@ -46,8 +46,8 @@ class Message extends Model $user = User::where('name', 'LIKE', '%' . ltrim($pseudo_usertag, '@') . '%') ->where('email', '!=', $ticket->user->email) ->where(function ($q) use ($ticket) { - $q->whereHas('projects', function ($q) use ($ticket) { - $q->where('id', $ticket->project->id); + $q->whereHas('sites', function ($q) use ($ticket) { + $q->where('id', $ticket->site->id); })->orWhere('role', Role::admin()->value) ->orWhere('role', Role::developper()->value); })->firstOrFail(); @@ -90,18 +90,18 @@ class Message extends Model return $this->belongsTo(User::class, 'user_id'); } - public function saveFile(Project $project, Ticket $ticket, UploadedFile $file) + public function saveFile(Site $site, Ticket $ticket, UploadedFile $file) { - $projectAssetFullPath = Project::ticketAssetsFullPath($project->slug_name); - $fileAssetPath = Project::ticketAssetsPath($project->slug_name); + $siteAssetFullPath = Site::ticketAssetsFullPath($site->slug_name); + $fileAssetPath = Site::ticketAssetsPath($site->slug_name); $fileName = sprintf( '%s-%s-%d-%d.%s', - $project->slug_name, + $site->slug_name, $ticket->id, rand(), $file->extension() ); - $file->move(sprintf('%s/messages/%d', $projectAssetFullPath, $ticket->id), $fileName); + $file->move(sprintf('%s/messages/%d', $siteAssetFullPath, $ticket->id), $fileName); return sprintf('%s/%d/%s', $fileAssetPath, $ticket->id, $fileName); } } diff --git a/app/Models/Project.php b/app/Models/Site.php similarity index 82% rename from app/Models/Project.php rename to app/Models/Site.php index e2946da..01f7d78 100644 --- a/app/Models/Project.php +++ b/app/Models/Site.php @@ -12,7 +12,7 @@ use Illuminate\Database\Eloquent\SoftDeletes; use Illuminate\Support\Facades\File; use Illuminate\Support\Str; -class Project extends Model +class Site extends Model { use HasFactory; use IsCrudModel; @@ -67,24 +67,24 @@ class Project extends Model protected static function booted() { - static::created(function (Project $project) { - $path = Project::ticketAssetsFullPath($project->slug_name); + static::created(function (Site $site) { + $path = Site::ticketAssetsFullPath($site->slug_name); if (!File::exists($path)) { File::makeDirectory($path, 0755, true); } }); - static::updating(function (Project $project) { - $oldName = Project::where('id', $project->id)->first()->name; - $oldPath = Project::ticketAssetsFullPath($oldName); - $newPath = Project::ticketAssetsFullPath($project->slug_name); + static::updating(function (Site $site) { + $oldName = Site::where('id', $site->id)->first()->name; + $oldPath = Site::ticketAssetsFullPath($oldName); + $newPath = Site::ticketAssetsFullPath($site->slug_name); if (File::exists($oldPath)) { File::move($oldPath, $newPath); } else { File::makeDirectory($newPath, 0755, true); } }); - static::deleted(function (Project $project) { - $path = Project::ticketAssetsFullPath($project->slug_name); + static::deleted(function (Site $site) { + $path = Site::ticketAssetsFullPath($site->slug_name); if (File::exists($path)) { File::deleteDirectory($path); } @@ -98,7 +98,7 @@ class Project extends Model public function tickets() { - return $this->hasMany(Ticket::class, 'project_id'); + return $this->hasMany(Ticket::class, 'site_id'); } public function getSlugNameAttribute() diff --git a/app/Models/ProjectUser.php b/app/Models/SiteUser.php similarity index 78% rename from app/Models/ProjectUser.php rename to app/Models/SiteUser.php index 5d2558e..a2ce503 100644 --- a/app/Models/ProjectUser.php +++ b/app/Models/SiteUser.php @@ -4,7 +4,7 @@ namespace App\Models; use Illuminate\Database\Eloquent\Relations\Pivot; -class ProjectUser extends Pivot +class SiteUser extends Pivot { public $timestamps = false; diff --git a/app/Models/Ticket.php b/app/Models/Ticket.php index e68fa87..bca5c2f 100644 --- a/app/Models/Ticket.php +++ b/app/Models/Ticket.php @@ -22,7 +22,7 @@ class Ticket extends Model ]; protected $fillable = [ - 'project_id', + 'site_id', 'type', 'status', 'text' @@ -48,9 +48,9 @@ class Ticket extends Model }); } - public function project() + public function site() { - return $this->belongsTo(Project::class); + return $this->belongsTo(Site::class); } public function user() @@ -68,19 +68,19 @@ class Ticket extends Model return $this->belongsToMany(User::class, 'subscriptions'); } - public static function saveFile(Project $project, Ticket $ticket, TicketType $type, UploadedFile $file) + public static function saveFile(Site $site, Ticket $ticket, TicketType $type, UploadedFile $file) { - $projectAssetFullPath = Project::ticketAssetsFullPath($project->slug_name); - $fileAssetPath = Project::ticketAssetsPath($project->slug_name); + $siteAssetFullPath = Site::ticketAssetsFullPath($site->slug_name); + $fileAssetPath = Site::ticketAssetsPath($site->slug_name); $fileName = sprintf( '%s-%s-%d-%d.%s', - $project->slug_name, + $site->slug_name, $type->getDefinition(), $ticket->id, rand(), $file->extension() ); - $file->move(sprintf('%s/%d', $projectAssetFullPath, $ticket->id), $fileName); + $file->move(sprintf('%s/%d', $siteAssetFullPath, $ticket->id), $fileName); return sprintf('%s/%d/%s', $fileAssetPath, $ticket->id, $fileName); } } diff --git a/app/Models/User.php b/app/Models/User.php index 0be8db9..5240572 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -123,10 +123,10 @@ class User extends Authenticatable CrudAction::update(), ] ], - 'projects' => [ + 'sites' => [ 'label' => trans('Projets'), 'type' => CrudType::belongsToMany(), - 'belongsToMany' => Project::class, + 'belongsToMany' => Site::class, 'belongsToManyLabel' => 'name', 'nullable' => true, 'readonly' => function () { @@ -178,9 +178,9 @@ class User extends Authenticatable return $this->belongsToMany(Ticket::class, 'subscriptions'); } - public function projects() + public function sites() { - return $this->belongsToMany(Project::class); + return $this->belongsToMany(Site::class); } public function sendMailConfirm() diff --git a/app/Policies/AppPolicies.php b/app/Policies/AppPolicies.php index 849952d..deabff6 100644 --- a/app/Policies/AppPolicies.php +++ b/app/Policies/AppPolicies.php @@ -24,7 +24,7 @@ class AppPolicies extends RootPolicy * This first rule to return true in a policy action authorises the action */ $this->policies = [ - 'project' => [ + 'site' => [ 'viewAny' => URR::make('userIsAdmin', $user), 'view' => URR::make('userIsAdmin', $user), 'update' => URR::make('userIsAdmin', $user), diff --git a/app/Policies/ProjectPolicy.php b/app/Policies/SitePolicy.php similarity index 78% rename from app/Policies/ProjectPolicy.php rename to app/Policies/SitePolicy.php index 4ef9498..d9f6c57 100644 --- a/app/Policies/ProjectPolicy.php +++ b/app/Policies/SitePolicy.php @@ -4,7 +4,7 @@ namespace App\Policies; use Illuminate\Auth\Access\HandlesAuthorization; -class ProjectPolicy extends AppPolicies +class SitePolicy extends AppPolicies { use HandlesAuthorization; diff --git a/app/Policies/TicketPolicy.php b/app/Policies/TicketPolicy.php index 5372d80..6581592 100644 --- a/app/Policies/TicketPolicy.php +++ b/app/Policies/TicketPolicy.php @@ -60,7 +60,7 @@ class TicketPolicy */ public function update(User $user, Ticket $ticket) { - return $user->isAdmin() or $user->projects->contains($ticket->project_id); + return $user->isAdmin() or $user->sites->contains($ticket->site_id); } /** @@ -85,7 +85,7 @@ class TicketPolicy */ public function restore(User $user, Ticket $ticket) { - return $user->isAdmin() or $user->projects->contains($ticket->project_id); + return $user->isAdmin() or $user->sites->contains($ticket->site_id); } /** @@ -119,9 +119,9 @@ class TicketPolicy { //can create if //role == 1 - // OR project_id IN user->projects + // OR site_id IN user->sites - if (!($user->isAdmin() or $user->projects->contains($ticket->project_id))) { + if (!($user->isAdmin() or $user->sites->contains($ticket->site_id))) { return Response::deny(trans('Vous ne pouvez modifier un ticket qui ne vous appartient pas.')); } return $ticket->status->equals(TicketStatus::archived()) ? diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 074e26b..565c5af 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -3,7 +3,7 @@ namespace App\Providers; use App\Models\Ticket; -use App\Policies\ProjectPolicy; +use App\Policies\SitePolicy; use App\Policies\TicketPolicy; use Illuminate\Foundation\Support\Providers\AuthServiceProvider as ServiceProvider; diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index 2595412..091d040 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -2,7 +2,7 @@ namespace App\Providers; -use App\Models\Project; +use App\Models\Site; use App\Models\Ticket; use App\Models\User; use Illuminate\Cache\RateLimiting\Limit; @@ -51,9 +51,9 @@ class RouteServiceProvider extends ServiceProvider ->group(base_path('routes/web.php')); }); Route::model('user', User::class); - Route::model('project', Project::class); + Route::model('site', Site::class); Route::bind('ticket', function ($value) { - return Ticket::where('id', $value)->has('project')->firstOrFail(); + return Ticket::where('id', $value)->has('site')->firstOrFail(); }); } diff --git a/database/migrations/2020_11_13_152248_create_projects.php b/database/migrations/2020_11_13_152248_create_projects.php index 132a0b7..92eace6 100644 --- a/database/migrations/2020_11_13_152248_create_projects.php +++ b/database/migrations/2020_11_13_152248_create_projects.php @@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class CreateProjects extends Migration +class CreateSites extends Migration { /** * Run the migrations. diff --git a/database/migrations/2021_06_17_173912_create_project_user_table.php b/database/migrations/2021_06_17_173912_create_project_user_table.php index 88aa981..565f84a 100644 --- a/database/migrations/2021_06_17_173912_create_project_user_table.php +++ b/database/migrations/2021_06_17_173912_create_project_user_table.php @@ -1,13 +1,13 @@ project_id) { - $uP = new ProjectUser(); + $uP = new SiteUser(); $uP->project_id = $user->project_id; $uP->user_id = $user->id; $uP->saveOrFail(); @@ -47,8 +47,8 @@ class CreateProjectUserTable extends Migration $table->foreignId('project_id')->nullable() ->after('role')->constrained('projects'); }); - /** @var \App\Models\ProjectUser */ - foreach (ProjectUser::all() as $uP) { + /** @var \App\Models\SiteUser */ + foreach (SiteUser::all() as $uP) { try { /** @var \App\Models\User */ $user = User::whereId($uP->user_id)->firstOrFail(); diff --git a/database/migrations/2021_06_28_163755_add_soft_delete_on_projects.php b/database/migrations/2021_06_28_163755_add_soft_delete_on_projects.php index b58a5fe..32b84ed 100644 --- a/database/migrations/2021_06_28_163755_add_soft_delete_on_projects.php +++ b/database/migrations/2021_06_28_163755_add_soft_delete_on_projects.php @@ -4,7 +4,7 @@ use Illuminate\Database\Migrations\Migration; use Illuminate\Database\Schema\Blueprint; use Illuminate\Support\Facades\Schema; -class AddSoftDeleteOnProjects extends Migration +class AddSoftDeleteOnSites extends Migration { /** * Run the migrations. diff --git a/database/migrations/2021_07_23_111336_rename_projects_table_into_sites_table.php b/database/migrations/2021_07_23_111336_rename_projects_table_into_sites_table.php new file mode 100644 index 0000000..861cc06 --- /dev/null +++ b/database/migrations/2021_07_23_111336_rename_projects_table_into_sites_table.php @@ -0,0 +1,40 @@ +dropForeign('project_user_project_id_foreign'); + $table->renameColumn('project_id ', 'site_id'); + $table->foreignId('site_id')->constrained('sites'); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::rename('sites', 'projects'); + Schema::rename('site_user', 'project_user'); + Schema::table('project_user', function (Blueprint $table) { + $table->dropForeign('site_user_site_id_foreign'); + $table->renameColumn('site_id ', 'project_id'); + $table->foreignId('project_id')->constrained('projects'); + }); + } +} diff --git a/resources/views/emails/new-ticket.blade.php b/resources/views/emails/new-ticket.blade.php index 4a48997..27b7297 100644 --- a/resources/views/emails/new-ticket.blade.php +++ b/resources/views/emails/new-ticket.blade.php @@ -1,7 +1,7 @@

Bonjour,

Un nouveau ticket (n°{{ $ticket->id }}) a été créer sur le support web :

    -
  • Projet : {{ $ticket->project->name }}
  • +
  • Projet : {{ $ticket->site->name }}
  • Type : {{ $ticket->type->label }}
  • Créé par : {{ $ticket->user->name }}
diff --git a/resources/views/emails/ticket-mention.blade.php b/resources/views/emails/ticket-mention.blade.php index 12399e8..af5d8af 100644 --- a/resources/views/emails/ticket-mention.blade.php +++ b/resources/views/emails/ticket-mention.blade.php @@ -1,7 +1,7 @@

Bonjour,

Vous avez été mentionné sur le ticket n°{{ $ticket->id }}:

    -
  • Projet : {{ $ticket->project->name }}
  • +
  • Projet : {{ $ticket->site->name }}
  • Type : {{ $ticket->type === 0 ? "Bug" : "Évolution" }}
  • Créé par : {{ $ticket->user->name }}
diff --git a/resources/views/emails/ticket-update.blade.php b/resources/views/emails/ticket-update.blade.php index 9b8fcc7..442eda0 100644 --- a/resources/views/emails/ticket-update.blade.php +++ b/resources/views/emails/ticket-update.blade.php @@ -1,7 +1,7 @@

Bonjour,

Le ticket n°{{ $ticket->id }} à été mis à jour :

    -
  • Projet : {{ $ticket->project->name }}
  • +
  • Projet : {{ $ticket->site->name }}
  • Type : {{ $ticket->type === 0 ? "Bug" : "Évolution" }}
  • Créé par : {{ $ticket->user->name }}
diff --git a/resources/views/layout/app.blade.php b/resources/views/layout/app.blade.php index 61f020a..bdbb726 100644 --- a/resources/views/layout/app.blade.php +++ b/resources/views/layout/app.blade.php @@ -16,8 +16,8 @@
{{__('Projet') }}  - @include('modules.sorter', ['colname' => 'project_id']) + @include('modules.sorter', ['colname' => 'site_id']) {{__('Type') }}  @@ -87,7 +87,7 @@ $userPr = Auth::user()->projects ?? collect([]); {{ $ticket->id }} {{ $ticket->project->name }}{{ $ticket->site->name }} @if ($ticket->type->equals(TicketType::bug())) {{ $ticket->type->label }} @@ -130,7 +130,7 @@ $userPr = Auth::user()->projects ?? collect([]);