diff --git a/app/Console/Commands/CreateAdmin.php b/app/Console/Commands/CreateAdmin.php index e6da7c7..1de2468 100644 --- a/app/Console/Commands/CreateAdmin.php +++ b/app/Console/Commands/CreateAdmin.php @@ -2,7 +2,7 @@ namespace App\Console\Commands; -use App\User; +use App\Models\User; use Illuminate\Console\Command; use Illuminate\Support\Facades\Validator; use Illuminate\Validation\ValidationException; diff --git a/app/Console/Commands/ExportDatas.php b/app/Console/Commands/ExportDatas.php index 417c59b..a8ab7f2 100644 --- a/app/Console/Commands/ExportDatas.php +++ b/app/Console/Commands/ExportDatas.php @@ -3,11 +3,11 @@ namespace App\Console\Commands; use App\Models\DatastorePcc; -use App\Models\DomainNames; -use App\Models\GitRepos; -use App\Models\LDCNetworks; -use App\Models\Projects; -use App\Models\Servers; +use App\Models\DomainName; +use App\Models\GitRepo; +use App\Models\LDCNetwork; +use App\Models\Project; +use App\Models\Server; use Illuminate\Console\Command; use Illuminate\Database\Eloquent\Collection; use Illuminate\Support\Facades\Storage; @@ -54,8 +54,8 @@ class ExportDatas extends Command */ private function exportGitRepos(string $filename) { - /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\GitRepos> */ - $repos = GitRepos::orderBy('name', 'ASC')->get(); + /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\GitRepo> */ + $repos = GitRepo::orderBy('name', 'ASC')->get(); Storage::disk('export')->append($filename, "Nom"); foreach ($repos as $repo) { $infos = [ @@ -74,8 +74,8 @@ class ExportDatas extends Command */ private function exportLdcNetworks(string $filename) { - /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\LDCNetworks> */ - $networks = LDCNetworks::all(); + /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\LDCNetwork> */ + $networks = LDCNetwork::all(); Storage::disk('export')->append($filename, "CIDR;First IP;Last IP"); foreach ($networks as $network) { $infos = [ @@ -96,8 +96,8 @@ class ExportDatas extends Command */ private function exportDomainNames(string $filename) { - /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\DomainNames> */ - $domains = DomainNames::all(); + /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\DomainName> */ + $domains = DomainName::all(); Storage::disk('export')->append( $filename, "ASCII;UTF-8;DATE D'EXPIRATION;RENOUVELLEMENT;MARQUE REF.;DNS REDIRIGES;TYPE CERTIFICATS;COMMENTAIRE" @@ -147,8 +147,8 @@ class ExportDatas extends Command */ private function exportServers(string $filename) { - /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Servers> */ - $servers = Servers::orderBy('env', 'DESC')->get(); + /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Server> */ + $servers = Server::orderBy('env', 'DESC')->get(); Storage::disk('export')->append( $filename, "ENV;NOM;TITRE;FUNCTION;SSH;IP INFRAWEB;VIRTUAL IP;DATASTORE PCC;COMMENTAIRE" @@ -178,8 +178,8 @@ class ExportDatas extends Command */ private function exportProjects(string $filename) { - /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Projects> */ - $projects = Projects::orderBy('name', 'ASC')->get(); + /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Project> */ + $projects = Project::orderBy('name', 'ASC')->get(); $fields = [ 'DEV', 'name', @@ -229,7 +229,7 @@ class ExportDatas extends Command */ private function writeProjectExport(Collection $projects, array $fields, string $filename) { - /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Projects> $projects */ + /** @var \Illuminate\Database\Eloquent\Collection<\App\Models\Project> $projects */ foreach ($projects as $project) { $infos = []; foreach ($fields as $field) { @@ -245,7 +245,7 @@ class ExportDatas extends Command case 'dev_db_server_id': case 'prod_web_server_id': case 'prod_db_server_id': - $server = Servers::find($project->{$field}); + $server = Server::find($project->{$field}); $infos[] = trim($server->name); $infos[] = trim($server->ssh); break; diff --git a/app/Enums/ProjectTypes.php b/app/Enums/ProjectTypes.php index 7053b5a..1482c1f 100644 --- a/app/Enums/ProjectTypes.php +++ b/app/Enums/ProjectTypes.php @@ -14,6 +14,11 @@ use Kwaadpepper\Enum\BaseEnumRoutable; */ final class ProjectTypes extends BaseEnumRoutable { + /** + * Enum values + * + * @return array + */ protected static function values(): array { return [ @@ -24,6 +29,11 @@ final class ProjectTypes extends BaseEnumRoutable ]; } + /** + * Enum labels + * + * @return array + */ protected static function labels(): array { return [ diff --git a/app/Enums/Smtp.php b/app/Enums/Smtp.php index 604131e..7e5c4e2 100644 --- a/app/Enums/Smtp.php +++ b/app/Enums/Smtp.php @@ -13,6 +13,11 @@ use Kwaadpepper\Enum\BaseEnumRoutable; */ final class Smtp extends BaseEnumRoutable { + /** + * Enum values + * + * @return array + */ protected static function values(): array { return [ @@ -22,6 +27,11 @@ final class Smtp extends BaseEnumRoutable ]; } + /** + * Enum labels + * + * @return array + */ protected static function labels(): array { return [ diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php index 88ed910..c65b9bc 100644 --- a/app/Exceptions/Handler.php +++ b/app/Exceptions/Handler.php @@ -2,53 +2,37 @@ namespace App\Exceptions; -use Throwable; use Kwaadpepper\ExceptionHandler\Exceptions\ExceptionHandler; +use Throwable; class Handler extends ExceptionHandler { /** * A list of the exception types that are not reported. * - * @var array + * @var array> */ - protected $dontReport = [ - ]; + protected $dontReport = []; /** * A list of the inputs that are never flashed for validation exceptions. * - * @var array + * @var array */ protected $dontFlash = [ + 'current_password', 'password', 'password_confirmation', ]; /** - * Report or log an exception. + * Register the exception handling callbacks for the application. * - * @param \Throwable $exception * @return void - * - * @throws \Throwable */ - public function report(Throwable $e) + public function register() { - parent::report($e); - } - - /** - * Render an exception into an HTTP response. - * - * @param \Illuminate\Http\Request $request - * @param \Throwable $exception - * @return \Symfony\Component\HttpFoundation\Response - * - * @throws \Exception - */ - public function render($request, Throwable $exception) - { - return parent::render($request, $exception); + $this->reportable(function (Throwable $e) { + }); } } diff --git a/app/Http/Controllers/API/LDCNetworksController.php b/app/Http/Controllers/API/LDCNetworksController.php index 33670a5..e80369a 100644 --- a/app/Http/Controllers/API/LDCNetworksController.php +++ b/app/Http/Controllers/API/LDCNetworksController.php @@ -3,7 +3,7 @@ namespace App\Http\Controllers\API; use App\Http\Controllers\Controller; -use App\Models\LDCNetworks; +use App\Models\LDCNetwork; use Illuminate\Http\Request; class LDCNetworksController extends Controller @@ -18,7 +18,7 @@ class LDCNetworksController extends Controller $ips = []; - $networks = LDCNetworks::all(); + $networks = LDCNetwork::all(); foreach ($networks as $network) { $infos = explode('.', $network->first_ip); $min = $infos[3]; diff --git a/app/Http/Controllers/API/StatusCheckerController.php b/app/Http/Controllers/API/StatusCheckerController.php index 70a2dc0..3101460 100644 --- a/app/Http/Controllers/API/StatusCheckerController.php +++ b/app/Http/Controllers/API/StatusCheckerController.php @@ -3,7 +3,7 @@ namespace App\Http\Controllers\API; use App\Http\Controllers\Controller; -use App\Models\Projects; +use App\Models\Project; use App\Models\ProjectsStatusChecker; use Illuminate\Http\Request; @@ -28,7 +28,7 @@ class StatusCheckerController extends Controller $project_sc = ProjectsStatusChecker::where('project_uuid', '=', $app_uuid)->first(); if (!$project_sc) { - $project = Projects::where('uuid', '=', $app_uuid)->first(); + $project = Project::where('uuid', '=', $app_uuid)->first(); if (!$project) { return response('Unknown', 404); } diff --git a/app/Http/Controllers/DatastorePCCController.php b/app/Http/Controllers/DatastorePCCController.php index 165cfc1..65710bd 100644 --- a/app/Http/Controllers/DatastorePCCController.php +++ b/app/Http/Controllers/DatastorePCCController.php @@ -3,7 +3,7 @@ namespace App\Http\Controllers; use App\Models\DatastorePcc; -use App\Models\Servers; +use App\Models\Server; use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -50,7 +50,7 @@ class DatastorePCCController extends Controller $dpcc_id = $request->id; $dpcc = DatastorePcc::findOrFail($dpcc_id); - $isUsed = Servers::where('datastore_pcc_id', '=', $dpcc->id)->get(); + $isUsed = Server::where('datastore_pcc_id', '=', $dpcc->id)->get(); if ($isUsed->count() === 0) { $isUsed = false; } diff --git a/app/Http/Controllers/DomainNamesController.php b/app/Http/Controllers/DomainNameController.php similarity index 85% rename from app/Http/Controllers/DomainNamesController.php rename to app/Http/Controllers/DomainNameController.php index 39f273b..cdec32e 100644 --- a/app/Http/Controllers/DomainNamesController.php +++ b/app/Http/Controllers/DomainNameController.php @@ -2,19 +2,19 @@ namespace App\Http\Controllers; -use App\Models\DomainNames; -use App\Models\EmailAddresses; +use App\Models\DomainName; +use App\Models\EmailAddress; use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; use lfkeitel\phptotp\Base32; use lfkeitel\phptotp\Totp; -class DomainNamesController extends Controller +class DomainNameController extends Controller { public function index(Request $request) { - $dms = DomainNames::all(); + $dms = DomainName::all(); return view('domain-names.index', ['dms' => $dms]); } @@ -26,21 +26,21 @@ class DomainNamesController extends Controller public function edit(Request $request) { $dm_id = $request->id; - $dm = DomainNames::findOrFail($dm_id); + $dm = DomainName::findOrFail($dm_id); return view('domain-names.edit', ['dm' => $dm]); } public function update(Request $request) { $dm_id = $request->id; - $dm = DomainNames::findOrFail($dm_id); + $dm = DomainName::findOrFail($dm_id); $this->makeChanges($request, $dm); return redirect()->route('domain-names.edit', ['id' => $dm->id])->with('status', 'Sauvegardé !'); } public function store(Request $request) { - $dm = new DomainNames(); + $dm = new DomainName(); $this->makeChanges($request, $dm); return redirect()->route('domain-names.edit', ['id' => $dm->id])->with('status', 'Sauvegardé !'); } @@ -48,9 +48,9 @@ class DomainNamesController extends Controller public function delete(Request $request) { $dm_id = $request->id; - $dm = DomainNames::findOrFail($dm_id); + $dm = DomainName::findOrFail($dm_id); - $isUsed = EmailAddresses::where('domain_name_id', '=', $dm->id)->get(); + $isUsed = EmailAddress::where('domain_name_id', '=', $dm->id)->get(); if ($isUsed->count() === 0) { $isUsed = false; } @@ -67,7 +67,7 @@ class DomainNamesController extends Controller $code = (new Totp())->GenerateToken(Base32::decode(Auth::user()->totp_secret)); if ($otp === $code || $otp === $lastCode) { - $dm = DomainNames::findOrFail($dm_id); + $dm = DomainName::findOrFail($dm_id); $dm->delete(); return redirect()->route('domain-names.index')->with('status', 'Nom de domaine supprimé !'); } else { diff --git a/app/Http/Controllers/EmailAddressesController.php b/app/Http/Controllers/EmailAddressesController.php index 3904ad2..164527f 100644 --- a/app/Http/Controllers/EmailAddressesController.php +++ b/app/Http/Controllers/EmailAddressesController.php @@ -2,8 +2,8 @@ namespace App\Http\Controllers; -use App\Models\DomainNames; -use App\Models\EmailAddresses; +use App\Models\DomainName; +use App\Models\EmailAddress; use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -14,35 +14,35 @@ class EmailAddressesController extends Controller { public function index(Request $request) { - $emails = EmailAddresses::all(); + $emails = EmailAddress::all(); return view('email-addresses.index', ['emails' => $emails]); } public function add(Request $request) { - $dms = DomainNames::orderBy('utf8_name')->get(); + $dms = DomainName::orderBy('utf8_name')->get(); return view('email-addresses.add', ['dms' => $dms]); } public function edit(Request $request) { $email_id = $request->id; - $email = EmailAddresses::findOrFail($email_id); - $dms = DomainNames::orderBy('utf8_name')->get(); + $email = EmailAddress::findOrFail($email_id); + $dms = DomainName::orderBy('utf8_name')->get(); return view('email-addresses.edit', ['email' => $email, 'dms' => $dms]); } public function update(Request $request) { $email_id = $request->id; - $email = EmailAddresses::findOrFail($email_id); + $email = EmailAddress::findOrFail($email_id); $this->makeChanges($request, $email); return redirect()->route('email-addresses.edit', ['id' => $email->id])->with('status', 'Sauvegardée !'); } public function store(Request $request) { - $email = new EmailAddresses(); + $email = new EmailAddress(); $this->makeChanges($request, $email); return redirect()->route('email-addresses.edit', ['id' => $email->id])->with('status', 'Sauvegardée !'); } @@ -50,7 +50,7 @@ class EmailAddressesController extends Controller public function delete(Request $request) { $email_id = $request->id; - $email = EmailAddresses::findOrFail($email_id); + $email = EmailAddress::findOrFail($email_id); return view('email-addresses.delete', ['email' => $email]); } @@ -63,7 +63,7 @@ class EmailAddressesController extends Controller $code = (new Totp())->GenerateToken(Base32::decode(Auth::user()->totp_secret)); if ($otp === $code || $otp === $lastCode) { - $email = EmailAddresses::findOrFail($email_id); + $email = EmailAddress::findOrFail($email_id); $email->delete(); return redirect()->route('email-addresses.index')->with('status', 'Adresse email supprimée !'); } else { diff --git a/app/Http/Controllers/GitReposController.php b/app/Http/Controllers/GitReposController.php index 574afc4..34f3a5c 100644 --- a/app/Http/Controllers/GitReposController.php +++ b/app/Http/Controllers/GitReposController.php @@ -4,7 +4,7 @@ namespace App\Http\Controllers; use App\Http\Requests\GitReposStoreRequest; use App\Http\Requests\GitReposUpdateRequest; -use App\Models\GitRepos; +use App\Models\GitRepo; class GitReposController extends Controller { @@ -15,7 +15,7 @@ class GitReposController extends Controller */ public function index() { - $repos = GitRepos::all(); + $repos = GitRepo::all(); return view('git-repos.index', compact('repos')); } @@ -38,7 +38,7 @@ class GitReposController extends Controller public function store(GitReposStoreRequest $request) { $datas = $request->validated(); - $git_repo = new GitRepos(); + $git_repo = new GitRepo(); $git_repo->fill($datas); $git_repo->save(); @@ -59,10 +59,10 @@ class GitReposController extends Controller /** * Show the form for editing the specified resource. * - * @param GitRepos $git_repo + * @param \App\Models\GitRepo $git_repo * @return \Illuminate\Http\Response */ - public function edit(GitRepos $git_repo) + public function edit(GitRepo $git_repo) { return view('git-repos.edit', compact('git_repo')); } @@ -71,10 +71,10 @@ class GitReposController extends Controller * Update the specified resource in storage. * * @param \Illuminate\Http\GitReposUpdateRequest $request - * @param GitRepos $git_repo + * @param \App\Models\GitRepo $git_repo * @return \Illuminate\Http\Response */ - public function update(GitReposUpdateRequest $request, GitRepos $git_repo) + public function update(GitReposUpdateRequest $request, GitRepo $git_repo) { $datas = $request->validated(); $git_repo->fill($datas); @@ -86,10 +86,10 @@ class GitReposController extends Controller /** * Remove the specified resource from storage. * - * @param GitRepos $git_repo + * @param \App\Models\GitRepo $git_repo * @return \Illuminate\Http\Response */ - public function destroy(GitRepos $git_repo) + public function destroy(GitRepo $git_repo) { $git_repo->delete(); return redirect()->route('git-repos.index')->with('status', __('Dépôt Git supprimé.')); diff --git a/app/Http/Controllers/LDCNetworkController.php b/app/Http/Controllers/LDCNetworkController.php index 4841004..5f7e17f 100644 --- a/app/Http/Controllers/LDCNetworkController.php +++ b/app/Http/Controllers/LDCNetworkController.php @@ -2,7 +2,7 @@ namespace App\Http\Controllers; -use App\Models\LDCNetworks; +use App\Models\LDCNetwork; use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -13,7 +13,7 @@ class LDCNetworkController extends Controller { public function index(Request $request) { - $networks = LDCNetworks::all(); + $networks = LDCNetwork::all(); return view('ldc-networks.index', ['networks' => $networks]); } @@ -25,21 +25,21 @@ class LDCNetworkController extends Controller public function edit(Request $request) { $network_id = $request->id; - $network = LDCNetworks::findOrFail($network_id); + $network = LDCNetwork::findOrFail($network_id); return view('ldc-networks.edit', ['network' => $network]); } public function update(Request $request) { $network_id = $request->id; - $network = LDCNetworks::findOrFail($network_id); + $network = LDCNetwork::findOrFail($network_id); $this->makeChanges($request, $network); return redirect()->route('ldc-networks.edit', ['id' => $network->id])->with('status', 'Sauvegardée !'); } public function store(Request $request) { - $network = new LDCNetworks(); + $network = new LDCNetwork(); $this->makeChanges($request, $network); return redirect()->route('ldc-networks.edit', ['id' => $network->id])->with('status', 'Sauvegardée !'); } @@ -47,7 +47,7 @@ class LDCNetworkController extends Controller public function delete(Request $request) { $network_id = $request->id; - $network = LDCNetworks::findOrFail($network_id); + $network = LDCNetwork::findOrFail($network_id); return view('ldc-networks.delete', ['network' => $network]); } @@ -61,7 +61,7 @@ class LDCNetworkController extends Controller $code = (new Totp())->GenerateToken(Base32::decode(Auth::user()->totp_secret)); if ($otp === $code || $otp === $lastCode) { - $network = LDCNetworks::findOrFail($network_id); + $network = LDCNetwork::findOrFail($network_id); $network->delete(); return redirect()->route('ldc-networks.index')->with('status', 'IP supprimée !'); } else { diff --git a/app/Http/Controllers/ProjectsController.php b/app/Http/Controllers/ProjectsController.php index 0746571..ccce4b7 100644 --- a/app/Http/Controllers/ProjectsController.php +++ b/app/Http/Controllers/ProjectsController.php @@ -4,8 +4,8 @@ namespace App\Http\Controllers; use App\Http\Requests\Projects\StoreProjects; use App\Http\Requests\Projects\UpdateProjects; -use App\Models\Projects; -use App\Models\Servers; +use App\Models\Project; +use App\Models\Server; use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -17,25 +17,25 @@ class ProjectsController extends Controller { public function index(Request $request) { - $projects = Projects::orderBy('name')->get(); + $projects = Project::orderBy('name')->get(); return view('projects.index', ['projects' => $projects]); } public function add(Request $request) { - $dev_db_server = Servers::where([ + $dev_db_server = Server::where([ ['env', 'DEV'], ['type', 'DB'] ])->get(); - $dev_web_server = Servers::where([ + $dev_web_server = Server::where([ ['env', 'DEV'], ['type', 'WEB'] ])->get(); - $prod_db_server = Servers::where([ + $prod_db_server = Server::where([ ['env', 'PROD'], ['type', 'DB'] ])->get(); - $prod_web_server = Servers::where([ + $prod_web_server = Server::where([ ['env', 'PROD'], ['type', 'WEB'] ])->get(); @@ -45,24 +45,24 @@ class ProjectsController extends Controller public function edit(Request $request) { $uuid = $request->uuid; - $project = Projects::where('uuid', '=', $uuid)->first(); + $project = Project::where('uuid', '=', $uuid)->first(); if (!$project) { abort(404); } - $dev_db_server = Servers::where([ + $dev_db_server = Server::where([ ['env', 'DEV'], ['type', 'DB'] ])->get(); - $dev_web_server = Servers::where([ + $dev_web_server = Server::where([ ['env', 'DEV'], ['type', 'WEB'] ])->get(); - $prod_db_server = Servers::where([ + $prod_db_server = Server::where([ ['env', 'PROD'], ['type', 'DB'] ])->get(); - $prod_web_server = Servers::where([ + $prod_web_server = Server::where([ ['env', 'PROD'], ['type', 'WEB'] ])->get(); @@ -72,7 +72,7 @@ class ProjectsController extends Controller public function update(UpdateProjects $request) { $uuid = $request->uuid; - $project = Projects::where('uuid', '=', $uuid)->first(); + $project = Project::where('uuid', '=', $uuid)->first(); if (!$project) { abort(404); } @@ -82,7 +82,7 @@ class ProjectsController extends Controller public function store(StoreProjects $request) { - $project = new Projects(); + $project = new Project(); $project->uuid = Uuid::uuid4(); $this->makeChanges($request, $project); return redirect()->route('projects.edit', ['uuid' => $project->uuid])->with('status', 'Sauvegardé !'); @@ -91,7 +91,7 @@ class ProjectsController extends Controller public function delete(Request $request) { $uuid = $request->uuid; - $project = Projects::where('uuid', '=', $uuid)->first(); + $project = Project::where('uuid', '=', $uuid)->first(); if (!$project) { abort(404); } @@ -107,7 +107,7 @@ class ProjectsController extends Controller $code = (new Totp())->GenerateToken(Base32::decode(Auth::user()->totp_secret)); if ($otp === $code || $otp === $lastCode) { - $project = Projects::where('uuid', '=', $uuid)->first(); + $project = Project::where('uuid', '=', $uuid)->first(); if (!$project) { abort(404); } @@ -118,7 +118,7 @@ class ProjectsController extends Controller } } - private function makeChanges(Request $request, $project) + private function makeChanges(Request $request, Project $project) { $name = $request->name; $display_name = $request->display_name; diff --git a/app/Http/Controllers/ServersController.php b/app/Http/Controllers/ServersController.php index d8aa64b..1b4389f 100644 --- a/app/Http/Controllers/ServersController.php +++ b/app/Http/Controllers/ServersController.php @@ -3,8 +3,8 @@ namespace App\Http\Controllers; use App\Models\DatastorePcc; -use App\Models\Projects; -use App\Models\Servers; +use App\Models\Project; +use App\Models\Server; use Carbon\Carbon; use Illuminate\Http\Request; use Illuminate\Support\Facades\Auth; @@ -15,7 +15,7 @@ class ServersController extends Controller { public function index(Request $request) { - $servers = Servers::all(); + $servers = Server::all(); return view('servers.index', ['servers' => $servers]); } @@ -28,7 +28,7 @@ class ServersController extends Controller public function edit(Request $request) { $server_id = $request->id; - $server = Servers::findOrFail($server_id); + $server = Server::findOrFail($server_id); $datastores_pcc = DatastorePcc::orderBy('title')->get(); return view('servers.edit', ['server' => $server, 'datastores_pcc' => $datastores_pcc]); } @@ -36,14 +36,14 @@ class ServersController extends Controller public function update(Request $request) { $server_id = $request->id; - $server = Servers::findOrFail($server_id); + $server = Server::findOrFail($server_id); $this->makeChanges($request, $server); return redirect()->route('servers.edit', ['id' => $server_id])->with('status', 'Sauvegardé !'); } public function store(Request $request) { - $server = new Servers(); + $server = new Server(); $this->makeChanges($request, $server); return redirect()->route('servers.edit', ['id' => $server->id])->with('status', 'Sauvegardé !'); } @@ -51,10 +51,10 @@ class ServersController extends Controller public function delete(Request $request) { $server_id = $request->id; - $server = Servers::findOrFail($server_id); + $server = Server::findOrFail($server_id); if ($server->type === 'DB' || $server->type === 'WEB') { - $isUsed = Projects::where('dev_db_server_id', '=', $server->id)->orWhere('dev_web_server_id', '=', $server->id)->orWhere('prod_db_server_id', '=', $server->id)->orWhere('prod_web_server_id', '=', $server->id)->get(); + $isUsed = Project::where('dev_db_server_id', '=', $server->id)->orWhere('dev_web_server_id', '=', $server->id)->orWhere('prod_db_server_id', '=', $server->id)->orWhere('prod_web_server_id', '=', $server->id)->get(); if ($isUsed->count() === 0) { $isUsed = false; } @@ -74,7 +74,7 @@ class ServersController extends Controller $code = (new Totp())->GenerateToken(Base32::decode(Auth::user()->totp_secret)); if ($otp === $code || $otp === $lastCode) { - $server = Servers::findOrFail($server_id); + $server = Server::findOrFail($server_id); $server->delete(); return redirect()->route('servers.index')->with('status', 'Serveur supprimé !'); } else { @@ -82,7 +82,7 @@ class ServersController extends Controller } } - private function makeChanges($request, $server) + private function makeChanges($request, Server $server) { $env = $request->env; $virtual_ip = $request->virtual_ip; diff --git a/app/Http/Controllers/StatusCheckerController.php b/app/Http/Controllers/StatusCheckerController.php index 2f798f7..7bec7fb 100644 --- a/app/Http/Controllers/StatusCheckerController.php +++ b/app/Http/Controllers/StatusCheckerController.php @@ -2,7 +2,7 @@ namespace App\Http\Controllers; -use App\Models\Projects; +use App\Models\Project; use Illuminate\Http\Request; class StatusCheckerController extends Controller @@ -24,7 +24,7 @@ class StatusCheckerController extends Controller $laravel_latest = substr($content, 84); $laravel_latest = substr($laravel_latest, 0, -31); - $projects = Projects::orderBy('name')->get(); + $projects = Project::orderBy('name')->get(); return view('status-checker.index', ['projects' => $projects, 'wp_latest' => $oContent->offers[0]->version, 'laravel_latest' => $laravel_latest]); } } diff --git a/app/Http/Kernel.php b/app/Http/Kernel.php index 8c5491f..ff1a327 100644 --- a/app/Http/Kernel.php +++ b/app/Http/Kernel.php @@ -11,11 +11,13 @@ class Kernel extends HttpKernel * * These middleware are run during every request to your application. * - * @var array + * @var array */ protected $middleware = [ + \App\Http\Middleware\TrustHosts::class, \App\Http\Middleware\TrustProxies::class, - \App\Http\Middleware\CheckForMaintenanceMode::class, + \Fruitcake\Cors\HandleCors::class, + \App\Http\Middleware\PreventRequestsDuringMaintenance::class, \Illuminate\Foundation\Http\Middleware\ValidatePostSize::class, \App\Http\Middleware\TrimStrings::class, \Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class, @@ -24,17 +26,19 @@ class Kernel extends HttpKernel /** * The application's route middleware groups. * - * @var array + * @var array> */ protected $middlewareGroups = [ 'web' => [ + 'htmlsanitize', \App\Http\Middleware\EncryptCookies::class, \Illuminate\Cookie\Middleware\AddQueuedCookiesToResponse::class, \Illuminate\Session\Middleware\StartSession::class, - // \Illuminate\Session\Middleware\AuthenticateSession::class, + \Illuminate\Session\Middleware\AuthenticateSession::class, \Illuminate\View\Middleware\ShareErrorsFromSession::class, \App\Http\Middleware\VerifyCsrfToken::class, \Illuminate\Routing\Middleware\SubstituteBindings::class, + \App\Http\Middleware\SecureHeaders::class ], 'api' => [ @@ -54,7 +58,7 @@ class Kernel extends HttpKernel * * These middleware may be assigned to groups or used individually. * - * @var array + * @var array */ protected $routeMiddleware = [ 'auth' => \App\Http\Middleware\Authenticate::class, @@ -67,6 +71,7 @@ class Kernel extends HttpKernel 'signed' => \Illuminate\Routing\Middleware\ValidateSignature::class, 'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class, 'verified' => \Illuminate\Auth\Middleware\EnsureEmailIsVerified::class, + 'htmlsanitize' => \App\Http\Middleware\HtmlSanitizer::class, ]; /** diff --git a/app/Http/Middleware/CheckForMaintenanceMode.php b/app/Http/Middleware/CheckForMaintenanceMode.php deleted file mode 100644 index 9037ddf..0000000 --- a/app/Http/Middleware/CheckForMaintenanceMode.php +++ /dev/null @@ -1,16 +0,0 @@ -all(); + array_walk_recursive($inputs, function (&$input, $name) use ($params) { + if (!is_string($input)) { + return; + } + if (in_array($name, $params)) { + // ? Is a json input ? + if ($isJson = \json_decode($input, true) and is_array($isJson)) { + // ! Decode each json field recursive. + \array_walk_recursive($isJson, function (&$item) { + if (\is_string($item)) { + $item = clean($item); + $item = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($item); + } + }); + } else { + $input = clean($input); + $input = ToolboxHelper::stripCkEditorSchemesOnMediaInputs($input); + } + } else { + $input = strip_tags($input); + } + }); + $request->merge($inputs); + return $next($request); + } +} diff --git a/app/Http/Middleware/PreventRequestsDuringMaintenance.php b/app/Http/Middleware/PreventRequestsDuringMaintenance.php new file mode 100644 index 0000000..842e4b9 --- /dev/null +++ b/app/Http/Middleware/PreventRequestsDuringMaintenance.php @@ -0,0 +1,15 @@ + + */ + protected $except = []; +} diff --git a/app/Http/Middleware/SecureHeaders.php b/app/Http/Middleware/SecureHeaders.php new file mode 100644 index 0000000..ad3a71f --- /dev/null +++ b/app/Http/Middleware/SecureHeaders.php @@ -0,0 +1,80 @@ +removeUnwantedHeaders($this->unwantedHeaderList); + $response = $next($request); + $response->headers->set('Referrer-Policy', 'no-referrer-when-downgrade'); + $response->headers->set('X-Content-Type-Options', 'nosniff'); + $response->headers->set('X-XSS-Protection', '1; mode=block'); + $response->headers->set('X-Frame-Options', 'SAMEORIGIN'); + $response->headers->set('Strict-Transport-Security', 'max-age=31536000; includeSubDomains;'); + $cspPolicies = [ + "default-src 'none';", + // * CKEDITOR Specific https://ckeditor.com/docs/ckeditor5/latest/installation/advanced/csp.html + "connect-src 'self' blob:;", + "img-src * data: blob:;", + "frame-src https://www.youtube.com;", + "font-src 'self' data:;", + // ! Using CKEditor wiill must have unsafe-inline style + // phpcs:ignore Generic.Files.LineLength.TooLong + // "style-src 'self' 'unsafe-inline';", + // ! If you dont use ckeditor use this + "style-src 'self' 'nonce-$nonce';", + // phpcs:ignore Generic.Files.LineLength.TooLong + "script-src 'self' $jsDev;" + ]; + $response->headers->set( + 'Content-Security-Policy', + implode(' ', $cspPolicies) . $reportUri + ); + $response->headers->set('Feature-Policy', 'fullscreen \'self\';'); + return $response; + } + + /** + * Remove unwanted headers + * + * @param array $headerList + * @return void + */ + private function removeUnwantedHeaders(array $headerList) + { + foreach ($headerList as $header) { + header_remove($header); + } + } +} diff --git a/app/Http/Middleware/TrustHosts.php b/app/Http/Middleware/TrustHosts.php new file mode 100644 index 0000000..7186414 --- /dev/null +++ b/app/Http/Middleware/TrustHosts.php @@ -0,0 +1,20 @@ + + */ + public function hosts() + { + return [ + $this->allSubdomainsOfApplicationUrl(), + ]; + } +} diff --git a/app/Lib/LDC/MailjetSms.php b/app/Lib/LDC/MailjetSms.php index 3eb3a02..094c73a 100644 --- a/app/Lib/LDC/MailjetSms.php +++ b/app/Lib/LDC/MailjetSms.php @@ -4,7 +4,6 @@ namespace App\Lib\LDC; use GuzzleHttp\Client; use Illuminate\Contracts\Foundation\Application; -use Illuminate\Support\Facades\Log; use Psr\Http\Message\ResponseInterface; class MailjetSms @@ -15,19 +14,34 @@ class MailjetSms /** @var array $config */ protected $config = []; + /** + * MailjetSms + * + * @param \Illuminate\Contracts\Foundation\Application $app + */ public function __construct(Application $app) { $this->app = $app; $this->loadDefaultOptions(); } - protected function loadDefaultOptions(): MailjetSms + /** + * loadDefaultOptions + * + * @return \App\Lib\LDC\MailjetSms + */ + protected function loadDefaultOptions(): \App\Lib\LDC\MailjetSms { $this->config = $this->app['config']->get('services.mailjet'); return $this; } - protected function buildHttpClient(): Client + /** + * buildHttpClient + * + * @return \GuzzleHttp\Client + */ + protected function buildHttpClient(): \GuzzleHttp\Client { return new Client([ 'allow_redirects' => false, @@ -43,7 +57,16 @@ class MailjetSms ]); } - public function send(string $message, string $to, $from = null): ResponseInterface + /** + * send sms + * + * @param string $message + * @param string $to + * @param string|null $from + * @return \Psr\Http\Message\ResponseInterface + * @throws \GuzzleHttp\Exception\RequestException If Mailsms send service call failed. + */ + public function send(string $message, string $to, ?string $from = null): ResponseInterface { $from = $from ?? $this->config['sms_from']; $client = $this->buildHttpClient(); @@ -56,16 +79,11 @@ class MailjetSms 'To' => $to, ] ]); - } catch (\GuzzleHttp\Exception\RequestException $ex) { - Log::debug('error ' . $ex->getMessage()); - if (!is_null($ex->getResponse())) { - Log::debug((string)$ex->getResponse()->getBody()); - } - throw $ex; + } catch (\GuzzleHttp\Exception\RequestException $e) { + report($e); + throw $e; } - - return $response; } } diff --git a/app/Lib/ToolboxHelper.php b/app/Lib/ToolboxHelper.php new file mode 100644 index 0000000..3b6a939 --- /dev/null +++ b/app/Lib/ToolboxHelper.php @@ -0,0 +1,228 @@ +)/m', '', $input); + return $input; + } + + /** + * Assert That no Back Office url is present on txt + * + * @param string $field + * @param string $text + * @return string + * @throws \Illuminate\Validation\ValidationException If url is a bo url. + */ + public static function assertNoInternalBoUrls(string $field, string $text): string + { + $routes = Route::getRoutes(); + // * Url replace and email replace. + $text = preg_replace_callback( + // phpcs:ignore Generic.Files.LineLength.TooLong + '/(?P(?:http[s]?:\/\/.)?(?:www\.)?[-a-zA-Z0-9@%._\+~#=]{2,256}\.[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_\+.~#?&\/\/=]*))/', + function ($matches) use ($routes, $field) { + $match = collect($matches)->first() ?? ''; + $url = $match; + try { + $request = Request::create($url); + // If a route is match then it do not throws exception. + if ( + \parse_url(config('app.url'), \PHP_URL_HOST) === \parse_url($url, \PHP_URL_HOST) && + trim($routes->match($request)->getPrefix() ?? '', '/') === 'bo' + ) { + // Removes the matched url. + throw ValidationException::withMessages([ + $field => sprintf( + '%s : Il est interdit de coller une url du back office dans ce champ', + trans($field) + ) + ]); + } + return $match; + } catch (NotFoundHttpException $e) { + return $match; + } + }, + $text + ); + return $text; + } + + /** + * Assert That only external url is present on txt + * + * @param string $field + * @param string $text + * @return string + * @throws \Illuminate\Validation\ValidationException If url is a bo url. + */ + public static function assertNoInternalUrls(string $field, string $text): string + { + self::assertNoInternalBoUrls($field, $text); + $routes = Route::getRoutes(); + // * Url replace and email replace. + $text = preg_replace_callback( + // phpcs:ignore Generic.Files.LineLength.TooLong + '/(?P(?:http[s]?:\/\/.)?(?:www\.)?[-a-zA-Z0-9@%._\+~#=]{2,256}\.[a-z]{2,6}\b(?:[-a-zA-Z0-9@:%_\+.~#?&\/\/=]*))/', + function ($matches) use ($routes, $field) { + $match = collect($matches)->first() ?? ''; + $url = $match; + try { + $request = Request::create($url); + // If a route is match then it do not throws exception. + if ( + \parse_url(config('app.url'), \PHP_URL_HOST) === \parse_url($url, \PHP_URL_HOST) && + $routes->match($request) + ) { + // Removes the matched url. + throw ValidationException::withMessages([ + $field => sprintf( + '%s : Il est interdit de coller une url de %s dans ce champ', + trans($field), + config('app.name') + ) + ]); + } + return $match; + } catch (NotFoundHttpException $e) { + return $match; + } + }, + $text + ); + return $text; + } + + /** + * Generates an array from a dot separated string + * + * @param string $path + * @param mixed $value + * @param string $separator + * @return array + */ + public static function dotStringToNestedArray(string $path, $value, string $separator = '.'): array + { + $arr = $value; + $keys = array_reverse(explode($separator, $path)); + + foreach ($keys as $key) { + $arr = [$key => $arr]; + } + return $arr; + } + + /** + * Destroy image + * + * @param \Illuminate\Database\Eloquent\Model $model + * @param string $attribute + * @return void + */ + public static function removeImage(Model $model, string $attribute) + { + $path = ltrim($model->{$attribute}, '/'); + if (File::exists($path) and \strpos($path, 'storage') === 0) { + File::delete($path); + } + } + + /** + * Destroy image + * + * @param \Illuminate\Database\Eloquent\Model $model + * @param string $attribute + * @return void + */ + public static function removeOldImage(Model $model, string $attribute) + { + $originalPath = ltrim($model->getOriginal($attribute), '/'); + if (File::exists($originalPath) and \strpos($originalPath, 'storage') === 0) { + File::delete($originalPath); + } + } + + /** + * Store an image of different types + * + * @param \Illuminate\Database\Eloquent\Model $model + * @param \Illuminate\Http\UploadedFile|\SplFileInfo|string $image + * @return string + * @throws \ErrorException If file copy fails. + */ + public static function storeImage(Model $model, $image): string + { + $table = $model->getTable(); + if (\is_object($image) and $image instanceof \Illuminate\Http\UploadedFile) { + /** @var \Illuminate\Http\UploadedFile $image */ + $newPath = self::prepareMoveFile($table, \filter_var( + \strip_tags(\urldecode($image->getClientOriginalName())), + \FILTER_SANITIZE_STRING + )); + $newPath = str_replace(storage_path('app'), '', $newPath); + $image->storePubliclyAs( + pathinfo($newPath, \PATHINFO_DIRNAME), + pathinfo($newPath, \PATHINFO_BASENAME) + ); + return 'storage' . str_replace('/public', '', $newPath); + } + if (\is_object($image) and $image instanceof \SplFileInfo) { + /** @var \SplFileInfo $image */ + $newPath = self::prepareMoveFile($table, $image->getBaseName()); + if (!File::copy($image->getRealPath(), $newPath)) { + throw new \ErrorException(sprintf( + 'Failed to copy file %s to %s', + $image->getRealPath(), + $newPath + )); + } + return \ltrim(str_replace(\storage_path('app/public'), '/storage', $newPath), '/'); + } + return \ltrim(strval($image), '/'); + } + + /** + * Prepare storage path and return + * the image full path + * + * @param string $table Model table name. + * @param string $filename The basename for the file. + * @return string + */ + private static function prepareMoveFile(string $table, string $filename): string + { + $pathFolder = \storage_path(sprintf('app/public/images/%s', $table)); + if (!File::exists($pathFolder)) { + File::makeDirectory($pathFolder, 0755, true); + } + $filename = sprintf('%s-%s', Str::uuid(), $filename); + $fullPath = sprintf('%s/%s', $pathFolder, $filename); + if (File::exists($fullPath)) { + File::delete($fullPath); + } + return $fullPath; + } +} diff --git a/app/Mail/Webhooks/Gitlab.php b/app/Mail/Webhooks/Gitlab.php index 2f55c8b..d299c7a 100644 --- a/app/Mail/Webhooks/Gitlab.php +++ b/app/Mail/Webhooks/Gitlab.php @@ -11,16 +11,21 @@ class Gitlab extends Mailable use Queueable; use SerializesModels; - public $datas; + /** + * Mail data + * + * @var array + */ + public $data; /** * Create a new message instance. * - * @return void + * @param array $data */ - public function __construct(array $datas) + public function __construct(array $data) { - $this->datas = $datas; + $this->data = $data; } /** diff --git a/app/Models/DatastorePcc.php b/app/Models/DatastorePcc.php index 718ed8b..efe7fc6 100644 --- a/app/Models/DatastorePcc.php +++ b/app/Models/DatastorePcc.php @@ -6,5 +6,10 @@ use Illuminate\Database\Eloquent\Model; class DatastorePcc extends Model { + /** + * The table associated with the model. + * + * @var string + */ protected $table = 'datastore_pcc'; } diff --git a/app/Models/DomainNames.php b/app/Models/DomainName.php similarity index 70% rename from app/Models/DomainNames.php rename to app/Models/DomainName.php index 179f09e..d5c9401 100644 --- a/app/Models/DomainNames.php +++ b/app/Models/DomainName.php @@ -4,6 +4,6 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; -class DomainNames extends Model +class DomainName extends Model { } diff --git a/app/Models/EmailAddress.php b/app/Models/EmailAddress.php new file mode 100644 index 0000000..61bd67c --- /dev/null +++ b/app/Models/EmailAddress.php @@ -0,0 +1,21 @@ +domain_name_id); + return $dn->utf8_name; + } +} diff --git a/app/Models/EmailAddresses.php b/app/Models/EmailAddresses.php deleted file mode 100644 index 4170bb9..0000000 --- a/app/Models/EmailAddresses.php +++ /dev/null @@ -1,14 +0,0 @@ -domain_name_id); - return $dn->utf8_name; - } -} diff --git a/app/Models/GitRepo.php b/app/Models/GitRepo.php new file mode 100644 index 0000000..d583160 --- /dev/null +++ b/app/Models/GitRepo.php @@ -0,0 +1,18 @@ + 'array' ]; + // * METHODS + + /** + * get dev_web_ip attribute + * + * @return mixed + */ public function getDevWebIpAttribute() { - $value = Servers::find($this->dev_web_server_id); + $value = Server::find($this->dev_web_server_id); if ($value) { $value = $value->ssh; } return $value; } + /** + * get dev_db_ip attribute + * + * @return mixed + */ public function getDevDbIpAttribute() { - $value = Servers::find($this->dev_db_server_id); + $value = Server::find($this->dev_db_server_id); if ($value) { $value = $value->ssh; } return $value; } + /** + * get prod_web_ip attribute + * + * @return mixed + */ public function getProdWebIpAttribute() { - $value = Servers::find($this->prod_web_server_id); + $value = Server::find($this->prod_web_server_id); if ($value) { $value = $value->ssh; } return $value; } + /** + * get prod_db_ip attribute + * + * @return mixed + */ public function getProdDbIpAttribute() { - $value = Servers::find($this->prod_db_server_id); + $value = Server::find($this->prod_db_server_id); if ($value) { $value = $value->ssh; } return $value; } + /** + * get checked attribute + * + * @return mixed + */ public function getCheckedAttribute() { $value = ProjectsStatusChecker::select('updated_at')->where('project_uuid', '=', $this->uuid)->first(); @@ -69,6 +96,12 @@ class Projects extends Model } return $value; } + + /** + * get sitemap_checked attribute + * + * @return mixed + */ public function getSitemapCheckedAttribute() { $value = ProjectsStatusChecker::select('sitemap')->where('project_uuid', '=', $this->uuid)->first(); @@ -80,6 +113,11 @@ class Projects extends Model return $value; } + /** + * get robots_checked attribute + * + * @return mixed + */ public function getRobotsCheckedAttribute() { $value = ProjectsStatusChecker::select('robots')->where('project_uuid', '=', $this->uuid)->first(); @@ -91,6 +129,11 @@ class Projects extends Model return $value; } + /** + * get logs_checked attribute + * + * @return mixed + */ public function getLogsCheckedAttribute() { $value = ProjectsStatusChecker::select('logs')->where('project_uuid', '=', $this->uuid)->first(); @@ -102,6 +145,11 @@ class Projects extends Model return $value; } + /** + * get code attribute + * + * @return mixed + */ public function getCodeAttribute() { $value = ProjectsStatusChecker::select('code')->where('project_uuid', '=', $this->uuid)->first(); @@ -113,13 +161,24 @@ class Projects extends Model return $value; } - public function getLogsHrAttribute() + /** + * get logs_hr attribute + * + * @return float + */ + public function getLogsHrAttribute(): float { $value = ProjectsStatusChecker::select('logs')->where('project_uuid', '=', $this->uuid)->first(); - return $this->human_filesize($value->logs); + return $this->humanFilesize($value->logs); } - private function human_filesize($size, $precision = 2) + /** + * Human readable file size + * + * @param float $size + * @return float + */ + private function humanFilesize(float $size): float { $i = floor(log($size, 1024)); return round($size / pow(1024, $i), [0,0,2,2,3][$i]) . [' O',' Ko',' Mo',' Go',' To'][$i]; diff --git a/app/Models/ProjectsStatusChecker.php b/app/Models/ProjectsStatusChecker.php index 39bea1f..b0e83c3 100644 --- a/app/Models/ProjectsStatusChecker.php +++ b/app/Models/ProjectsStatusChecker.php @@ -6,5 +6,10 @@ use Illuminate\Database\Eloquent\Model; class ProjectsStatusChecker extends Model { + /** + * The table associated with the model. + * + * @var string + */ protected $table = 'projects_status_checker'; } diff --git a/app/Models/Servers.php b/app/Models/Server.php similarity index 72% rename from app/Models/Servers.php rename to app/Models/Server.php index 28ee324..7fed83c 100644 --- a/app/Models/Servers.php +++ b/app/Models/Server.php @@ -4,6 +4,6 @@ namespace App\Models; use Illuminate\Database\Eloquent\Model; -class Servers extends Model +class Server extends Model { } diff --git a/app/User.php b/app/Models/User.php similarity index 97% rename from app/User.php rename to app/Models/User.php index 6c58d05..445916c 100644 --- a/app/User.php +++ b/app/Models/User.php @@ -1,6 +1,6 @@ map(function ($contant) { + setlocale( + $contant, + \sprintf( + '%s_%s.UTF-8', + config('app.locale'), + \strtoupper(config('app.locale')) + ) + ); + }); + Carbon::setLocale(config('app.locale')); + + // * Force bootstrap paginator + Paginator::useBootstrap(); + + // * HA PROXY FIX + app()->singleton('clientIp', function () { + if ( + config('app.env') === 'local' + ) { + return request()->getClientIp(); + } + return request()->server('HTTP_X_FORWARDED_FOR') ?? request()->getClientIp(); + }); } } diff --git a/app/Providers/AuthServiceProvider.php b/app/Providers/AuthServiceProvider.php index 7971bf7..afb0cf8 100644 --- a/app/Providers/AuthServiceProvider.php +++ b/app/Providers/AuthServiceProvider.php @@ -9,11 +9,9 @@ class AuthServiceProvider extends ServiceProvider /** * The policy mappings for the application. * - * @var array + * @var array */ - protected $policies = [ - // 'App\Model' => 'App\Policies\ModelPolicy', - ]; + protected $policies = []; /** * Register any authentication / authorization services. diff --git a/app/Providers/BroadcastServiceProvider.php b/app/Providers/BroadcastServiceProvider.php deleted file mode 100644 index 395c518..0000000 --- a/app/Providers/BroadcastServiceProvider.php +++ /dev/null @@ -1,21 +0,0 @@ -getSaml2Auth()->getLastMessageId(); - // TODO : Add your own code preventing reuse of a $messageId to stop replay attacks + // TODO: Add your own code preventing reuse of a $messageId to stop replay attacks. $user = $event->getSaml2User(); $email = $user->getNameId(); $lUser = User::where('email', '=', $email)->first(); @@ -48,6 +48,7 @@ class EventServiceProvider extends ServiceProvider abort(redirect()->route('auth.verify')); }); + // phpcs:ignore Generic.CodeAnalysis.UnusedFunctionParameter.FoundInExtendedClass Event::listen('Aacotroneo\Saml2\Events\Saml2LogoutEvent', function ($event) { Auth::logout(); Session::save(); diff --git a/app/Providers/MailjetSmsServiceProvider.php b/app/Providers/MailjetSmsServiceProvider.php index ab66475..2ce2d14 100644 --- a/app/Providers/MailjetSmsServiceProvider.php +++ b/app/Providers/MailjetSmsServiceProvider.php @@ -2,7 +2,6 @@ namespace App\Providers; -use Illuminate\Support\Facades\App; use Illuminate\Support\ServiceProvider; use App\Lib\LDC\MailjetSms; @@ -24,7 +23,7 @@ class MailjetSmsServiceProvider extends ServiceProvider */ public function boot() { - App::singleton('MailjetSms', function ($app) { + $this->app->singleton('MailjetSms', function ($app) { return new MailjetSms($app); }); } diff --git a/app/Providers/RouteServiceProvider.php b/app/Providers/RouteServiceProvider.php index e800a84..7fd0a52 100644 --- a/app/Providers/RouteServiceProvider.php +++ b/app/Providers/RouteServiceProvider.php @@ -2,26 +2,22 @@ namespace App\Providers; +use Illuminate\Cache\RateLimiting\Limit; use Illuminate\Foundation\Support\Providers\RouteServiceProvider as ServiceProvider; +use Illuminate\Http\Request; +use Illuminate\Support\Facades\RateLimiter; use Illuminate\Support\Facades\Route; class RouteServiceProvider extends ServiceProvider { - /** - * This namespace is applied to your controller routes. - * - * In addition, it is set as the URL generator's root namespace. - * - * @var string - */ - protected $namespace = 'App\Http\Controllers'; - /** * The path to the "home" route for your application. * + * This is used by Laravel authentication to redirect users after login. + * * @var string */ - public const HOME = '/'; + public const HOME = '/home'; /** * Define your route model bindings, pattern filters, etc. @@ -30,48 +26,31 @@ class RouteServiceProvider extends ServiceProvider */ public function boot() { + $this->configureRateLimiting(); - parent::boot(); + $this->routes(function () { + Route::middleware('web') + ->namespace($this->namespace) + ->group(base_path('routes/web-bo.php')); + + Route::middleware('web') + ->namespace($this->namespace) + ->group(base_path('routes/web-fo.php')); + }); } /** - * Define the routes for the application. + * Configure the rate limiters for the application. * * @return void */ - public function map() + protected function configureRateLimiting() { - $this->mapApiRoutes(); - - $this->mapWebRoutes(); - } - - /** - * Define the "web" routes for the application. - * - * These routes all receive session state, CSRF protection, etc. - * - * @return void - */ - protected function mapWebRoutes() - { - Route::middleware('web') - ->namespace($this->namespace) - ->group(base_path('routes/web.php')); - } - - /** - * Define the "api" routes for the application. - * - * These routes are typically stateless. - * - * @return void - */ - protected function mapApiRoutes() - { - Route::prefix('api') - ->middleware('api') - ->namespace($this->namespace) - ->group(base_path('routes/api.php')); + RateLimiter::for('web', function (Request $request) { + return Limit::perMinute(150)->by(optional($request->user())->id ?: app('clientIp')); + }); + RateLimiter::for('api', function (Request $request) { + return Limit::perMinute(150)->by(optional($request->user())->id ?: app('clientIp')); + }); } } diff --git a/composer.json b/composer.json index e9b29f2..6574224 100644 --- a/composer.json +++ b/composer.json @@ -11,6 +11,7 @@ "php": "^7.3", "aacotroneo/laravel-saml2": "^2.1", "fideloper/proxy": "^4.0", + "fruitcake/laravel-cors": "^2.2", "guzzlehttp/guzzle": "^7.0.1", "kwaadpepper/enum": "^2.1", "kwaadpepper/exception-handler": "^0.0.8", @@ -18,6 +19,7 @@ "laravel/tinker": "^2.5", "laravel/ui": "^3.0", "lfkeitel/phptotp": " 1.0", + "mews/purifier": "^3.3", "propaganistas/laravel-phone": "^4.3", "simplesoftwareio/simple-qrcode": "^4.2", "slevomat/coding-standard": "^7.0" diff --git a/composer.lock b/composer.lock index 01d45b6..36755c7 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,7 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "147d92394452eddc47ce6d82469fa882", + "content-hash": "c16e5bed328844ecd2cdb0b1b31c8435", "packages": [ { "name": "aacotroneo/laravel-saml2", @@ -71,6 +71,62 @@ }, "time": "2019-10-01T23:05:14+00:00" }, + { + "name": "asm89/stack-cors", + "version": "v2.1.1", + "source": { + "type": "git", + "url": "https://github.com/asm89/stack-cors.git", + "reference": "73e5b88775c64ccc0b84fb60836b30dc9d92ac4a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/asm89/stack-cors/zipball/73e5b88775c64ccc0b84fb60836b30dc9d92ac4a", + "reference": "73e5b88775c64ccc0b84fb60836b30dc9d92ac4a", + "shasum": "" + }, + "require": { + "php": "^7.2|^8.0", + "symfony/http-foundation": "^4|^5|^6", + "symfony/http-kernel": "^4|^5|^6" + }, + "require-dev": { + "phpunit/phpunit": "^7|^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + } + }, + "autoload": { + "psr-4": { + "Asm89\\Stack\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Alexander", + "email": "iam.asm89@gmail.com" + } + ], + "description": "Cross-origin resource sharing library and stack middleware", + "homepage": "https://github.com/asm89/stack-cors", + "keywords": [ + "cors", + "stack" + ], + "support": { + "issues": "https://github.com/asm89/stack-cors/issues", + "source": "https://github.com/asm89/stack-cors/tree/v2.1.1" + }, + "time": "2022-01-18T09:12:03+00:00" + }, { "name": "bacon/bacon-qr-code", "version": "2.0.7", @@ -603,6 +659,60 @@ ], "time": "2020-12-29T14:50:06+00:00" }, + { + "name": "ezyang/htmlpurifier", + "version": "v4.13.0", + "source": { + "type": "git", + "url": "https://github.com/ezyang/htmlpurifier.git", + "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/08e27c97e4c6ed02f37c5b2b20488046c8d90d75", + "reference": "08e27c97e4c6ed02f37c5b2b20488046c8d90d75", + "shasum": "" + }, + "require": { + "php": ">=5.2" + }, + "require-dev": { + "simpletest/simpletest": "dev-master#72de02a7b80c6bb8864ef9bf66d41d2f58f826bd" + }, + "type": "library", + "autoload": { + "files": [ + "library/HTMLPurifier.composer.php" + ], + "psr-0": { + "HTMLPurifier": "library/" + }, + "exclude-from-classmap": [ + "/library/HTMLPurifier/Language/" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "LGPL-2.1-or-later" + ], + "authors": [ + { + "name": "Edward Z. Yang", + "email": "admin@htmlpurifier.org", + "homepage": "http://ezyang.com" + } + ], + "description": "Standards compliant HTML filter written in PHP", + "homepage": "http://htmlpurifier.org/", + "keywords": [ + "html" + ], + "support": { + "issues": "https://github.com/ezyang/htmlpurifier/issues", + "source": "https://github.com/ezyang/htmlpurifier/tree/master" + }, + "time": "2020-06-29T00:56:53+00:00" + }, { "name": "fideloper/proxy", "version": "4.4.1", @@ -661,6 +771,85 @@ }, "time": "2020-10-22T13:48:01+00:00" }, + { + "name": "fruitcake/laravel-cors", + "version": "v2.2.0", + "source": { + "type": "git", + "url": "https://github.com/fruitcake/laravel-cors.git", + "reference": "783a74f5e3431d7b9805be8afb60fd0a8f743534" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/fruitcake/laravel-cors/zipball/783a74f5e3431d7b9805be8afb60fd0a8f743534", + "reference": "783a74f5e3431d7b9805be8afb60fd0a8f743534", + "shasum": "" + }, + "require": { + "asm89/stack-cors": "^2.0.1", + "illuminate/contracts": "^6|^7|^8|^9", + "illuminate/support": "^6|^7|^8|^9", + "php": ">=7.2" + }, + "require-dev": { + "laravel/framework": "^6|^7.24|^8", + "orchestra/testbench-dusk": "^4|^5|^6|^7", + "phpunit/phpunit": "^6|^7|^8|^9", + "squizlabs/php_codesniffer": "^3.5" + }, + "type": "library", + "extra": { + "branch-alias": { + "dev-master": "2.1-dev" + }, + "laravel": { + "providers": [ + "Fruitcake\\Cors\\CorsServiceProvider" + ] + } + }, + "autoload": { + "psr-4": { + "Fruitcake\\Cors\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Fruitcake", + "homepage": "https://fruitcake.nl" + }, + { + "name": "Barry vd. Heuvel", + "email": "barryvdh@gmail.com" + } + ], + "description": "Adds CORS (Cross-Origin Resource Sharing) headers support in your Laravel application", + "keywords": [ + "api", + "cors", + "crossdomain", + "laravel" + ], + "support": { + "issues": "https://github.com/fruitcake/laravel-cors/issues", + "source": "https://github.com/fruitcake/laravel-cors/tree/v2.2.0" + }, + "funding": [ + { + "url": "https://fruitcake.nl", + "type": "custom" + }, + { + "url": "https://github.com/barryvdh", + "type": "github" + } + ], + "time": "2022-02-23T14:25:13+00:00" + }, { "name": "giggsey/libphonenumber-for-php", "version": "8.12.50", @@ -1995,6 +2184,87 @@ }, "time": "2017-02-06T17:46:14+00:00" }, + { + "name": "mews/purifier", + "version": "3.3.7", + "source": { + "type": "git", + "url": "https://github.com/mewebstudio/Purifier.git", + "reference": "9844bc82886e4291b3116afbd9ab5f532856662a" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/mewebstudio/Purifier/zipball/9844bc82886e4291b3116afbd9ab5f532856662a", + "reference": "9844bc82886e4291b3116afbd9ab5f532856662a", + "shasum": "" + }, + "require": { + "ezyang/htmlpurifier": "4.13.*", + "illuminate/config": "^5.8|^6.0|^7.0|^8.0|^9.0", + "illuminate/filesystem": "^5.8|^6.0|^7.0|^8.0|^9.0", + "illuminate/support": "^5.8|^6.0|^7.0|^8.0|^9.0", + "php": "^7.2|^8.0" + }, + "require-dev": { + "graham-campbell/testbench": "^3.2|^5.5.1", + "mockery/mockery": "^1.3.3", + "phpunit/phpunit": "^8.0|^9.0" + }, + "suggest": { + "laravel/framework": "To test the Laravel bindings", + "laravel/lumen-framework": "To test the Lumen bindings" + }, + "type": "package", + "extra": { + "laravel": { + "providers": [ + "Mews\\Purifier\\PurifierServiceProvider" + ], + "aliases": { + "Purifier": "Mews\\Purifier\\Facades\\Purifier" + } + } + }, + "autoload": { + "files": [ + "src/helpers.php" + ], + "psr-4": { + "Mews\\Purifier\\": "src/" + } + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "MIT" + ], + "authors": [ + { + "name": "Muharrem ERİN", + "email": "me@mewebstudio.com", + "homepage": "https://github.com/mewebstudio", + "role": "Developer" + } + ], + "description": "Laravel 5/6/7 HtmlPurifier Package", + "homepage": "https://github.com/mewebstudio/purifier", + "keywords": [ + "Purifier", + "htmlpurifier", + "laravel5 HtmlPurifier", + "laravel5 Purifier", + "laravel5 Security", + "laravel6 HtmlPurifier", + "laravel6 Purifier", + "laravel6 Security", + "security", + "xss" + ], + "support": { + "issues": "https://github.com/mewebstudio/Purifier/issues", + "source": "https://github.com/mewebstudio/Purifier/tree/3.3.7" + }, + "time": "2022-02-12T15:54:11+00:00" + }, { "name": "monolog/monolog", "version": "2.7.0", diff --git a/config/app.php b/config/app.php index d695fbe..ab5db16 100644 --- a/config/app.php +++ b/config/app.php @@ -139,6 +139,7 @@ return [ /* * Laravel Framework Service Providers... */ + Illuminate\Auth\AuthServiceProvider::class, Illuminate\Broadcasting\BroadcastServiceProvider::class, Illuminate\Bus\BusServiceProvider::class, @@ -169,9 +170,9 @@ return [ /* * Application Service Providers... */ + App\Providers\AppServiceProvider::class, App\Providers\AuthServiceProvider::class, - // App\Providers\BroadcastServiceProvider::class, App\Providers\EventServiceProvider::class, App\Providers\RouteServiceProvider::class, App\Providers\TranslationServiceProvider::class, diff --git a/config/auth.php b/config/auth.php index 2051dfd..ac749ac 100644 --- a/config/auth.php +++ b/config/auth.php @@ -68,7 +68,7 @@ return [ 'providers' => [ 'users' => [ 'driver' => 'eloquent', - 'model' => App\User::class, + 'model' => App\Models\User::class, ], // 'users' => [ diff --git a/config/cache.php b/config/cache.php index f765d26..43d1de1 100644 --- a/config/cache.php +++ b/config/cache.php @@ -59,9 +59,7 @@ return [ env('MEMCACHED_USERNAME'), env('MEMCACHED_PASSWORD'), ], - 'options' => [ - // Memcached::OPT_CONNECT_TIMEOUT => 2000, - ], + 'options' => [], 'servers' => [ [ 'host' => env('MEMCACHED_HOST', '127.0.0.1'), diff --git a/config/saml2/ldc_idp_settings.php b/config/saml2/ldc_idp_settings.php index 57f00ea..c7bbbdd 100644 --- a/config/saml2/ldc_idp_settings.php +++ b/config/saml2/ldc_idp_settings.php @@ -1,14 +1,14 @@ true, -// @todo: make this depend on laravel config - // Enable debug mode (to print errors) + // TODO: make this depend on laravel config + // Enable debug mode (to print errors). 'debug' => env('APP_DEBUG', false), - // Service Provider Data that we are deploying + // Service Provider Data that we are deploying. 'sp' => array( // Specifies constraints on the name identifier to be used to // represent the requested subject. - // Take a look on lib/Saml2/Constants.php to see the NameIdFormat supported + // Take a look on lib/Saml2/Constants.php to see the NameIdFormat supported. 'NameIDFormat' => 'urn:oasis:names:tc:SAML:1.1:nameid-format:emailAddress', // Usually x509cert and privateKey of the SP are provided by files placed at - // the certs folder. But we can also provide them with the following parameters + // the certs folder. But we can also provide them with the following parameters. 'x509cert' => env('SAML2_' . $this_idp_env_id . '_SP_x509', ''), 'privateKey' => env('SAML2_' . $this_idp_env_id . '_SP_PRIVATEKEY', ''), @@ -45,7 +45,7 @@ return $settings = array( 'assertionConsumerService' => array( // URL Location where the from the IdP will be returned, // using HTTP-POST binding. - // Leave blank to use the '{idpName}_acs' route, e.g. 'test_acs' + // Leave blank to use the '{idpName}_acs' route, e.g. 'test_acs'. 'url' => '', ), // Specifies info about where and how the message MUST be @@ -54,16 +54,16 @@ return $settings = array( 'singleLogoutService' => array( // URL Location where the from the IdP will be returned, // using HTTP-Redirect binding. - // Leave blank to use the '{idpName}_sls' route, e.g. 'test_sls' + // Leave blank to use the '{idpName}_sls' route, e.g. 'test_sls'. 'url' => '', ), ), - // Identity Provider Data that we want connect with our SP + // Identity Provider Data that we want connect with our SP. 'idp' => array( - // Identifier of the IdP entity (must be a URI) + // Identifier of the IdP entity (must be a URI). 'entityId' => env('SAML2_' . $this_idp_env_id . '_IDP_ENTITYID', $idp_host . '/saml2/idp/metadata.php'), - // SSO endpoint info of the IdP. (Authentication Request protocol) + // SSO endpoint info of the IdP. (Authentication Request protocol). 'singleSignOnService' => array( // URL Target of the IdP where the SP will send the Authentication Request Message, // using HTTP-Redirect binding. @@ -75,12 +75,15 @@ return $settings = array( // using HTTP-Redirect binding. 'url' => env('SAML2_' . $this_idp_env_id . '_IDP_SL_URL', $idp_host . '/saml2/idp/SingleLogoutService.php'), ), - // Public x509 certificate of the IdP + // Public x509 certificate of the IdP. + // phpcs:ignore Generic.Files.LineLength.TooLong 'x509cert' => env('SAML2_' . $this_idp_env_id . '_IDP_x509', 'MIID/TCCAuWgAwIBAgIJAI4R3WyjjmB1MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYDVQQGEwJBUjEVMBMGA1UECAwMQnVlbm9zIEFpcmVzMRUwEwYDVQQHDAxCdWVub3MgQWlyZXMxDDAKBgNVBAoMA1NJVTERMA8GA1UECwwIU2lzdGVtYXMxFDASBgNVBAMMC09yZy5TaXUuQ29tMSAwHgYJKoZIhvcNAQkBFhFhZG1pbmlAc2l1LmVkdS5hcjAeFw0xNDEyMDExNDM2MjVaFw0yNDExMzAxNDM2MjVaMIGUMQswCQYDVQQGEwJBUjEVMBMGA1UECAwMQnVlbm9zIEFpcmVzMRUwEwYDVQQHDAxCdWVub3MgQWlyZXMxDDAKBgNVBAoMA1NJVTERMA8GA1UECwwIU2lzdGVtYXMxFDASBgNVBAMMC09yZy5TaXUuQ29tMSAwHgYJKoZIhvcNAQkBFhFhZG1pbmlAc2l1LmVkdS5hcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbzW/EpEv+qqZzfT1Buwjg9nnNNVrxkCfuR9fQiQw2tSouS5X37W5h7RmchRt54wsm046PDKtbSz1NpZT2GkmHN37yALW2lY7MyVUC7itv9vDAUsFr0EfKIdCKgxCKjrzkZ5ImbNvjxf7eA77PPGJnQ/UwXY7W+cvLkirp0K5uWpDk+nac5W0JXOCFR1BpPUJRbz2jFIEHyChRt7nsJZH6ejzNqK9lABEC76htNy1Ll/D3tUoPaqo8VlKW3N3MZE0DB9O7g65DmZIIlFqkaMH3ALd8adodJtOvqfDU/A6SxuwMfwDYPjoucykGDu1etRZ7dF2gd+W+1Pn7yizPT1q8CAwEAAaNQME4wHQYDVR0OBBYEFPsn8tUHN8XXf23ig5Qro3beP8BuMB8GA1UdIwQYMBaAFPsn8tUHN8XXf23ig5Qro3beP8BuMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAGu60odWFiK+DkQekozGnlpNBQz5lQ/bwmOWdktnQj6HYXu43e7sh9oZWArLYHEOyMUekKQAxOK51vbTHzzw66BZU91/nqvaOBfkJyZKGfluHbD0/hfOl/D5kONqI9kyTu4wkLQcYGyuIi75CJs15uA03FSuULQdY/Liv+czS/XYDyvtSLnu43VuAQWN321PQNhuGueIaLJANb2C5qq5ilTBUw6PxY9Z+vtMjAjTJGKEkE/tQs7CvzLPKXX3KTD9lIILmX5yUC3dLgjVKi1KGDqNApYGOMtjr5eoxPQrqDBmyx3flcy0dQTdLXud3UjWVW3N0PYgJtw5yBsS74QTGD4='), + /* * Instead of use the whole x509cert you can use a fingerprint * (openssl x509 -noout -fingerprint -in "idp.crt" to generate it) */ + // 'certFingerprint' => '', ), @@ -92,7 +95,7 @@ return $settings = array( * * */ - // Security settings + // Security settings. 'security' => array( 'signatureAlgorithm' => 'http://www.w3.org/2000/09/xmldsig#rsa-sha1', @@ -105,7 +108,7 @@ return $settings = array( 'nameIdEncrypted' => false, // Indicates whether the messages sent by this SP - // will be signed. [The Metadata of the SP will offer this info] + // will be signed. [The Metadata of the SP will offer this info]. 'authnRequestsSigned' => true, // Indicates whether the messages sent by this SP @@ -116,12 +119,12 @@ return $settings = array( // will be signed. 'logoutResponseSigned' => true, - /* - Sign the Metadata - False || True (use sp certs) || array ( - keyFileName => 'metadata.key', - certFileName => 'metadata.crt' - ) + /** + * Sign the Metadata + * False || True (use sp certs) || array ( + * keyFileName => 'metadata.key', + * certFileName => 'metadata.crt' + * ) */ 'signMetadata' => true, @@ -133,21 +136,25 @@ return $settings = array( 'wantMessagesSigned' => true, // Indicates a requirement for the elements received by - // this SP to be signed. [The Metadata of the SP will offer this info] + // this SP to be signed. [The Metadata of the SP will offer this info]. 'wantAssertionsSigned' => true, // Indicates a requirement for the NameID received by // this SP to be encrypted. 'wantNameIdEncrypted' => false, - // Authentication context. - // Set to false and no AuthContext will be sent in the AuthNRequest, - // Set true or don't present thi parameter and you will get an AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' - // Set an array with the possible auth context values: array ('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509'), + /** + * Authentication context. + * Set to false and no AuthContext will be sent in the AuthNRequest, + * Set true or don't present thi parameter and you will get an + * AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + * Set an array with the possible auth context values: array + * ('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509'), + */ 'requestedAuthnContext' => false, ), - // Contact information template, it is recommended to suply a technical and support contacts + // Contact information template, it is recommended to suply a technical and support contacts. 'contactPerson' => array( 'technical' => array( 'givenName' => 'Vincent BRIDIER', @@ -159,7 +166,7 @@ return $settings = array( ), ), - // Organization information template, the info in en_US lang is recomended, add more if required + // Organization information template, the info in en_US lang is recomended, add more if required. 'organization' => array( 'fr-FR' => array( 'name' => 'LDC', @@ -179,3 +186,5 @@ return $settings = array( */ ); + +return $settings; diff --git a/config/saml2/ldc_idp_settings_local.php b/config/saml2/ldc_idp_settings_local.php index 3c12555..3a99644 100644 --- a/config/saml2/ldc_idp_settings_local.php +++ b/config/saml2/ldc_idp_settings_local.php @@ -1,14 +1,14 @@ true, -// @todo: make this depend on laravel config - // Enable debug mode (to print errors) + // TODO: make this depend on laravel config. + // Enable debug mode (to print errors) . 'debug' => env('APP_DEBUG', false), - // Service Provider Data that we are deploying + // Service Provider Data that we are deploying. 'sp' => array( // Specifies constraints on the name identifier to be used to // represent the requested subject. - // Take a look on lib/Saml2/Constants.php to see the NameIdFormat supported + // Take a look on lib/Saml2/Constants.php to see the NameIdFormat supported. 'NameIDFormat' => 'urn:oasis:names:tc:SAML:2.0:nameid-format:persistent', // Usually x509cert and privateKey of the SP are provided by files placed at - // the certs folder. But we can also provide them with the following parameters + // the certs folder. But we can also provide them with the following parameters. 'x509cert' => env('SAML2_' . $this_idp_env_id . '_SP_x509', ''), 'privateKey' => env('SAML2_' . $this_idp_env_id . '_SP_PRIVATEKEY', ''), @@ -45,7 +45,7 @@ return $settings = array( 'assertionConsumerService' => array( // URL Location where the from the IdP will be returned, // using HTTP-POST binding. - // Leave blank to use the '{idpName}_acs' route, e.g. 'test_acs' + // Leave blank to use the '{idpName}_acs' route, e.g. 'test_acs'. 'url' => '', ), // Specifies info about where and how the message MUST be @@ -54,16 +54,16 @@ return $settings = array( 'singleLogoutService' => array( // URL Location where the from the IdP will be returned, // using HTTP-Redirect binding. - // Leave blank to use the '{idpName}_sls' route, e.g. 'test_sls' + // Leave blank to use the '{idpName}_sls' route, e.g. 'test_sls'. 'url' => '', ), ), - // Identity Provider Data that we want connect with our SP + // Identity Provider Data that we want connect with our SP. 'idp' => array( - // Identifier of the IdP entity (must be a URI) + // Identifier of the IdP entity (must be a URI). 'entityId' => env('SAML2_' . $this_idp_env_id . '_IDP_ENTITYID', $idp_host . '/saml2/idp/metadata.php'), - // SSO endpoint info of the IdP. (Authentication Request protocol) + // SSO endpoint info of the IdP. (Authentication Request protocol). 'singleSignOnService' => array( // URL Target of the IdP where the SP will send the Authentication Request Message, // using HTTP-Redirect binding. @@ -75,12 +75,15 @@ return $settings = array( // using HTTP-Redirect binding. 'url' => env('SAML2_' . $this_idp_env_id . '_IDP_SL_URL', $idp_host . '/saml2/idp/SingleLogoutService.php'), ), - // Public x509 certificate of the IdP + // Public x509 certificate of the IdP. + //phpcs:ignore Generic.Files.LineLength.TooLong 'x509cert' => env('SAML2_' . $this_idp_env_id . '_IDP_x509', 'MIID/TCCAuWgAwIBAgIJAI4R3WyjjmB1MA0GCSqGSIb3DQEBCwUAMIGUMQswCQYDVQQGEwJBUjEVMBMGA1UECAwMQnVlbm9zIEFpcmVzMRUwEwYDVQQHDAxCdWVub3MgQWlyZXMxDDAKBgNVBAoMA1NJVTERMA8GA1UECwwIU2lzdGVtYXMxFDASBgNVBAMMC09yZy5TaXUuQ29tMSAwHgYJKoZIhvcNAQkBFhFhZG1pbmlAc2l1LmVkdS5hcjAeFw0xNDEyMDExNDM2MjVaFw0yNDExMzAxNDM2MjVaMIGUMQswCQYDVQQGEwJBUjEVMBMGA1UECAwMQnVlbm9zIEFpcmVzMRUwEwYDVQQHDAxCdWVub3MgQWlyZXMxDDAKBgNVBAoMA1NJVTERMA8GA1UECwwIU2lzdGVtYXMxFDASBgNVBAMMC09yZy5TaXUuQ29tMSAwHgYJKoZIhvcNAQkBFhFhZG1pbmlAc2l1LmVkdS5hcjCCASIwDQYJKoZIhvcNAQEBBQADggEPADCCAQoCggEBAMbzW/EpEv+qqZzfT1Buwjg9nnNNVrxkCfuR9fQiQw2tSouS5X37W5h7RmchRt54wsm046PDKtbSz1NpZT2GkmHN37yALW2lY7MyVUC7itv9vDAUsFr0EfKIdCKgxCKjrzkZ5ImbNvjxf7eA77PPGJnQ/UwXY7W+cvLkirp0K5uWpDk+nac5W0JXOCFR1BpPUJRbz2jFIEHyChRt7nsJZH6ejzNqK9lABEC76htNy1Ll/D3tUoPaqo8VlKW3N3MZE0DB9O7g65DmZIIlFqkaMH3ALd8adodJtOvqfDU/A6SxuwMfwDYPjoucykGDu1etRZ7dF2gd+W+1Pn7yizPT1q8CAwEAAaNQME4wHQYDVR0OBBYEFPsn8tUHN8XXf23ig5Qro3beP8BuMB8GA1UdIwQYMBaAFPsn8tUHN8XXf23ig5Qro3beP8BuMAwGA1UdEwQFMAMBAf8wDQYJKoZIhvcNAQELBQADggEBAGu60odWFiK+DkQekozGnlpNBQz5lQ/bwmOWdktnQj6HYXu43e7sh9oZWArLYHEOyMUekKQAxOK51vbTHzzw66BZU91/nqvaOBfkJyZKGfluHbD0/hfOl/D5kONqI9kyTu4wkLQcYGyuIi75CJs15uA03FSuULQdY/Liv+czS/XYDyvtSLnu43VuAQWN321PQNhuGueIaLJANb2C5qq5ilTBUw6PxY9Z+vtMjAjTJGKEkE/tQs7CvzLPKXX3KTD9lIILmX5yUC3dLgjVKi1KGDqNApYGOMtjr5eoxPQrqDBmyx3flcy0dQTdLXud3UjWVW3N0PYgJtw5yBsS74QTGD4='), + /* * Instead of use the whole x509cert you can use a fingerprint * (openssl x509 -noout -fingerprint -in "idp.crt" to generate it) */ + // 'certFingerprint' => '', ), @@ -92,7 +95,7 @@ return $settings = array( * * */ - // Security settings + // Security settings. 'security' => array( /** signatures and encryptions offered */ @@ -101,8 +104,10 @@ return $settings = array( // will be encrypted. 'nameIdEncrypted' => false, - // Indicates whether the messages sent by this SP - // will be signed. [The Metadata of the SP will offer this info] + /** + * Indicates whether the messages sent by this SP + * will be signed. [The Metadata of the SP will offer this info] + */ 'authnRequestsSigned' => false, // Indicates whether the messages sent by this SP @@ -113,12 +118,12 @@ return $settings = array( // will be signed. 'logoutResponseSigned' => false, - /* - Sign the Metadata - False || True (use sp certs) || array ( - keyFileName => 'metadata.key', - certFileName => 'metadata.crt' - ) + /** + * Sign the Metadata + * False || True (use sp certs) || array ( + * keyFileName => 'metadata.key', + * certFileName => 'metadata.crt' + * ) */ 'signMetadata' => false, @@ -129,22 +134,30 @@ return $settings = array( // elements received by this SP to be signed. 'wantMessagesSigned' => false, - // Indicates a requirement for the elements received by - // this SP to be signed. [The Metadata of the SP will offer this info] + /** + * Indicates a requirement for the elements received by + * this SP to be signed. + * [The Metadata of the SP will offer this info] + * */ 'wantAssertionsSigned' => false, // Indicates a requirement for the NameID received by // this SP to be encrypted. 'wantNameIdEncrypted' => false, - // Authentication context. - // Set to false and no AuthContext will be sent in the AuthNRequest, - // Set true or don't present thi parameter and you will get an AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' - // Set an array with the possible auth context values: array ('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509'), + /** + * Authentication context. + * Set to false and no AuthContext will be sent in the AuthNRequest, + * Set true or don't present thi parameter and you will get an + * AuthContext 'exact' 'urn:oasis:names:tc:SAML:2.0:ac:classes:PasswordProtectedTransport' + * Set an array with the possible auth context values: array + * ('urn:oasis:names:tc:SAML:2.0:ac:classes:Password', 'urn:oasis:names:tc:SAML:2.0:ac:classes:X509'), + */ + 'requestedAuthnContext' => true, ), - // Contact information template, it is recommended to suply a technical and support contacts + // Contact information template, it is recommended to suply a technical and support contacts. 'contactPerson' => array( 'technical' => array( 'givenName' => 'name', @@ -156,7 +169,7 @@ return $settings = array( ), ), - // Organization information template, the info in en_US lang is recomended, add more if required + // Organization information template, the info in en_US lang is recomended, add more if required. 'organization' => array( 'en-US' => array( 'name' => 'Name', @@ -176,3 +189,5 @@ return $settings = array( */ ); + +return $settings; diff --git a/config/saml2_settings.php b/config/saml2_settings.php index c7077b4..b23d782 100644 --- a/config/saml2_settings.php +++ b/config/saml2_settings.php @@ -1,6 +1,6 @@ ['test1', 'test2', 'test3'], @@ -58,7 +58,7 @@ return $settings = array( // e.g X-Forwarded-Proto / HTTP_X_FORWARDED_PROTO. This is useful if // your application is running behind a load balancer which terminates // SSL. - // LDC WEB SET FALSE IF LOCAL + // LDC WEB SET FALSE IF LOCAL. 'proxyVars' => true, /** @@ -70,3 +70,5 @@ return $settings = array( */ // 'saml2_controller' => '', ); + +return $settings; diff --git a/database/seeders/DatabaseSeeder.php b/database/seeders/DatabaseSeeder.php index f870c20..cac798a 100644 --- a/database/seeders/DatabaseSeeder.php +++ b/database/seeders/DatabaseSeeder.php @@ -13,6 +13,5 @@ class DatabaseSeeder extends Seeder */ public function run() { - // $this->call(UsersTableSeeder::class); } } diff --git a/resources/views/emails/webhooks/gitlab.blade.php b/resources/views/emails/webhooks/gitlab.blade.php index 81e6c33..c9a38a1 100644 --- a/resources/views/emails/webhooks/gitlab.blade.php +++ b/resources/views/emails/webhooks/gitlab.blade.php @@ -1,12 +1,12 @@ -Nouvelle merge request de la part de : {{ $datas['user'] }} +Nouvelle merge request de la part de : {{ $data['user'] }} -Projet : {{ $datas['project_name'] }} -Dépôt : {{ $datas['project_path'] }} -URL : {{ $datas['attributes_url'] }} +Projet : {{ $data['project_name'] }} +Dépôt : {{ $data['project_path'] }} +URL : {{ $data['attributes_url'] }} -Description : {{ $datas['attributes_description'] }} -Branches : {{ $datas['attributes_source_branch'] }} vers {{ $datas['attributes_target_branch'] }} -Statut du merge : {{ $datas['attributes_status'] }} -Statut de la merge request : {{ $datas['attributes_request_status'] }} +Description : {{ $data['attributes_description'] }} +Branches : {{ $data['attributes_source_branch'] }} vers {{ $data['attributes_target_branch'] }} +Statut du merge : {{ $data['attributes_status'] }} +Statut de la merge request : {{ $data['attributes_request_status'] }} -Auteur du dernier commit : {{ $datas['last_commit_author'] }} +Auteur du dernier commit : {{ $data['last_commit_author'] }} diff --git a/routes/api.php b/routes/api.php index 5c5c81f..23312d7 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1,15 +1,7 @@ id === (int)$id; -}); diff --git a/routes/console.php b/routes/console.php index 23c267d..b3d9bbc 100644 --- a/routes/console.php +++ b/routes/console.php @@ -1,18 +1 @@ comment(Inspiring::quote()); -})->describe('Display an inspiring quote'); diff --git a/routes/web-bo.php b/routes/web-bo.php new file mode 100644 index 0000000..55a1a3c --- /dev/null +++ b/routes/web-bo.php @@ -0,0 +1,81 @@ + ['auth']], function () { + Route::get('/', [HomeController::class, 'index'])->name('home'); + Route::get('/otp-qr-code', [HomeController::class, 'qr'])->name('otp-qr-code'); + + // * STATUS CHECKER + Route::get('/status-checker', [StatusCheckerController::class, 'index']); + + // * EDL WEB + Route::get('/projects', [ProjectsController::class, 'index'])->name('projects.index'); + Route::get('/projects/{uuid}/edit', [ProjectsController::class, 'edit'])->name('projects.edit'); + Route::post('/projects/{uuid}/update', [ProjectsController::class, 'update']); + Route::get('/projects/{uuid}/delete', [ProjectsController::class, 'delete']); + Route::post('/projects/{uuid}/force-delete', [ProjectsController::class, 'forceDelete']); + Route::get('/projects/add', [ProjectsController::class, 'add']); + Route::post('/projects/store', [ProjectsController::class, 'store']); + + // * SERVERS + Route::get('/servers', [ServersController::class, 'index'])->name('servers.index'); + Route::post('/servers/store', [ServersController::class, 'store'])->name('servers.store'); + Route::get('/servers/add', [ServersController::class, 'add'])->name('servers.add'); + Route::get('/servers/{id}', [ServersController::class, 'edit'])->name('servers.edit'); + Route::post('/servers/{id}/update', [ServersController::class, 'update'])->name('servers.update'); + Route::get('/servers/{id}/delete', [ServersController::class, 'delete'])->name('servers.delete'); + Route::post('/servers/{id}/force-delete', [ServersController::class, 'forceDelete'])->name('servers.force-delete'); + + // * DATASTORE PCC + Route::get('/dpccs', [DatastorePCCController::class, 'index'])->name('dpccs.index'); + Route::post('/dpccs/store', [DatastorePCCController::class, 'store'])->name('dpccs.store'); + Route::get('/dpccs/add', [DatastorePCCController::class, 'add'])->name('dpccs.add'); + Route::get('/dpccs/{id}', [DatastorePCCController::class, 'edit'])->name('dpccs.edit'); + Route::post('/dpccs/{id}/update', [DatastorePCCController::class, 'update'])->name('dpccs.update'); + Route::get('/dpccs/{id}/delete', [DatastorePCCController::class, 'delete'])->name('dpccs.delete'); + Route::post('/dpccs/{id}/force-delete', [DatastorePCCController::class, 'forceDelete'])->name('dpccs.force-delete'); + + // * DOMAIN NAMES + Route::get('/domain-names', [DomainNameController::class, 'index'])->name('domain-names.index'); + Route::post('/domain-names/store', [DomainNamesController::class, 'store'])->name('domain-names.store'); + Route::get('/domain-names/add', [DomainNameController::class, 'add'])->name('domain-names.add'); + Route::get('/domain-names/{id}', [DomainNameController::class, 'edit'])->name('domain-names.edit'); + Route::post('/domain-names/{id}/update', [DomainNameController::class, 'update'])->name('domain-names.update'); + Route::get('/domain-names/{id}/delete', [DomainNameController::class, 'delete'])->name('domain-names.delete'); + Route::post('/domain-names/{id}/force-delete', [DomainNameController::class, 'forceDelete']) + ->name('domain-names.force-delete'); + + // * EMAIL ADDRESSES + Route::get('/email-addresses', [EmailAddressesController::class, 'index'])->name('email-addresses.index'); + Route::post('/email-addresses/store', [EmailAddressesController::class, 'store'])->name('email-addresses.store'); + Route::get('/email-addresses/add', [EmailAddressesController::class, 'add'])->name('email-addresses.add'); + Route::get('/email-addresses/{id}', [EmailAddressesController::class, 'edit'])->name('email-addresses.edit'); + Route::post('/email-addresses/{id}/update', [EmailAddressesController::class, 'update']) + ->name('email-addresses.update'); + Route::get('/email-addresses/{id}/delete', [EmailAddressesController::class, 'delete']) + ->name('email-addresses.delete'); + Route::post('/email-addresses/{id}/force-delete', [EmailAddressesController::class, 'forceDelete']) + ->name('email-addresses.force-delete'); + + // * IP LDC NETWORK + Route::get('/ldc-networks', [LDCNetworkController::class, 'index'])->name('ldc-networks.index'); + Route::post('/ldc-networks/store', [LDCNetworkController::class, 'store'])->name('ldc-networks.store'); + Route::get('/ldc-networks/add', [LDCNetworkController::class, 'add'])->name('ldc-networks.add'); + Route::get('/ldc-networks/{id}', [LDCNetworkController::class, 'edit'])->name('ldc-networks.edit'); + Route::post('/ldc-networks/{id}/update', [LDCNetworkController::class, 'update'])->name('ldc-networks.update'); + Route::get('/ldc-networks/{id}/delete', [LDCNetworkController::class, 'delete'])->name('ldc-networks.delete'); + Route::post('/ldc-networks/{id}/force-delete', [LDCNetworkController::class, 'forceDelete']) + ->name('ldc-networks.force-delete'); + + // * GIT REPOS + Route::resource('git-repos', 'GitReposController'); +}); diff --git a/routes/web-fo.php b/routes/web-fo.php new file mode 100644 index 0000000..4553f57 --- /dev/null +++ b/routes/web-fo.php @@ -0,0 +1,14 @@ +name('verification_failed'); +Route::view('/login/unauthorized', 'auth.unauthorized')->name('unauthorized'); + +Route::get('/login/verify', [OTPController::class, 'verify'])->name('auth.verify'); +Route::get('/login/send-sms-otp', [OTPController::class, 'sendOTPBySMS'])->name('auth.sms-otp'); +Route::post('/login/checkOTP', [OTPController::class, 'check'])->name('auth.otp'); diff --git a/routes/web.php b/routes/web.php deleted file mode 100644 index 82b4df7..0000000 --- a/routes/web.php +++ /dev/null @@ -1,77 +0,0 @@ -name('auth.verify'); -Route::get('/login/send-sms-otp', 'OTPController@sendOTPBySMS')->name('auth.sms-otp'); -Route::post('/login/checkOTP', 'OTPController@check')->name('auth.otp'); -Route::view('/login/verification_failed', 'auth.verification_failed')->name('verification_failed'); -Route::view('/login/unauthorized', 'auth.unauthorized')->name('unauthorized'); - -Route::group(['middleware' => ['auth']], function () { - Route::get('/', 'HomeController@index')->name('home'); - Route::get('/otp-qr-code', 'HomeController@qr')->name('otp-qr-code'); - // STATUS CHECKER - Route::get('/status-checker', 'StatusCheckerController@index'); - // EDL WEB - Route::get('/projects', 'ProjectsController@index')->name('projects.index'); - Route::get('/projects/{uuid}/edit', 'ProjectsController@edit')->name('projects.edit'); - Route::post('/projects/{uuid}/update', 'ProjectsController@update'); - Route::get('/projects/{uuid}/delete', 'ProjectsController@delete'); - Route::post('/projects/{uuid}/force-delete', 'ProjectsController@forceDelete'); - Route::get('/projects/add', 'ProjectsController@add'); - Route::post('/projects/store', 'ProjectsController@store'); - // SERVERS - Route::get('/servers', 'ServersController@index')->name('servers.index'); - Route::post('/servers/store', 'ServersController@store')->name('servers.store'); - Route::get('/servers/add', 'ServersController@add')->name('servers.add'); - Route::get('/servers/{id}', 'ServersController@edit')->name('servers.edit'); - Route::post('/servers/{id}/update', 'ServersController@update')->name('servers.update'); - Route::get('/servers/{id}/delete', 'ServersController@delete')->name('servers.delete'); - Route::post('/servers/{id}/force-delete', 'ServersController@forceDelete')->name('servers.force-delete'); - // DATASTORE PCC - Route::get('/dpccs', 'DatastorePCCController@index')->name('dpccs.index'); - Route::post('/dpccs/store', 'DatastorePCCController@store')->name('dpccs.store'); - Route::get('/dpccs/add', 'DatastorePCCController@add')->name('dpccs.add'); - Route::get('/dpccs/{id}', 'DatastorePCCController@edit')->name('dpccs.edit'); - Route::post('/dpccs/{id}/update', 'DatastorePCCController@update')->name('dpccs.update'); - Route::get('/dpccs/{id}/delete', 'DatastorePCCController@delete')->name('dpccs.delete'); - Route::post('/dpccs/{id}/force-delete', 'DatastorePCCController@forceDelete')->name('dpccs.force-delete'); - // DOMAIN NAMES - Route::get('/domain-names', 'DomainNamesController@index')->name('domain-names.index'); - Route::post('/domain-names/store', 'DomainNamesController@store')->name('domain-names.store'); - Route::get('/domain-names/add', 'DomainNamesController@add')->name('domain-names.add'); - Route::get('/domain-names/{id}', 'DomainNamesController@edit')->name('domain-names.edit'); - Route::post('/domain-names/{id}/update', 'DomainNamesController@update')->name('domain-names.update'); - Route::get('/domain-names/{id}/delete', 'DomainNamesController@delete')->name('domain-names.delete'); - Route::post('/domain-names/{id}/force-delete', 'DomainNamesController@forceDelete')->name('domain-names.force-delete'); - // EMAIL ADDRESSES - Route::get('/email-addresses', 'EmailAddressesController@index')->name('email-addresses.index'); - Route::post('/email-addresses/store', 'EmailAddressesController@store')->name('email-addresses.store'); - Route::get('/email-addresses/add', 'EmailAddressesController@add')->name('email-addresses.add'); - Route::get('/email-addresses/{id}', 'EmailAddressesController@edit')->name('email-addresses.edit'); - Route::post('/email-addresses/{id}/update', 'EmailAddressesController@update')->name('email-addresses.update'); - Route::get('/email-addresses/{id}/delete', 'EmailAddressesController@delete')->name('email-addresses.delete'); - Route::post('/email-addresses/{id}/force-delete', 'EmailAddressesController@forceDelete')->name('email-addresses.force-delete'); - // IP LDC NETWORK - Route::get('/ldc-networks', 'LDCNetworkController@index')->name('ldc-networks.index'); - Route::post('/ldc-networks/store', 'LDCNetworkController@store')->name('ldc-networks.store'); - Route::get('/ldc-networks/add', 'LDCNetworkController@add')->name('ldc-networks.add'); - Route::get('/ldc-networks/{id}', 'LDCNetworkController@edit')->name('ldc-networks.edit'); - Route::post('/ldc-networks/{id}/update', 'LDCNetworkController@update')->name('ldc-networks.update'); - Route::get('/ldc-networks/{id}/delete', 'LDCNetworkController@delete')->name('ldc-networks.delete'); - Route::post('/ldc-networks/{id}/force-delete', 'LDCNetworkController@forceDelete')->name('ldc-networks.force-delete'); - // GIT REPOS - Route::resource('git-repos', 'GitReposController'); -});