- Removed Crud and Policies in favor of kwaadpepper/crud-policies

- PHPCS cleanup
This commit is contained in:
Jérémy Munsch 2021-07-15 02:05:00 +02:00
parent 2bc92200d8
commit 8dc056e9bc
56 changed files with 761 additions and 1947 deletions

View file

@ -7,6 +7,7 @@ use App\Models\User;
class AdminCreate extends Command
{
/**
* The name and signature of the console command.
*
@ -21,16 +22,6 @@ class AdminCreate extends Command
*/
protected $description = 'Create Admin User';
/**
* Create a new command instance.
*
* @return void
*/
public function __construct()
{
parent::__construct();
}
/**
* Execute the console command.
*

View file

@ -35,19 +35,19 @@ class UserCreate extends Command
*
* @return int
*/
// phpcs:ignore Generic.Metrics.CyclomaticComplexity.TooHigh
public function handle()
{
$sitename = $this->ask('For which site would you like to create a user ?');
$site = Site::where('name', 'LIKE', "%$sitename%")->first();
if ($site) {
if (!$this->confirm(sprintf('Would you like to use %s ? ', $site->name))) {
$this->info('Command cancelled');
return 0;
}
} else {
if (!$site) {
$this->error(sprintf('Site %s not found cancelled', $sitename));
return 0;
}
if (!$this->confirm(sprintf('Would you like to use %s ? ', $site->name))) {
$this->info('Command cancelled');
return 0;
}
$name = null;
while (is_null($name)) {
try {

View file

@ -28,7 +28,6 @@ class Kernel extends ConsoleKernel
*/
protected function schedule(Schedule $schedule)
{
// $schedule->command('inspire')->hourly();
}
/**

View file

@ -1,49 +0,0 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnum;
/**
*
* https://laravel.com/docs/8.x/authorization
* Controller Method Policy Method
* index viewAny
* show view
* create create
* store create
* edit update
* update update
* destroy delete
*
* @method static self viewAny()
* @method static self view()
* @method static self create()
* @method static self update()
* @method static self delete()
*/
class CrudAction extends BaseEnum
{
protected static function values(): array
{
return [
'viewAny' => 0,
'view' => 1,
'create' => 2,
'update' => 3,
'delete' => 4,
];
}
protected static function labels(): array
{
return [
'viewAny' => trans('Liste'),
'view' => trans('Voir'),
'create' => trans('Créer'),
'update' => trans('Éditer'),
'delete' => trans('Supprimer'),
];
}
}

View file

@ -1,59 +0,0 @@
<?php
namespace App\Enums;
use Kwaadpepper\Enum\BaseEnum;
/**
* @method static self boolean()
* @method static self int()
* @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()
* @method static self enum()
* @method static self belongsTo()
* @method static self belongsToMany()
*/
class CrudType extends BaseEnum
{
protected static function values(): array
{
return [
'boolean' => 0,
'int' => 1,
'string' => 2,
'text' => 3,
'json' => 4,
'image' => 5,
'email' => 6,
'password' => 7,
'float' => 8,
'enum' => 9,
'belongsTo' => 10,
'belongsToMany' => 11
];
}
protected static function labels(): array
{
return [
'boolean' => trans('Booléen'),
'int' => trans('Nombre'),
'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'),
'enum' => trans('Énumération'),
'belongsTo' => trans('Clé étrangère'),
'belongsToMany' => trans('Relation Belongs To Many')
];
}
}

View file

@ -1,9 +0,0 @@
<?php
namespace App\Exceptions;
use Exception;
class CrudException extends Exception
{
}

View file

@ -2,28 +2,14 @@
namespace App\Http\Controllers;
use App\Models\Employee;
use Closure;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
use Illuminate\Routing\Controller as BaseController;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\View;
class Controller extends BaseController
{
use AuthorizesRequests;
use DispatchesJobs;
use ValidatesRequests;
/**
* Get authenticated Employee
*
* @return Employee
*/
protected function getEmployee(): Employee
{
return Auth::guard('employee')->user();
}
}

View file

@ -1,262 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Enums\CrudType;
use App\Exceptions\CrudException;
use App\Http\Requests\CrudIndexRequest;
use App\Http\Requests\StoreCrudModel;
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;
use Illuminate\Support\Facades\View;
use Illuminate\Support\Str;
class CrudController extends Controller
{
/** @var \Illuminate\Database\Eloquent\Model */
protected static $modelClass = null;
// Eloquent callbacks
public function indexQuery(Builder $query): Builder
{
return $query;
}
public function storeModel(Model &$model)
{
}
public function storedModel(Model &$model)
{
}
public function updateModel(Model &$model)
{
}
public function updatedModel(Model &$model)
{
}
public function __construct()
{
// AUTH CONTROL TO ROOT POLICY
$this->authorizeResource(static::$modelClass);
$modelClass = static::$modelClass;
if (is_null($modelClass) or !class_exists($modelClass)) {
throw new CrudException(sprintf(
'%s needs the modelClass prop to be a class, %s %s given',
__CLASS__,
gettype($modelClass),
$modelClass
));
}
if (!is_subclass_of($modelClass, Model::class)) {
throw new CrudException(sprintf(
'%s needs the model prop to be a class the extends %s',
__CLASS__,
Model::class
));
}
if (!request()->ajax() and !app()->runningInConsole()) {
self::shareCrudModelsClassesToView();
$this->shareModelClassToView();
$this->shareModelHasImageToView();
$this->shareModelTableToView();
$this->shareModelPropsToView();
}
}
public function index(CrudIndexRequest $request)
{
/** @var \Illuminate\Database\Eloquent\Builder */
$models = static::$modelClass::query();
// Search on crud Label column
if ($request->search) {
$model = static::$modelClass;
$col = (new $model())->crudLabelColumn;
$models = $models->where($col, 'LIKE', "%$request->search%");
}
// Sort columns
$tableName = (new static::$modelClass())->getTable();
if ($request->rst) {
Session::remove("crud.$tableName.sort_col");
Session::remove("crud.$tableName.sort_way");
}
if ($request->sort_col) {
Session::put("crud.$tableName.sort_col", $request->sort_col);
Session::save();
}
if ($request->sort_way) {
Session::put("crud.$tableName.sort_way", $request->sort_way);
Session::save();
}
if (
Session::has("crud.$tableName.sort_col") and
Session::has("crud.$tableName.sort_way") and
Schema::hasColumn($tableName, Session::get("crud.$tableName.sort_col"))
) {
$models = $models->orderBy(
Session::get("crud.$tableName.sort_col"),
Session::get("crud.$tableName.sort_way")
);
}
$models = $this->indexQuery($models);
/** @var \Illuminate\Pagination\AbstractPaginator */
$models = $models->paginate(config('crud.paginate', 15));
if ($request->ajax()) {
return response()->json(CrudResource::collection($models));
} else {
$models = $models->withQueryString();
return view('crud.index', compact('models'));
}
}
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
public function show(Model $model)
{
return view('crud.show', compact('model'));
}
public function create()
{
return view('crud.create');
}
public function store(StoreCrudModel $request)
{
$modelClass = static::$modelClass;
$model = new $modelClass();
$model->fill($request->validated());
$this->storeModel($model);
$model->saveOrFail();
$model->saveRelations($request);
$this->storedModel($model);
return \redirect()->route(sprintf('bo.%s.edit', $model->getTable()), $model)
->with('success', trans(':model a bien été enregistré.', ['model' => $model->getModelName()]));
}
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass
public function edit(Model $model)
{
return view('crud.edit', compact('model'));
}
public function update(UpdateCrudModel $request, Model $model)
{
$model->fill($request->validated());
$this->updateModel($model);
$model->saveOrFail();
$model->saveRelations($request);
$this->updatedModel($model);
return \redirect()->route(sprintf('bo.%s.edit', $model->getTable()), $model)
->with('success', trans(':model a bien été enregistré.', ['model' => $model->getModelName()]));
}
public function destroy(Model $model)
{
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',
[
'model' => $model->getModelName(),
'associated' => Str::plural($restrict)
]
));
}
if ($model->delete()) {
return \redirect()->route(sprintf('bo.%s.index', $model->getTable()))
->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()]));
}
}
public function getModelClass()
{
return static::$modelClass;
}
/**
* Get the current model class
*
* @return void
*/
public static function shareCrudModelsClassesToView(): void
{
$models = [];
foreach (File::allFiles(\app_path('Http/Controllers')) as $file) {
$class = sprintf('App\Http\Controllers\%s', \substr($file->getFilename(), 0, -4));
if (is_subclass_of($class, CrudController::class) and $class::$modelClass) {
$models[] = $class::$modelClass;
}
}
View::share('modelsClasses', $models);
}
/**
* Get the current model class
*
* @return void
*/
private function shareModelClassToView(): void
{
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
*
* @return void
*/
private function shareModelTableToView(): void
{
/** @var \Illuminate\Database\Eloquent\Model $model */
$model = static::$modelClass;
View::share('modelTable', (new $model())->getTable());
}
/**
* Get the current model properties
*
* @return void
*/
private function shareModelPropsToView(): void
{
$model = static::$modelClass;
View::share('props', (new $model())->getEditableProperties());
}
}

View file

@ -15,11 +15,11 @@ use App\Http\Requests\EmployeeResetPasswordRequest;
use App\Http\Requests\ImportEmployeesCsvFile;
use App\Imports\EmployeeImport;
use App\Imports\EmployeeSortie;
use App\Jobs\SendMailConfirmToEmployee;
use App\Jobs\SendMailResetPasswordToEmployee;
use App\Jobs\SendEmployeeInfoMailToSiteRH;
use App\Jobs\SendEmployeeLockedDownMailToEmployee;
use App\Jobs\SendEmployeeLockedDownMailToSiteRH;
use App\Jobs\SendMailConfirmToEmployee;
use App\Jobs\SendMailResetPasswordToEmployee;
use App\Mail\EmployeeInfoAddress;
use App\Mail\EmployeeInfoBank;
use App\Mail\EmployeeInfoFamily;
@ -36,17 +36,17 @@ use Illuminate\Database\Eloquent\Model;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Str;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
use Maatwebsite\Excel\Excel as LExcel;
use Maatwebsite\Excel\Facades\Excel;
use Maatwebsite\Excel\Validators\ValidationException;
use PhpOffice\PhpSpreadsheet\Reader\Exception as ReaderException;
class EmployeesController extends CrudController
class EmployeesController extends Controller
{
use CrudController;
/** @var Employee */
protected static $modelClass = Employee::class;
public static $modelClass = Employee::class;
// BO
@ -82,7 +82,7 @@ class EmployeesController extends CrudController
public function importExit()
{
$this->authorize('importExit', Employee::class);
CrudController::shareCrudModelsClassesToView();
self::shareCrudModelsClassesToView();
return view('back.employees.import-exit');
}
@ -104,7 +104,10 @@ class EmployeesController extends CrudController
);
} catch (ReaderException $e) {
// this time cannot read anything
return redirect()->back()->withErrors('Echec lors de l\'import le fichier doit être conforme à celui fourni lors du developement de l\'application');
return redirect()->back()->withErrors(
// phpcs:ignore Generic.Files.LineLength.TooLong
'Echec lors de l\'import le fichier doit être conforme à celui fourni lors du developement de l\'application'
);
} catch (Exception $e) {
// $employeeImport->errorMessages
// this time cannot read anything
@ -141,7 +144,7 @@ class EmployeesController extends CrudController
public function import()
{
$this->authorize('import', Employee::class);
CrudController::shareCrudModelsClassesToView();
self::shareCrudModelsClassesToView();
return view('back.employees.import');
}
@ -169,7 +172,10 @@ class EmployeesController extends CrudController
));
} catch (ReaderException $e) {
// this time cannot read anything
return redirect()->back()->withErrors('Echec lors de l\'import le fichier doit être conforme à celui fourni lors du developement de l\'application');
return redirect()->back()->withErrors(
// phpcs:ignore Generic.Files.LineLength.TooLong
'Echec lors de l\'import le fichier doit être conforme à celui fourni lors du developement de l\'application'
);
} finally {
$message = '';
$errors = [];
@ -183,6 +189,7 @@ class EmployeesController extends CrudController
}
if (count($errors)) {
$message = sprintf(
// phpcs:ignore Generic.Files.LineLength.TooLong
"%d salariés ont été importés \n %d salariés mis à jour\n %d erreurs\n Les erreurs suivantes sont apparues %s",
$employeeImport->importedCount,
$employeeImport->updatedCount,
@ -236,10 +243,17 @@ class EmployeesController extends CrudController
// Is employee locked down ?
if ($employee->password_attempts >= 3) {
SendEmployeeLockedDownMailToEmployee::dispatchAfterResponse(new EmployeeLockedDown($employee), $employee);
SendEmployeeLockedDownMailToSiteRH::dispatchAfterResponse(new EmployeeYourAccountIsLockedDown($employee), $employee);
SendEmployeeLockedDownMailToEmployee::dispatchAfterResponse(
new EmployeeLockedDown($employee),
$employee
);
SendEmployeeLockedDownMailToSiteRH::dispatchAfterResponse(
new EmployeeYourAccountIsLockedDown($employee),
$employee
);
return \redirect()->route('employees.login')
->withErrors(
// phpcs:ignore Generic.Files.LineLength.TooLong
[trans('Votre compte est verrouillé, veuillez contacter votre responsable RH pour le déverrouiller')],
'lockedDown'
)->with('site', $employee->site);
@ -317,7 +331,7 @@ class EmployeesController extends CrudController
Session::remove('required');
Session::save();
return redirect()->route('fo.access')
->with('message', trans('Votre mot de passe a bien été mis à jour'));
->with('message', trans('Votre mot de passe a bien été mis à jour'));
}
return \redirect()->back()->with('success', true);
}

View file

@ -6,12 +6,14 @@ use App\Models\Flash;
use App\Models\Site;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class FlashesController extends CrudController
class FlashesController extends Controller
{
use CrudController;
/** @var Flash */
protected static $modelClass = Flash::class;
public static $modelClass = Flash::class;
// BO

View file

@ -2,6 +2,8 @@
namespace App\Http\Controllers;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class HomeController extends Controller
{
// BO

View file

@ -7,6 +7,7 @@ use App\Imports\PlanningImport;
use App\Models\Planning;
use App\Models\Site;
use Illuminate\Http\UploadedFile;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
use Maatwebsite\Excel\Facades\Excel;
use Maatwebsite\Excel\Excel as LExcel;
use Maatwebsite\Excel\HeadingRowImport;
@ -78,7 +79,10 @@ class PlanningController extends Controller
}
} catch (ReaderException $e) {
// this time cannot read anything
return redirect()->back()->withErrors('Echec lors de l\'import le fichier doit être conforme à celui fourni lors du developement de l\'application');
return redirect()->back()->withErrors(
// phpcs:ignore Generic.Files.LineLength.TooLong
'Echec lors de l\'import le fichier doit être conforme à celui fourni lors du developement de l\'application'
);
} finally {
return redirect()->route('bo.plannings.import')
->with('success', sprintf(
@ -119,7 +123,9 @@ class PlanningController extends Controller
'<Font ss:FontName="Arial" x:Family="Swiss" ss:Color="#000000" ss:Size="8" ss:Bold="1"/>',
'<Font ss:FontName="Arial" x:Family="Swiss" ss:Size="8" ss:Color="#000000" ss:Bold="1"/>',
'<Font ss:FontName="Arial" x:Family="Swiss" ss:Size="8" ss:Color="#FF0000" ss:Bold="1"/>',
//phpcs:ignore Generic.Files.LineLength.TooLong
'<Font html:Face=\'Parisine Plus Ptf Sombre\' x:Family=\'Swiss\' html:Size=\'11\' html:Color=\'#FFFFFF\'>',
//phpcs:ignore Generic.Files.LineLength.TooLong
"<Font ss:FontName=\"Arial\" x:Family=\"Swiss\" ss:Size=\"8\" ss:Color=\"#000000\"\n ss:Bold=\"1\"/>",
"<Font ss:FontName=\"Arial\" x:Family=\"Swiss\" ss:Size=\"8\" ss:Color=\"#000000\"\n",
"<Font ss:FontName=\"Arial\" x:Family=\"Swiss\" ss:Size=\"8\" ss:Color=\"#fdfefe\"\n",
@ -131,7 +137,6 @@ class PlanningController extends Controller
'',
$xmlString
);
// dd($xmlString);
return $xmlString;
}

View file

@ -3,10 +3,12 @@
namespace App\Http\Controllers;
use App\Models\Pole;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class PolesController extends CrudController
class PolesController extends Controller
{
use CrudController;
/** @var Pole */
protected static $modelClass = Pole::class;
public static $modelClass = Pole::class;
}

View file

@ -5,12 +5,14 @@ namespace App\Http\Controllers;
use App\Enums\Role;
use App\Models\Site;
use Illuminate\Database\Eloquent\Builder;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class SitesController extends CrudController
class SitesController extends Controller
{
use CrudController;
/** @var Site */
protected static $modelClass = Site::class;
public static $modelClass = Site::class;
// BO

View file

@ -3,10 +3,12 @@
namespace App\Http\Controllers;
use App\Models\Societe;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class SocietesController extends CrudController
class SocietesController extends Controller
{
use CrudController;
/** @var Employee */
protected static $modelClass = Societe::class;
public static $modelClass = Societe::class;
}

View file

@ -10,13 +10,15 @@ use App\Models\Sondage;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Str;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
use League\Csv\Writer;
class SondagesController extends CrudController
class SondagesController extends Controller
{
use CrudController;
/** @var Sondage */
protected static $modelClass = Sondage::class;
public static $modelClass = Sondage::class;
// Eloquent callbacks
public function indexQuery(Builder $query): Builder
@ -105,13 +107,17 @@ class SondagesController extends CrudController
}
foreach ($res as $customerIntel) {
$identifier = $customerIntel['employee']->matricule ." ". $customerIntel['employee']->firstname ." ".$customerIntel['employee']->lastname;
$identifier = sprintf(
'%s %s %s',
$customerIntel['employee']->matricule,
$customerIntel['employee']->firstname,
$customerIntel['employee']->lastname
);
$w->insertOne(array_replace(
$tmpl,
[
$identifier,
],
$customerIntel['answers']
));

View file

@ -6,12 +6,14 @@ use App\Enums\Role;
use App\Models\User;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Model;
use Kwaadpepper\CrudPolicies\Traits\CrudController;
class UsersController extends CrudController
class UsersController extends Controller
{
use CrudController;
/** @var User */
protected static $modelClass = User::class;
public static $modelClass = User::class;
// Eloquent callbacks
public function indexQuery(Builder $query): Builder

View file

@ -15,7 +15,6 @@ class Kernel extends HttpKernel
* @var array
*/
protected $middleware = [
// \App\Http\Middleware\TrustHosts::class,
\App\Http\Middleware\TrustProxies::class,
\Fruitcake\Cors\HandleCors::class,
\App\Http\Middleware\PreventRequestsDuringMaintenance::class,

View file

@ -20,5 +20,10 @@ class TrustProxies extends Middleware
*
* @var int
*/
protected $headers = Request::HEADER_X_FORWARDED_FOR | Request::HEADER_X_FORWARDED_HOST | Request::HEADER_X_FORWARDED_PORT | Request::HEADER_X_FORWARDED_PROTO | Request::HEADER_X_FORWARDED_AWS_ELB;
protected $headers =
Request::HEADER_X_FORWARDED_FOR |
Request::HEADER_X_FORWARDED_HOST |
Request::HEADER_X_FORWARDED_PORT |
Request::HEADER_X_FORWARDED_PROTO |
Request::HEADER_X_FORWARDED_AWS_ELB;
}

View file

@ -1,30 +0,0 @@
<?php
namespace App\Http\Requests;
use Illuminate\Foundation\Http\FormRequest;
class CrudIndexRequest extends FormRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return auth()->check();
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'search' => 'nullable|string'
];
}
}

View file

@ -1,90 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Enums\CrudAction;
use App\Enums\CrudType;
use App\Exceptions\CrudException;
use App\Http\Controllers\CrudController;
use Illuminate\Support\Str;
use Illuminate\Foundation\Http\FormRequest;
class CrudRequest extends FormRequest
{
/** @var array */
protected $rules = [];
/**
* Get rules for a specific action
*
* @param CrudAction $action
* @return array
*/
public function getRulesForAction(CrudAction $action): array
{
$model = $this->getCurrentModel();
$props = $this->getCurrentModel()::getEditableProperties();
$propsRules = [];
foreach ($this->getCurrentModel()::getRules() as $k => $rules) {
$propsRules[$k] = [];
$propIsAllowedOnUpdateAction = in_array($action, $props[$k]['actions']);
foreach ($rules as $rule) {
// dont copy required if prop is not allowed on update
if (!$propIsAllowedOnUpdateAction and is_string($rule) and $rule == 'required') {
continue;
}
if (!in_array($rule, $propsRules[$k])) {
$propsRules[$k][] = $rule;
}
// handle password
if (
$props[$k]['type']->equals(CrudType::password()) and
!$this->{$k} or (is_string($this->{$k}) and !\strlen($this->{$k}))
) {
$this->offsetUnset($k);
}
// handle boolean
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:' .
(new $props[$k]['belongsToMany']())->getTable() . ',id';
if (!isset($this->{$k})) {
$this->merge([$k => []]);
}
}
}
}
return $propsRules;
}
/**
* Returns the first parameter that is a crud model
*
* @return string \Illuminate\Database\Eloquent\Model class name
* @throws \App\Exceptions\CrudException if the request does not have a crud model parameter
*/
protected function getCurrentModel(): string
{
if (
!is_object($this->route()->controller) or
!$this->route()->controller instanceof CrudController
) {
throw new CrudException(sprintf(
'Request `%s` needs to be bound on route that use a CrudController',
get_class($this)
));
}
return $this->route()->controller->getModelClass();
}
}

View file

@ -44,6 +44,7 @@ class EmployeePasswordChangeRequest extends FormRequest
'newpassword' => [
'required',
'string',
// phpcs:ignore Generic.Files.LineLength.TooLong
'regex:/^(?=.*[A-Z])(?=.*[²&~"#\'\{\(\[\-|`_\\^@\)\°=+\}¨^$£¤%?,;.:\/!§*<>])(?=.*[0-9].*)(?=.*[a-z]).{8,}$/'
],
'newpasswordConfirm' => 'required|same:newpassword'

View file

@ -28,6 +28,7 @@ class EmployeeResetPasswordRequest extends FormRequest
'newpassword' => [
'required',
'string',
// phpcs:ignore Generic.Files.LineLength.TooLong
'regex:/^(?=.*[A-Z])(?=.*[²&~"#\'\{\(\[\-|`_\\^@\)\°=+\}¨^$£¤%?,;.:\/!§*<>])(?=.*[0-9].*)(?=.*[a-z]).{8,}$/'
],
'newpasswordConfirm' => 'required|same:newpassword'

View file

@ -1,32 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Enums\CrudAction;
class StoreCrudModel extends CrudRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$authorized = auth()->check();
if ($authorized) {
$this->rules = $this->getRulesForAction(CrudAction::create());
}
return $authorized;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return $this->rules;
}
}

View file

@ -1,32 +0,0 @@
<?php
namespace App\Http\Requests;
use App\Enums\CrudAction;
class UpdateCrudModel extends CrudRequest
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
$authorized = auth()->check();
if ($authorized) {
$this->rules = $this->getRulesForAction(CrudAction::update());
}
return $authorized;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return $this->rules;
}
}

View file

@ -2,6 +2,8 @@
namespace App\Http\Requests;
use Kwaadpepper\CrudPolicies\Http\Requests\UpdateCrudModel;
class UpdateSondage extends UpdateCrudModel
{
/**

View file

@ -1,22 +0,0 @@
<?php
namespace App\Http\Resources;
use Illuminate\Http\Resources\Json\JsonResource;
class CrudResource extends JsonResource
{
/**
* Transform the resource collection into an array.
*
* @param \Illuminate\Http\Request $request
* @return array
*/
public function toArray($request)
{
return [
'label' => $this->crudLabel,
'value' => $this->crudValue
];
}
}

View file

@ -1,106 +0,0 @@
<?php
namespace App\Lib\PolicySystem;
use App\Models\User;
use App\Lib\PolicySystem\StaticRules as SR;
use Illuminate\Auth\Access\Response;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Support\Facades\Log;
class RootPolicy
{
protected $policy = null;
protected $policies = null;
public function __construct()
{
$cls = \explode('\\', \get_called_class());
$this->policy = \strtolower(\str_replace('Policy', '', \end($cls)));
}
protected function actionPolicy(string $method, string $policy, User $user, Model $model = null)
{
$this->setPolicies($user, $model);
$ctx = [$policy, $user, $model];
if (!$this->hasPolicy($policy)) {
$m = __('Unhandled policy ":policy"', ['policy' => $policy]);
Log::critical($m, $ctx);
return $this->deny($m);
}
if (!is_array($this->policies[$policy])) {
$m = __('Policy ":policy" has to be array', ['policy' => $policy]);
Log::critical($m, $ctx);
return $this->deny($m);
}
// Policy method exists
if (!array_key_exists($method, $this->policies[$policy])) {
$m = __('Unhandled policy ":policy" for action ":action"', ['policy' => $policy, 'action' => $method]);
Log::critical($m, $ctx);
return $this->deny($m);
}
// Call policy method
if (Sr::handle($this->policies[$policy][$method], $user, $model)) {
return $this->allow();
} else {
$m = __('Policy ":policy" for action ":action" denied :onmodel', [
'policy' => $policy,
'action' => $method,
'onmodel' => $model ? get_class($model) : ''
]);
if (config('app.policyDebug')) {
Log::debug(sprintf("%s user => %s model => %s", $m, $user, $model), $ctx);
}
return $this->deny($m);
}
$m = __('Unhandled policy case on resource ":method"', ['method' => $method]);
Log::critical($m, $ctx);
return $this->deny();
}
/**
** Do the magic calling Root policy from any policy
*/
public function __call($method, $args)
{
return call_user_func_array([$this, 'actionPolicy'], array_merge([$method, $this->policy], $args));
}
private function hasPolicy(string $policy)
{
return array_key_exists($policy, $this->policies);
}
/**
* Allow action for the user
*
* @param string|null $message
* @return \Illuminate\Auth\Access\Response
*/
protected function allow(?string $message = null)
{
return Response::allow($message);
}
/**
* Deny action for the user
*
* @param string|null $message
* @param mixed $code
* @return \Illuminate\Auth\Access\Response
*/
protected function deny(?string $message = null, $code = null)
{
if (!$message) {
$message = __('This action is not allowed to you for this resource.');
}
return Response::deny($message, $code);
}
}

View file

@ -1,86 +0,0 @@
<?php
namespace App\Lib\PolicySystem;
use App\Models\User;
use Exception;
use Closure;
use Illuminate\Database\Eloquent\Model;
/**
* Generic Policiy Static Rules
*! Rules has to return boolean value
*/
abstract class StaticRules
{
/**
* Make a rule closure
*
* @param string $rulename
* @param mixed ...$args
* @return Closure
*/
public static function make(string $rulename, ...$args)
{
if (!method_exists(static::class, $rulename)) {
throw new Exception(sprintf('Unknown rule %s in Policies StaticRules', $rulename));
}
return function () use ($rulename, $args) {
return call_user_func_array([static::class, $rulename], $args);
};
}
public static function and(array $ruleClosures)
{
return function (User $user, Model $model = null) use ($ruleClosures) {
$nbRules = count($ruleClosures);
$out = true;
$i = 0;
do {
if (!($out = (self::handle($ruleClosures[$i++], $user, $model) && $out))) {
break;
}
} while ($i < $nbRules);
return $out;
};
}
public static function or(array $ruleClosures)
{
return function (User $user, Model $model = null) use ($ruleClosures) {
$nbRules = count($ruleClosures);
$out = false;
$i = 0;
do {
if ($out = (self::handle($ruleClosures[$i++], $user, $model) || $out)) {
break;
}
} while ($i < $nbRules);
return $out;
};
}
public static function handle($rule, User $user, Model $model = null)
{
if (is_array($rule)) {
$nbRule = count($rule);
$out = false;
$i = 0;
while ($i < $nbRule) {
if ($out = self::handle($rule[$i++], $user, $model)) {
break;
}
}
return $out;
}
if (!is_callable($rule)) {
throw new Exception('Rule has to ba callable.');
}
return (bool)$rule($user, $model);
}
protected static function anyone()
{
return true;
}
}

View file

@ -2,10 +2,7 @@
namespace App\Models;
use App\Enums\CrudAction;
use App\Enums\CrudType;
use App\Jobs\SendEmployeeCreatedAccountMail;
use App\Traits\IsCrudModel;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Support\Facades\Hash;
@ -13,6 +10,9 @@ use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Support\Carbon;
use Illuminate\Support\Collection as SupportCollection;
use Illuminate\Support\Str;
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
use Kwaadpepper\CrudPolicies\Enums\CrudType;
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
class Employee extends Authenticatable
{

View file

@ -2,12 +2,11 @@
namespace App\Models;
use App\Casts\NiceDate;
use App\Enums\CrudAction;
use App\Enums\CrudType;
use App\Traits\IsCrudModel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
use Kwaadpepper\CrudPolicies\Enums\CrudType;
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
class Flash extends Model
{

View file

@ -2,11 +2,11 @@
namespace App\Models;
use App\Enums\CrudAction;
use App\Enums\CrudType;
use App\Traits\IsCrudModel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
use Kwaadpepper\CrudPolicies\Enums\CrudType;
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
class Pole extends Model
{

View file

@ -2,11 +2,11 @@
namespace App\Models;
use App\Enums\CrudAction;
use App\Enums\CrudType;
use App\Traits\IsCrudModel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
use Kwaadpepper\CrudPolicies\Enums\CrudType;
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
class Site extends Model
{

View file

@ -2,12 +2,12 @@
namespace App\Models;
use App\Enums\CrudAction;
use App\Enums\CrudType;
use App\Traits\IsCrudModel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Http\UploadedFile;
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
use Kwaadpepper\CrudPolicies\Enums\CrudType;
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
class Societe extends Model
{
@ -112,6 +112,7 @@ class Societe extends Model
'type' => CrudType::json(),
'validate' => [
'json',
// phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClassBeforeLastUsed
function ($attribute, $value, $fail) {
$pattern = '/^#([A-Fa-f0-9]{6}|[A-Fa-f0-9]{3})$/';
$a = \json_decode($value, true);

View file

@ -2,12 +2,12 @@
namespace App\Models;
use App\Enums\CrudAction;
use App\Enums\CrudType;
use App\Enums\TypeSondage;
use App\Traits\IsCrudModel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
use Kwaadpepper\CrudPolicies\Enums\CrudType;
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
use Kwaadpepper\Enum\Traits\CastsEnums;
class Sondage extends Model

View file

@ -2,15 +2,15 @@
namespace App\Models;
use App\Enums\CrudAction;
use App\Enums\CrudType;
use App\Enums\Role;
use App\Traits\IsCrudModel;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Foundation\Auth\User as Authenticatable;
use Illuminate\Notifications\Notifiable;
use Illuminate\Support\Facades\Hash;
use Illuminate\Support\Str;
use Kwaadpepper\CrudPolicies\Enums\CrudAction;
use Kwaadpepper\CrudPolicies\Enums\CrudType;
use Kwaadpepper\CrudPolicies\Traits\IsCrudModel;
use Kwaadpepper\Enum\Traits\CastsEnums;
class User extends Authenticatable

View file

@ -3,8 +3,6 @@
namespace App\Policies;
use App\Models\User;
use App\Lib\PolicySystem\RootPolicy;
use App\Lib\PolicySystem\StaticRules as Sr;
use App\Policies\Rules\FlashStaticRules as FSR;
use App\Policies\Rules\UserStaticRules as USR;
use App\Policies\Rules\UserRoleRules as URR;
@ -12,6 +10,8 @@ use App\Policies\Rules\SiteStaticRules as SSR;
use App\Policies\Rules\SondageStaticRules as SoSR;
use App\Policies\Rules\EmployeeStaticRules as SaSR;
use Illuminate\Database\Eloquent\Model;
use Kwaadpepper\CrudPolicies\Policies\RootPolicy;
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
class AppPolicies extends RootPolicy
{
@ -46,11 +46,11 @@ class AppPolicies extends RootPolicy
],
'site' => [
'viewAny' => USR::make('everyOne'),
'view' => Sr::or([
'view' => StaticRules::or([
URR::make('userIsAdmin', $user),
SSR::make('siteIsOwnedByUser', $user, $model)
]),
'update' => Sr::or([
'update' => StaticRules::or([
URR::make('userIsAdmin', $user),
SSR::make('siteIsOwnedByUser', $user, $model)
]),
@ -59,32 +59,32 @@ class AppPolicies extends RootPolicy
],
'flash' => [
'viewAny' => USR::make('everyOne'),
'view' => Sr::or([
'view' => StaticRules::or([
URR::make('userIsAdmin', $user),
FSR::make('flashIsOwnedByUser', $user, $model)
]),
'update' => Sr::or([
'update' => StaticRules::or([
URR::make('userIsAdmin', $user),
FSR::make('flashIsOwnedByUser', $user, $model)
]),
'create' => USR::make('everyOne'),
'delete' => Sr::or([
'delete' => StaticRules::or([
URR::make('userIsAdmin', $user),
FSR::make('flashIsOwnedByUser', $user, $model)
])
],
'employee' => [
'viewAny' => USR::make('everyOne'),
'view' => Sr::or([
'view' => StaticRules::or([
URR::make('userIsAdmin', $user),
SaSR::make('employeeIsOwnedByUser', $user, $model)
]),
'update' => Sr::or([
'update' => StaticRules::or([
URR::make('userIsAdmin', $user),
SaSR::make('employeeIsOwnedByUser', $user, $model)
]),
'create' => USR::make('everyOne'),
'delete' => Sr::or([
'delete' => StaticRules::or([
URR::make('userIsAdmin', $user),
SaSR::make('employeeIsOwnedByUser', $user, $model)
]),
@ -93,26 +93,26 @@ class AppPolicies extends RootPolicy
],
'sondage' => [
'viewAny' => USR::make('everyOne'),
'view' => Sr::or([
'view' => StaticRules::or([
URR::make('userIsAdmin', $user),
SoSR::make('sondageIsOwnedByUser', $user, $model)
]),
// edit
'update' => Sr::or([
'update' => StaticRules::or([
URR::make('userIsAdmin', $user),
SoSR::make('sondageIsOwnedByUser', $user, $model)
]),
// update submit
'updateSondage' => Sr::or([
'updateSondage' => StaticRules::or([
URR::make('userIsAdmin', $user),
SoSR::make('sondageIsOwnedByUser', $user, $model)
]),
'create' => USR::make('everyOne'),
'delete' => Sr::or([
'delete' => StaticRules::or([
URR::make('userIsAdmin', $user),
SoSR::make('sondageIsOwnedByUser', $user, $model)
]),
'export' => Sr::or([
'export' => StaticRules::or([
URR::make('userIsAdmin', $user),
SoSR::make('sondageIsOwnedByUser', $user, $model)
]),
@ -122,11 +122,11 @@ class AppPolicies extends RootPolicy
],
'user' => [
'viewAny' => USR::make('everyOne'),
'view' => Sr::or([
'view' => StaticRules::or([
URR::make('userIsAdmin', $user),
USR::make('usersAreTheSame', $user, $model)
]),
'update' => Sr::or([
'update' => StaticRules::or([
URR::make('userIsAdmin', $user),
USR::make('usersAreTheSame', $user, $model)
]),

View file

@ -3,8 +3,8 @@
namespace App\Policies\Rules;
use App\Models\User;
use App\Lib\PolicySystem\StaticRules;
use App\Models\Employee;
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
/**
* Userlevel Policiy Static Rules

View file

@ -3,8 +3,8 @@
namespace App\Policies\Rules;
use App\Models\User;
use App\Lib\PolicySystem\StaticRules;
use App\Models\Flash;
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
/**
* Userlevel Policiy Static Rules

View file

@ -3,8 +3,8 @@
namespace App\Policies\Rules;
use App\Models\User;
use App\Lib\PolicySystem\StaticRules;
use App\Models\Site;
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
/**
* Userlevel Policiy Static Rules

View file

@ -3,8 +3,8 @@
namespace App\Policies\Rules;
use App\Models\User;
use App\Lib\PolicySystem\StaticRules;
use App\Models\Sondage;
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
/**
* Userlevel Policiy Static Rules

View file

@ -4,7 +4,7 @@ namespace App\Policies\Rules;
use App\Enums\Role;
use App\Models\User;
use App\Lib\PolicySystem\StaticRules;
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
/**
* Userlevel Policiy Static Rules

View file

@ -3,7 +3,7 @@
namespace App\Policies\Rules;
use App\Models\User;
use App\Lib\PolicySystem\StaticRules;
use Kwaadpepper\CrudPolicies\Policies\Rules\StaticRules;
/**
* Userlevel Policiy Static Rules

View file

@ -13,9 +13,7 @@ class AuthServiceProvider extends ServiceProvider
*
* @var array
*/
protected $policies = [
// 'App\Models\Model' => 'App\Policies\ModelPolicy',
];
protected $policies = [];
/**
* Register any authentication / authorization services.

View file

@ -28,15 +28,6 @@ class RouteServiceProvider extends ServiceProvider
*/
public const HOME = '/bo';
/**
* The controller namespace for the application.
*
* When present, controller route declarations will automatically be prefixed with this namespace.
*
* @var string|null
*/
// protected $namespace = 'App\\Http\\Controllers';
/**
* Define your route model bindings, pattern filters, etc.
*

View file

@ -1,532 +0,0 @@
<?php
namespace App\Traits;
use App\Enums\CrudAction;
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;
trait IsCrudModel
{
protected static $editableProperties = [];
private static $schemaCrud = [
'label' => null,
'placeholder' => '',
'type' => null,
'enum' => null,
'nullable' => false,
'readonly' => false,
'disabled' => false,
'required' => false,
'validate' => [],
'rules' => [],
'actions' => [],
'belongsTo' => null,
'belongsToMany' => null,
'getAttribute' => null,
'setAttribute' => null
];
// OVERLOAD MODEL FUNCTION
public function __get($key)
{
if (
isset(static::$editableProperties[$key]['getAttribute']) and
is_callable(static::$editableProperties[$key]['getAttribute'])
) {
return static::$editableProperties[$key]['getAttribute']($this);
}
return parent::__get($key);
}
// OVERLOAD MODEL FUNCTION
public function __set($key, $value)
{
if (
isset($this::$editableProperties[$key]['setAttribute']) and
is_callable($this::$editableProperties[$key]['setAttribute'])
) {
return $this::$editableProperties[$key]['setAttribute']($this, $value);
}
return parent::__set($key, $value);
}
// OVERLOAD MODEL FUNCTION
public function fill(array $attributes)
{
parent::fill($attributes);
foreach ($attributes as $k => $attribute) {
if (
isset(static::$editableProperties[$k]['setAttribute']) and
is_callable(static::$editableProperties[$k]['setAttribute'])
) {
$this->{$k} = $attribute;
}
if (\is_object($this->{$k}) and \get_class($this->{$k}) === UploadedFile::class) {
$this->moveUploadedFile($k, $this->{$k});
}
}
}
public function saveRelations(CrudRequest $request)
{
$validated = $request->validated();
$props = self::getEditableProperties();
foreach ($props as $k => $prop) {
if ($prop['belongsToMany']) {
$this->{$k}()->sync(is_array($validated[$k]) ? $validated[$k] : []);
}
}
}
/**
* Has this model Has many relations with delete restrict ?
*
* @return bool|string
*/
public function gotHasManyRelationWithRestrictOnDelete()
{
$sm = DB::getDoctrineSchemaManager();
foreach (self::getRelationships() as $relation => $type) {
if ($type[0] === 'HasMany') {
$table = (new $type[1]())->getTable();
/** @var \Doctrine\DBAL\Schema\ForeignKeyConstraint $foreignKey */
foreach ($sm->listTableForeignKeys($table) as $foreignKey) {
// /vendor/doctrine/dbal/src/Schema/ForeignKeyConstraint.php onEvent()
if ($foreignKey->onDelete() === 'CASCADE') {
// allow only CASCADE action, otherwise it would break the app
continue;
}
return class_basename($type[1]);
}
}
}
return false;
}
/**
* Get the crud label
*/
public function getCrudLabelAttribute()
{
return $this->{$this->crudLabelColumn};
}
/**
* Get the crud value
*/
public function getCrudValueAttribute()
{
if (is_null($this->crudValueColumn)) {
throw new CrudException(sprintf(
'[\'belongsTo\'] model `%s` must have `crudValueColumn` property',
get_class($this),
CrudAction::class
));
}
return $this->{$this->crudValueColumn};
}
/**
* Get the crud label column
*/
public function getCrudLabelColumnAttribute()
{
if (is_null($this->crudLabelColumn)) {
throw new CrudException(sprintf(
'[\'belongsTo\'] model `%s` must have `crudLabelColumn` property',
get_class($this),
CrudAction::class
));
}
return $this->crudLabelColumn;
}
/**
* Get the crud value column
*/
public function getCrudValueColumnAttribute()
{
return $this->crudValueColumn;
}
/**
* Get the model validation rules
*
* @return array
*/
public static function getRules(): array
{
return collect(static::$editableProperties)->mapWithKeys(function ($item, $key) {
$item = \array_merge(self::$schemaCrud, $item);
$defaultRules = [];
if (!$item['nullable'] === true) {
$defaultRules[] = 'required';
} elseif ($item['required'] === true) {
$defaultRules[] = 'required';
} elseif ($item['readonly'] === true) {
$defaultRules[] = 'prohibited';
}
switch ($item['type']) {
case CrudType::boolean():
$defaultRules[] = 'boolean';
break;
case CrudType::image():
$defaultRules[] = 'file';
break;
case CrudType::email():
$defaultRules[] = 'email:rfc,dns';
break;
case CrudType::belongsTo():
$defaultRules[] = 'integer';
$defaultRules[] = 'min:0';
break;
case CrudType::int():
$defaultRules[] = 'integer';
break;
case CrudType::belongsToMany():
$defaultRules[] = 'array';
break;
case CrudType::password():
// phpcs:ignore Generic.Files.LineLength.TooLong
$defaultRules[] = "regex:/^(?=.*[A-Z])(?=.*[²&~\"#'\{\(\[\-|`_\\^@\)\°=+\}¨^\$£¤%?,;.:\/!§*<>])(?=.*[0-9].*)(?=.*[a-z]).{8,}$/";
break;
case CrudType::text():
case CrudType::string():
default:
$defaultRules[] = 'string';
break;
}
return [$key => array_merge($defaultRules, $item['validate'] ?? self::$schemaCrud['validate'])];
})->all();
}
/**
* Get the model Name
*
* @return string
*/
public function getModelName(): string
{
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
*
* @return array
*/
public static function getEditableProperties(): array
{
static::assertEditablePropertiesIsCorrect();
return static::$editableProperties;
}
/**
* Assert self::$editableProperties is in a correct format
*
* 'string' => CrudType::value()
*
* @return void
* @throws Exception
*/
private static function assertEditablePropertiesIsCorrect(): void
{
if (empty(static::$editableProperties)) {
throw new CrudException('$editableProperties must be defined in ' . __CLASS__);
}
foreach (static::$editableProperties as $name => &$prop) {
if (!is_string($name)) {
throw new CrudException(sprintf(
'editableProperties array value must be an array given: %s',
print_r($prop, true) // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Found
));
}
if (!is_array($prop)) {
throw new CrudException(sprintf(
'editableProperties array value must be an array given: %s',
print_r($prop, true) // phpcs:ignore Squiz.PHP.DiscouragedFunctions.Found
));
}
$prop = array_merge_recursive_distinct(self::$schemaCrud, $prop);
// Auto label
$prop['label'] = $prop['label'] ?? ucfirst($name);
self::assertLabelIscorrect($prop);
self::assertPlaceholderIscorrect($prop);
self::assertTypeIscorrect($prop);
switch ($prop['type']) {
// Email auto rule
case CrudType::email():
$prop['validate'] = is_array($prop['validate']) ? $prop['validate'] : [];
if (!array_search('email:rfc,dns', $prop['validate'])) {
$prop['validate'][] = 'email:rfc,dns';
}
break;
case CrudType::json():
$prop['validate'] = is_array($prop['validate']) ? $prop['validate'] : [];
if (!array_search('json', $prop['validate'])) {
$prop['validate'][] = 'json';
}
break;
}
self::assertNullableIscorrect($prop);
self::assertReadonlyIscorrect($prop);
self::assertDisabledIscorrect($prop);
self::assertValidateIscorrect($prop);
self::assertRulesArecorrect($prop);
self::assertActionsArecorrect($prop);
self::assertBelongsToIsCorrect($prop);
self::assertEnumIscorrect($prop);
self::assertGetAttributeIscorrect($prop);
self::assertSetAttributeIscorrect($prop);
self::assertBelongsToManyIsCorrect($prop);
}
}
private static function assertLabelIscorrect(array $prop): void
{
if (!isset($prop['label']) or !is_string($prop['label'])) {
throw new CrudException('$editableProperties[\'label\'] array value must be a string');
}
}
private static function assertPlaceholderIscorrect(array $prop): void
{
if (!isset($prop['placeholder']) or !is_string($prop['placeholder'])) {
throw new CrudException('$editableProperties[\'placeholder\'] array value must be a string');
}
}
private static function assertTypeIscorrect(array $prop): void
{
if (!isset($prop['type']) or !is_object($prop['type']) or get_class($prop['type']) !== CrudType::class) {
throw new CrudException('$editableProperties[\'type\'] value must be a CrudType enum');
}
}
private static function assertNullableIscorrect(array $prop): void
{
if (!isset($prop['nullable']) or !is_bool($prop['nullable'])) {
throw new CrudException('$editableProperties[\'nullable\'] array value must be a boolean');
}
}
private static function assertReadonlyIscorrect(array $prop): void
{
if (
!isset($prop['readonly']) or
(!is_bool($prop['readonly']) and !\is_callable($prop['readonly']))
) {
throw new CrudException('$editableProperties[\'readonly\'] array value must be a boolean or a function returnning a boolean');
}
}
private static function assertDisabledIscorrect(array $prop): void
{
if (!isset($prop['disabled']) or !is_bool($prop['disabled'])) {
throw new CrudException('$editableProperties[\'disabled\'] array value must be a boolean');
}
}
private static function assertRequiredIscorrect(array $prop): void
{
if (!isset($prop['required']) or !is_bool($prop['required'])) {
throw new CrudException('$editableProperties[\'required\'] array value must be a boolean');
}
}
private static function assertValidateIscorrect(array $prop): void
{
if (!isset($prop['validate']) or !\is_array($prop['validate'])) {
throw new CrudException('$editableProperties[\'validate\'] array value must be an array');
}
}
private static function assertGetAttributeIscorrect(array $prop): void
{
if (!is_null($prop['getAttribute']) and !is_callable($prop['getAttribute'])) {
throw new CrudException('$editableProperties[\'getAttribute\'] array value must be callable');
}
}
private static function assertSetAttributeIscorrect(array $prop): void
{
if (!is_null($prop['setAttribute']) and !is_callable($prop['setAttribute'])) {
throw new CrudException('$editableProperties[\'setAttribute\'] array value must be callable');
}
}
private static function assertRulesArecorrect(array $prop): void
{
$allowedRules = [
'min' => function ($v) {
return \is_numeric($v);
},
'max' => function ($v) {
return \is_numeric($v);
},
'step' => function ($v) {
return \is_numeric($v);
},
];
if (!isset($prop['rules']) or !\is_array($prop['rules'])) {
throw new CrudException('$editableProperties[\'rules\'] array value must be an array');
}
if (count(array_diff_key($prop['rules'], $allowedRules))) {
throw new CrudException(sprintf(
'$editableProperties[\'rules\'] array contains unallowed rule, allowed are : %s',
implode(',', array_keys($allowedRules))
));
}
foreach ($allowedRules as $k => $f) {
if (array_key_exists($k, $prop['rules']) and !$f($prop['rules'][$k])) {
throw new CrudException(sprintf(
'$editableProperties[\'rules\'] rule `%s` does not validate with value `%s`',
$k,
$prop['rules'][$k]
));
}
}
}
private static function assertActionsArecorrect(array $prop): void
{
if (!isset($prop['actions']) or !\is_array($prop['actions'])) {
throw new CrudException('$editableProperties[\'actions\'] array value must be an array');
}
foreach ($prop['actions'] as $action) {
if (!is_object($action) or get_class($action) !== CrudAction::class) {
throw new CrudException(sprintf(
'$editableProperties[\'actions\'] array value must contain `%s` objects',
CrudAction::class
));
}
}
}
private static function assertEnumIscorrect(array $prop): void
{
if (
$prop['type']->equals(CrudType::enum()) and (is_null($prop['enum']) or
!\is_subclass_of($prop['enum'], BaseEnum::class))
) {
throw new CrudException(sprintf(
'$editableProperties[\'enum\'] array value must be an enum `%s`',
BaseEnum::class
));
}
}
private static function assertBelongsToIsCorrect(array $prop): void
{
if (is_null($prop['belongsTo'])) {
return;
}
if (
$prop['type']->equals(CrudType::belongsTo()) and
(!\is_string($prop['belongsTo']) or
!\class_exists($prop['belongsTo']) or
is_a($prop['belongsTo'], Model::class, true) or
!in_array(IsCrudModel::class, class_uses_recursive($prop['belongsTo'])))
) {
throw new CrudException(sprintf(
'$editableProperties[\'belongsTo\'] array value must be a CrudModel given: `%s`',
$prop['belongsTo']
));
}
}
private static function assertBelongsToManyIsCorrect(array $prop): void
{
if (is_null($prop['belongsToMany'])) {
return;
}
if (
$prop['type']->equals(CrudType::belongsToMany()) and
(!\is_string($prop['belongsToMany']) or
!\class_exists($prop['belongsToMany']) or
is_a($prop['belongsToMany'], Model::class, true) or
!in_array(IsCrudModel::class, class_uses_recursive($prop['belongsToMany'])))
) {
throw new CrudException(sprintf(
'$editableProperties[\'belongsToMany\'] array value must be a CrudModel given: `%s`',
$prop['belongsToMany']
));
}
if (
$prop['type']->equals(CrudType::belongsToMany()) and
(!\is_string($prop['belongsToManyLabel']))
) {
throw new CrudException(sprintf(
'$editableProperties[\'belongsToManyLabel\'] must be string using belongsToMany, given: `%s`',
$prop['belongsToMany']
));
}
}
/**
* Get eloquent relationships
*
* @url https://laracasts.com/discuss/channels/eloquent/get-all-model-relationships
*
* @return array
*/
private static function getRelationships()
{
$instance = new static();
// Get public methods declared without parameters and non inherited
$class = get_class($instance);
$allMethods = (new \ReflectionClass($class))->getMethods(\ReflectionMethod::IS_PUBLIC);
$methods = array_filter(
$allMethods,
function ($method) use ($class) {
return $method->class === $class
&& !$method->getParameters() // relationships have no parameters
&& $method->getName() !== 'getRelationships' // prevent infinite recursion
&& $method->getName() !== 'gotHasManyRelationWithRestrictOnDelete'; // prevent infinite recursion
}
);
DB::beginTransaction();
$relations = [];
foreach ($methods as $method) {
try {
$methodName = $method->getName();
$methodReturn = $instance->$methodName();
if (!$methodReturn instanceof Relation) {
continue;
}
} catch (\Throwable $th) {
continue;
}
$type = (new \ReflectionClass($methodReturn))->getShortName();
$model = get_class($methodReturn->getRelated());
$relations[$methodName] = [$type, $model];
}
DB::rollBack();
return $relations;
}
}

View file

@ -12,6 +12,7 @@
"fruitcake/laravel-cors": "^2.0",
"guzzlehttp/guzzle": "^7.0.1",
"htmlmin/htmlmin": "^8.0",
"kwaadpepper/crud-policies": "^0.0.1",
"kwaadpepper/enum": "^0.1.4",
"kwaadpepper/image-resizer": "^0.0.3",
"laravel/framework": "^8.12",
@ -28,7 +29,8 @@
"laravel/sail": "^1.0.1",
"mockery/mockery": "^1.4.2",
"nunomaduro/collision": "^5.0",
"phpunit/phpunit": "^9.3.3"
"phpunit/phpunit": "^9.3.3",
"squizlabs/php_codesniffer": "^3.6"
},
"autoload": {
"psr-4": {

1094
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -171,7 +171,6 @@ return [
*/
App\Providers\AppServiceProvider::class,
App\Providers\AuthServiceProvider::class,
// App\Providers\BroadcastServiceProvider::class,
App\Providers\EventServiceProvider::class,
App\Providers\RouteServiceProvider::class,
App\Providers\TranslationServiceProvider::class
@ -216,7 +215,6 @@ return [
'Password' => Illuminate\Support\Facades\Password::class,
'Queue' => Illuminate\Support\Facades\Queue::class,
'Redirect' => Illuminate\Support\Facades\Redirect::class,
// 'Redis' => Illuminate\Support\Facades\Redis::class,
'Request' => Illuminate\Support\Facades\Request::class,
'Response' => Illuminate\Support\Facades\Response::class,
'Route' => Illuminate\Support\Facades\Route::class,
@ -227,13 +225,10 @@ return [
'URL' => Illuminate\Support\Facades\URL::class,
'Validator' => Illuminate\Support\Facades\Validator::class,
'View' => Illuminate\Support\Facades\View::class,
'CrudAction' => App\Enums\CrudAction::class,
'CrudType' => App\Enums\CrudType::class,
'Carbon' => Illuminate\Support\Carbon::class,
'TypeSondage' => App\Enums\TypeSondage::class,
'Employee' => App\Models\Employee::class,
'Site' => App\Models\Site::class,
'Role' => App\Enums\Role::class
],
];

View file

@ -61,9 +61,7 @@ return [
env('MEMCACHED_USERNAME'),
env('MEMCACHED_PASSWORD'),
],
'options' => [
// Memcached::OPT_CONNECT_TIMEOUT => 2000,
],
'options' => [],
'servers' => [
[
'host' => env('MEMCACHED_HOST', '127.0.0.1'),

View file

@ -15,20 +15,17 @@ return [
* of your proxy (e.g. if using ELB or similar).
*
*/
'proxies' => '*', // [<ip addresses>,], '*', '<ip addresses>,'
'proxies' => '*',
/*
* To trust one or more specific proxies that connect
* directly to your server, use an array or a string separated by comma of IP addresses:
*/
// 'proxies' => ['192.168.1.1'],
// 'proxies' => '192.168.1.1, 192.168.1.2',
/*
* Or, to trust all proxies that connect
* directly to your server, use a "*"
*/
// 'proxies' => '*',
/*
* Which headers to use to detect proxy related data (For, Host, Proto, Port)
@ -45,6 +42,8 @@ return [
*
* @link https://symfony.com/doc/current/deployment/proxies.html
*/
'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_ALL,
'headers' => Illuminate\Http\Request::HEADER_X_FORWARDED_FOR |
Illuminate\Http\Request::HEADER_X_FORWARDED_HOST |
Illuminate\Http\Request::HEADER_X_FORWARDED_PORT |
Illuminate\Http\Request::HEADER_X_FORWARDED_PROTO,
];

View file

@ -24,13 +24,16 @@ class DatabaseSeeder extends Seeder
public function run()
{
Pole::factory(3)->create()->each(function (Pole $pole) {
Societe::factory(rand(2, 10))->create(['pole_id' => $pole])->each(function (Societe $societe) use ($pole) {
Site::factory(rand(1, 10))->create(['societe_id' => $societe])->each(function (Site $site) use ($societe) {
Societe::factory(rand(2, 10))
->create(['pole_id' => $pole])->each(function (Societe $societe) use ($pole) {
Site::factory(rand(1, 10))
->create(['societe_id' => $societe])->each(function (Site $site) use ($societe) {
Flash::factory(rand(2, 10))->create(['site_id' => $site]);
User::factory(rand(1, 2))->create()->each(function (User $user) use ($site) {
$user->sites()->syncWithoutDetaching([$site->id]);
});
Sondage::factory(rand(4, 7))->create(['site_id' => $site])->each(function (Sondage $sondage) use ($site) {
Sondage::factory(rand(4, 7))->create(['site_id' => $site])
->each(function (Sondage $sondage) use ($site) {
ReponseSondage::factory(rand(1, 3))->create(['sondage_id' => $sondage]);
});
Employee::factory(10)->create(['site_id' => $site]);

View file

@ -1,8 +1,5 @@
<?php
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Route;
/*
|--------------------------------------------------------------------------
| API Routes
@ -13,7 +10,3 @@ use Illuminate\Support\Facades\Route;
| is assigned the "api" middleware group. Enjoy building your API!
|
*/
// Route::middleware('auth:api')->get('/user', function (Request $request) {
// return $request->user();
// });

View file

@ -1,7 +1,5 @@
<?php
use Illuminate\Support\Facades\Broadcast;
/*
|--------------------------------------------------------------------------
| Broadcast Channels
@ -12,7 +10,3 @@ use Illuminate\Support\Facades\Broadcast;
| used to check if an authenticated user can listen to the channel.
|
*/
Broadcast::channel('App.Models.User.{id}', function ($user, $id) {
return (int)$user->id === (int)$id;
});

View file

@ -1,8 +1,5 @@
<?php
use Illuminate\Foundation\Inspiring;
use Illuminate\Support\Facades\Artisan;
/*
|--------------------------------------------------------------------------
| Console Routes
@ -13,7 +10,3 @@ use Illuminate\Support\Facades\Artisan;
| simple approach to interacting with each command's IO methods.
|
*/
Artisan::command('inspire', function () {
$this->comment(Inspiring::quote());
})->purpose('Display an inspiring quote');

View file

@ -69,7 +69,7 @@ Route::prefix('bo')
Route::middleware('guest:employee')
->group(function () {
Route::redirect('/', '/connexion')->name('home');
// Connexion
Route::view('/connexion', 'front.login')->name('employees.login');
Route::post('/connexion', [EmployeesController::class, 'loginSubmit'])->name('employees.loginSubmit')