From fb5464b63618e6db72313fabde34b0f3b352b37b Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 3 Nov 2024 13:57:05 +0100 Subject: [PATCH 1/5] update roadmap --- ROADMAP.md | 1 + 1 file changed, 1 insertion(+) diff --git a/ROADMAP.md b/ROADMAP.md index 62daee6c..d892b365 100644 --- a/ROADMAP.md +++ b/ROADMAP.md @@ -9,6 +9,7 @@ This document contains the evolutions planned in 2024. * [ ] Docker * [ ] Create action plans not linked to a measurement * [ ] Change Logs +* [ ] Automatically remove measurements after a defined number of months ## Improvements From 8e6c613cbc0fa33fd5832051fc6651c4010a7b4a Mon Sep 17 00:00:00 2001 From: didier Date: Sun, 10 Nov 2024 14:48:37 +0100 Subject: [PATCH 2/5] new action plans --- app/Exports/ActionsExport.php | 97 ++++ app/Http/Controllers/ActionplanController.php | 509 ++++++++++++++---- app/Models/Action.php | 51 ++ app/Models/Control.php | 14 - composer.lock | 20 +- .../2024_11_06_123808_add_actions.php | 128 +++++ docs/index.fr.md | 2 +- docs/index.md | 2 +- resources/lang/en/common.php | 1 + resources/lang/en/cruds.php | 24 +- resources/lang/fr/common.php | 1 + resources/lang/fr/cruds.php | 21 +- resources/views/actions/close.blade.php | 188 +++++++ resources/views/actions/create.blade.php | 167 ++++++ resources/views/actions/edit.blade.php | 203 +++++++ resources/views/actions/index.blade.php | 168 ++++-- resources/views/actions/show.blade.php | 136 +++-- resources/views/controls/edit.blade.php | 8 +- resources/views/controls/index.blade.php | 34 +- resources/views/reports.blade.php | 3 + routes/web.php | 10 +- 21 files changed, 1556 insertions(+), 231 deletions(-) create mode 100644 app/Exports/ActionsExport.php create mode 100644 app/Models/Action.php create mode 100644 database/migrations/2024_11_06_123808_add_actions.php create mode 100644 resources/views/actions/close.blade.php create mode 100644 resources/views/actions/create.blade.php create mode 100644 resources/views/actions/edit.blade.php diff --git a/app/Exports/ActionsExport.php b/app/Exports/ActionsExport.php new file mode 100644 index 00000000..f04061ee --- /dev/null +++ b/app/Exports/ActionsExport.php @@ -0,0 +1,97 @@ + ['font' => ['bold' => true], + 'alignment' => [ + 'wrapText' => true, + 'vertical' => 'top', + ], + ], + ]; + } + + public function columnWidths(): array + { + return [ + 'A' => 10, // Reference + 'B' => 10, // Type + 'C' => 10, // creation_date + 'D' => 20, // scope + 'E' => 30, // clause + 'F' => 50, // name + 'G' => 50, // Cause + 'H' => 20, // Owners + 'I' => 50, // remediation + 'J' => 10, // status + 'K' => 10, // close_date + 'L' => 50, // justification + ]; + } + + /** + * @var action $action + */ + public function map($action): array + { + return [ + [ + $action->reference, + $action->type, + $action->due_date, + $action->scope, + $action->measures()->implode('clause', ', '), + $action->name, + $action->cause, + $action->owners()->implode('name', ', '), + $action->remediation, + $action->status, + $action->close_date, + $action->justification, + ], + ]; + } + + /** + * @return \Illuminate\Support\Collection + */ + public function query() + { + return Action::orderBy('creation_date'); + } +} diff --git a/app/Http/Controllers/ActionplanController.php b/app/Http/Controllers/ActionplanController.php index 385ee22c..52724550 100644 --- a/app/Http/Controllers/ActionplanController.php +++ b/app/Http/Controllers/ActionplanController.php @@ -2,11 +2,15 @@ namespace App\Http\Controllers; +use App\Models\Action; use App\Models\Control; +use App\Exports\ActionsExport; + use Illuminate\Http\Request; use Illuminate\Http\Response; use Illuminate\Support\Facades\Auth; use Illuminate\Support\Facades\DB; +use Maatwebsite\Excel\Facades\Excel; class ActionplanController extends Controller { @@ -15,7 +19,7 @@ class ActionplanController extends Controller * * @return \Illuminate\Http\Response */ - public function index() + public function index(Request $request) { abort_if( ! ((Auth::User()->role === 1) || @@ -25,67 +29,99 @@ public function index() '403 Forbidden' ); + // Get type filter + $type = $request->get('type'); + if ($type !== null) + $request->session()->put('type', $type); + elseif ($request->has('type')) + $request->session()->forget('type'); + else + $type = $request->session()->get('type'); + + // Get status filter + $status = $request->get('status'); + if ($status !== null) + $request->session()->put('status', $status); + elseif ($request->has('status')) + $request->session()->forget('status'); + else + $status = $request->session()->get('status'); + + // Get scope filter + $scope = $request->get('scope'); + if ($scope !== null) + $request->session()->put('scope', $scope); + elseif ($request->has('scope')) + $request->session()->forget('scope'); + else + $scope = $request->session()->get('scope'); + // Build query - $actions = DB::table('controls as c1') - ->leftjoin('controls as c2', 'c1.next_id', '=', 'c2.id'); + $actions = DB::table('actions') + ->leftjoin('controls', 'control_id', '=', 'controls.id'); + + // filter on type + if (($type!==null) && (strlen($type)>0)) + $actions = $actions->where("type",$type); + + // filter on status + if ($status=="0") + $actions = $actions->where("actions.status",0); + elseif ($status=="1") + $actions = $actions->where("actions.status",1); + + // filter on scope + if (($scope!==null) && (strlen($scope)>0)) + $actions = $actions->where("actions.scope",$scope); // filter on auditee controls if (Auth::User()->role == 5) { $actions = $actions - ->leftjoin('control_user', 'c1.id', '=', 'control_user.control_id') - ->where('control_user.user_id', '=', Auth::User()->id); + ->leftjoin('action_user', 'controls.id', '=', 'control_user.control_id') + ->where('action_user.user_id', '=', Auth::User()->id); } - // filter on scores that are red or orange - $actions = $actions - ->where(function ($query) { - $query->where('c1.score', '=', 1) - ->orWhere('c1.score', '=', 2); - }); - - // filter on not yet realised next control - $actions = $actions - ->whereIn('c2.status', [0,1]); - // Query DB $actions = $actions->select( [ - 'c1.id', - 'c1.action_plan', - 'c1.score', - 'c1.name', - 'c1.scope', - 'c1.plan_date', - 'c2.id as next_id', - 'c2.plan_date as next_date', + 'actions.id', + 'actions.reference', + 'actions.type', + 'actions.name', + 'actions.criticity', + 'actions.scope', + 'actions.cause', + 'actions.status', + 'actions.due_date', ] - ) - ->orderBy('c1.realisation_date')->get(); - - // Fetch measures for all controls in one query - $measuresByControlId = DB::table('control_measure') - ->select([ - 'control_id', - 'measure_id', - 'clause', - ]) - ->leftjoin('measures', 'measures.id', '=', 'measure_id') - ->whereIn('control_id', $actions->pluck('id')) + )->get(); + + // Get types + $types = DB::table('actions') + ->select('type') + ->whereNotNull('type') + ->where('status','<>',3) + ->distinct() + ->orderBy('type') ->get() - ->groupBy('control_id'); - - // map clauses - foreach ($actions as $action) { - $action->measures = $measuresByControlId->get($action->id, collect())->map(function ($controlMeasure) { - return [ - 'id' => $controlMeasure->measure_id, - 'clause' => $controlMeasure->clause, - ]; - }); - } + ->pluck('type') + ->toArray(); + + // Get scopes + $scopes = DB::table('actions') + ->select('scope') + ->whereNotNull('scope') + ->where('status','<>',3) + ->distinct() + ->orderBy('scope') + ->get() + ->pluck('scope') + ->toArray(); // return return view('actions.index') + ->with('types', $types) + ->with('scopes', $scopes) ->with('actions', $actions); } @@ -104,28 +140,66 @@ public function save(Request $request) '403 Forbidden' ); + // Get the action plan $id = (int) $request->get('id'); + $action = Action::find($id); - // save control - $control = Control::find($id); - $control->action_plan = request('action_plan'); - $control->update(); - - // save next control - $next_id = $control->next_id; - if ($next_id !== null) { - $next_control = Control::find($next_id); - if ($next_control !== null) { - $next_control->plan_date = request('plan_date'); - $next_control->update(); - } - } + // Action not found + abort_if($action === null, Response::HTTP_NOT_FOUND, '404 Not Found'); - return redirect('/actions'); + // Update fields + $action->reference = request('reference'); + $action->type = request('type'); + $action->due_date = request('due_date'); + $action->name = request('name'); + $action->scope = request('scope'); + $action->cause = request('cause'); + $action->remediation = request('remediation'); + $action->status = request('status'); + $action->close_date = request('close_date'); + $action->justification = request('justification'); + $action->update(); + + // Sync measures + $action->measures()->sync($request->input('measures', [])); + + // Sync owners + $action->owners()->sync($request->input('owners', [])); + + return redirect("/action/show/{$id}"); + } + + /** + * Update an action plan + * + * @param \App\Domain $domain + * + * @return \Illuminate\Http\Response + */ + public function update(Request $request) + { + abort_if( + ! ((Auth::User()->role === 1) || (Auth::User()->role === 2)), + Response::HTTP_FORBIDDEN, + '403 Forbidden' + ); + + // Get the action plan + $id = (int) $request->get('id'); + $action = Action::find($id); + + // Action not found + abort_if($action === null, Response::HTTP_NOT_FOUND, '404 Not Found'); + + // Update fields + $action->remediation = request('remediation'); + $action->update(); + + return redirect("/actions"); } /** - * Display the specified resource. + * Display the action. * * @param int $id * @@ -141,49 +215,278 @@ public function show(int $id) '403 Forbidden' ); - $action = DB::table('controls as c1') - ->select( - 'c1.id', - 'c1.name', - 'c1.scope', - 'c1.objective', - 'c1.observations', - 'c1.action_plan', - 'c1.plan_date', - 'c1.score', - 'c1.realisation_date', - 'c1.score', - 'c2.plan_date as next_date', - 'c2.id as next_id' - ) - ->leftJoin('controls as c2', function ($join) { - $join->on('c1.next_id', '=', 'c2.id'); - }) - ->where('c1.id', '=', $id) - ->first(); - - // Fetch measures for all controls in one query - $measuresByControlId = DB::table('control_measure') - ->select([ - 'control_id', - 'measure_id', - 'clause', - ]) - ->leftjoin('measures', 'measures.id', '=', 'measure_id') - ->where('control_id', '=', $action->id) - ->get() - ->groupBy('control_id'); + // TODO : check for user - // map clauses - $action->measures = $measuresByControlId->get($action->id, collect())->map(function ($controlMeasure) { - return [ - 'id' => $controlMeasure->measure_id, - 'clause' => $controlMeasure->clause, - ]; - }); + // Get the action + $action = Action::find($id); - // return + // Control not found + abort_if($action === null, Response::HTTP_NOT_FOUND, '404 Not Found'); + + // Return return view('actions.show') ->with('action', $action); } + + /** + * Edit the action. + * + * @param int $id + * + * @return \Illuminate\Http\Response + */ + public function edit(int $id) + { + abort_if( + ! ((Auth::User()->role == 1) || + (Auth::User()->role == 2) || + (Auth::User()->role == 3)), + Response::HTTP_FORBIDDEN, + '403 Forbidden' + ); + + // TODO : check for user + + // Get the action + $action = Action::find($id); + + // Control not found + abort_if($action === null, Response::HTTP_NOT_FOUND, '404 Not Found'); + + // Get all scopes + $scopes = DB::table('actions') + ->select('scope') + ->whereNotNull('scope') + ->where('status', '<> ', 2) + ->distinct() + ->orderBy('scope') + ->get() + ->pluck('scope') + ->toArray(); + + // Get all types + $types = DB::table('actions') + ->select('type') + ->whereNotNull('type') + ->where('status', '<> ', 2) + ->distinct() + ->orderBy('type') + ->get() + ->pluck('type') + ->toArray(); + + // Get all measures + $all_measures = DB::table('measures') + ->select('id', 'clause') + ->orderBy('id') + ->get(); + + $measures = DB::table('control_measure') + ->select('measure_id') + ->where('control_id', $id) + ->get() + ->pluck('measure_id') + ->toArray(); + + // Get users + $users = DB::table('users') + ->select('id','name') + ->orderBy('name') + ->get(); + + // Return + return view('actions.edit') + ->with('scopes', $scopes) + ->with('types', $types) + ->with('all_measures', $all_measures) + ->with('measures', $measures) + ->with('users', $users) + ->with('action', $action); + } + + /** + * Create an action. + * + * @return \Illuminate\Http\Response + */ + public function create() + { + abort_if( + ! ((Auth::User()->role == 1) || + (Auth::User()->role == 2)), + Response::HTTP_FORBIDDEN, + '403 Forbidden' + ); + + // Get all scopes + $scopes = DB::table('actions') + ->select('scope') + ->whereNotNull('scope') + ->where('status', '<> ', 2) + ->distinct() + ->orderBy('scope') + ->get() + ->pluck('scope') + ->toArray(); + + // Get all types + $types = DB::table('actions') + ->select('type') + ->whereNotNull('type') + ->where('status', '<> ', 2) + ->distinct() + ->orderBy('type') + ->get() + ->pluck('type') + ->toArray(); + + // Get all measures + $all_measures = DB::table('measures') + ->select('id', 'clause') + ->orderBy('id') + ->get(); + + // Get users + $users = DB::table('users') + ->select('id','name') + ->orderBy('name') + ->get(); + + // Return + return view('actions.create') + ->with('scopes', $scopes) + ->with('types', $types) + ->with('all_measures', $all_measures) + ->with('users', $users); + } + + /** + * Store the action. + * + * @param int $id + * + * @return \Illuminate\Http\Response + */ + public function store(Request $request) + { + abort_if( + ! ((Auth::User()->role == 1) || + (Auth::User()->role == 2)), + Response::HTTP_FORBIDDEN, + '403 Forbidden' + ); + + $action = new Action(); + + // Set fields + $action->reference = request('reference'); + $action->type = request('type'); + $action->due_date = request('due_date'); + $action->name = request('name'); + $action->scope = request('scope'); + $action->cause = request('cause'); + $action->remediation = request('remediation'); + + // Save + $action->save(); + + // Sync measures + $action->measures()->sync($request->input('measures', [])); + + // Sync owners + $action->owners()->sync($request->input('owners', [])); + + // Return + return redirect('/actions'); + + } + + + /** + * Show Close action. + * + * @param int $id + * + * @return \Illuminate\Http\Response + */ + public function close(int $id) + { + abort_if( + ! ((Auth::User()->role == 1) || + (Auth::User()->role == 2) || + (Auth::User()->role == 3)), + Response::HTTP_FORBIDDEN, + '403 Forbidden' + ); + + // TODO : check for user + + // Get the action + $action = Action::find($id); + + // Control not found + abort_if($action === null, Response::HTTP_NOT_FOUND, '404 Not Found'); + + // Return + return view('actions.close') + ->with('action', $action); + } + + + /** + * Show Close action. + * + * @param int $id + * + * @return \Illuminate\Http\Response + */ + public function doClose(Request $request) + { + abort_if( + ! ((Auth::User()->role == 1) || + (Auth::User()->role == 2) || + (Auth::User()->role == 3)), + Response::HTTP_FORBIDDEN, + '403 Forbidden' + ); + + // TODO : check for user + + // Get the action + $id = request('id'); + $action = Action::find($id); + + // Control not found + abort_if($action === null, Response::HTTP_NOT_FOUND, '404 Not Found'); + + // Get fields + $action->status=request('status'); + $action->close_date=request('close_date'); + $action->justification=request('justification'); + + // Save action + $action->save(); + + // Return + return redirect('/actions'); + } + + public function export() + { + // For administrators and users only + abort_if( + Auth::User()->role !== 1 && Auth::User()->rol !== 2, + Response::HTTP_FORBIDDEN, + '403 Forbidden' + ); + + return Excel::download( + new ActionsExport(), + trans('cruds.actions.title') . + '-' . + now()->format('Y-m-d Hi') . + '.xlsx' + ); + } + } diff --git a/app/Models/Action.php b/app/Models/Action.php new file mode 100644 index 00000000..de4d4db1 --- /dev/null +++ b/app/Models/Action.php @@ -0,0 +1,51 @@ +belongsToMany(User::class, 'action_user', 'action_id')->orderBy('name'); + } + + public function measures() + { + return $this->belongsToMany(Measure::class, 'action_measure', 'action_id'); + } +} diff --git a/app/Models/Control.php b/app/Models/Control.php index 81f92d09..f6b3c90f 100644 --- a/app/Models/Control.php +++ b/app/Models/Control.php @@ -14,8 +14,6 @@ class Control extends Model 'attributes', 'model', 'action_plan', - 'realisation_date', - 'plan_date', ]; protected $dates = [ @@ -42,18 +40,6 @@ class Control extends Model // 1 - Proposed by auditee => relisation date not null // 2 - Done => relisation date not null - /* - public function domain() - { - return $this->belongsTo(Domain::class, 'domain_id'); - } - - // deprecated - public function measure() - { - return $this->belongsTo(Measure::class, 'measure_id'); - } - */ public function measures() { return $this->belongsToMany(Measure::class)->orderBy('clause'); diff --git a/composer.lock b/composer.lock index d39badfc..e94c839b 100644 --- a/composer.lock +++ b/composer.lock @@ -710,20 +710,20 @@ }, { "name": "ezyang/htmlpurifier", - "version": "v4.17.0", + "version": "v4.18.0", "source": { "type": "git", "url": "https://github.com/ezyang/htmlpurifier.git", - "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c" + "reference": "cb56001e54359df7ae76dc522d08845dc741621b" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/bbc513d79acf6691fa9cf10f192c90dd2957f18c", - "reference": "bbc513d79acf6691fa9cf10f192c90dd2957f18c", + "url": "https://api.github.com/repos/ezyang/htmlpurifier/zipball/cb56001e54359df7ae76dc522d08845dc741621b", + "reference": "cb56001e54359df7ae76dc522d08845dc741621b", "shasum": "" }, "require": { - "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0" + "php": "~5.6.0 || ~7.0.0 || ~7.1.0 || ~7.2.0 || ~7.3.0 || ~7.4.0 || ~8.0.0 || ~8.1.0 || ~8.2.0 || ~8.3.0 || ~8.4.0" }, "require-dev": { "cerdic/css-tidy": "^1.7 || ^2.0", @@ -765,9 +765,9 @@ ], "support": { "issues": "https://github.com/ezyang/htmlpurifier/issues", - "source": "https://github.com/ezyang/htmlpurifier/tree/v4.17.0" + "source": "https://github.com/ezyang/htmlpurifier/tree/v4.18.0" }, - "time": "2023-11-17T15:01:25+00:00" + "time": "2024-11-01T03:51:45+00:00" }, { "name": "firebase/php-jwt", @@ -10005,12 +10005,12 @@ ], "aliases": [], "minimum-stability": "stable", - "stability-flags": {}, + "stability-flags": [], "prefer-stable": true, "prefer-lowest": false, "platform": { "php": "^8.2" }, - "platform-dev": {}, - "plugin-api-version": "2.6.0" + "platform-dev": [], + "plugin-api-version": "2.3.0" } diff --git a/database/migrations/2024_11_06_123808_add_actions.php b/database/migrations/2024_11_06_123808_add_actions.php new file mode 100644 index 00000000..fc47d98c --- /dev/null +++ b/database/migrations/2024_11_06_123808_add_actions.php @@ -0,0 +1,128 @@ +increments('id'); + $table->string('reference', 32)->nullable(); + $table->string('type', 32)->nullable(); + $table->integer('criticity')->dafault(0); + $table->integer('status')->dafault(0); + $table->string('scope', 32)->nullable(); + $table->string('name')->nullable(); + $table->text('cause')->nullable(); + $table->text('remediation')->nullable(); + $table->integer('control_id')->unsigned()->nullable(); + $table->foreign('control_id')->references('id')->on('controls'); + $table->date('creation_date')->nullable(); + $table->date('due_date')->nullable(); + $table->date('close_date')->nullable(); + $table->text('justification')->nullable(); + + $table->timestamps(); + }); + + // Link between actions and users + Schema::create('action_user', function (Blueprint $table) { + $table->integer('action_id')->unsigned(); + $table->foreign('action_id')->references('id')->on('actions'); + $table->biginteger('user_id')->unsigned(); + $table->foreign('user_id')->references('id')->on('users'); + }); + + // Link between actions and measure + Schema::create('action_measure', function (Blueprint $table) { + $table->integer('action_id')->unsigned(); + $table->foreign('action_id')->references('id')->on('actions'); + $table->integer('measure_id')->unsigned(); + $table->foreign('measure_id')->references('id')->on('measures'); + }); + + // Move data from Controls to Actions + $controls = DB::table('controls as c1') + ->select( + [ + 'c1.id', + 'c1.name', + 'c1.action_plan', + 'c1.score', + 'c1.scope', + 'c1.observations', + 'c1.realisation_date', + 'c2.plan_date' + ]) + ->leftjoin('controls as c2', 'c1.next_id', '=', 'c2.id') + ->where(function ($query) { + $query->where('c1.score', '=', 1) + ->orWhere('c1.score', '=', 2); + }) + ->whereIn('c2.status', [0,1]) + ->get(); + + foreach($controls as $control) { + + // Create Action + $action = new Action(); + + // Fill fields + $action->control_id = $control->id; + $action->name = $control->name; + $action->criticity = $control->score; + $action->scope = $control->scope; + $action->cause = $control->observations; + $action->remediation = $control->action_plan; + $action->creation_date = $control->realisation_date; + $action->due_date = $control->plan_date; + + // Save it + $action->save(); + + // Sync onwers + $owners = DB::table('control_user') + ->select('user_id') + ->where('control_id',$control->id) + ->pluck('user_id')->toArray(); + + $action->owners()->sync($owners); + + // Sync measures + $measures = DB::table('control_measure') + ->select('measure_id') + ->where('control_id',$control->id) + ->pluck('measure_id')->toArray(); + + $action->measures()->sync($measures); + } + + // remove fields from controls + } + + /** + * Reverse the migrations. + */ + public function down(): void + { + Schema::dropIfExists('action_user'); + Schema::dropIfExists('action_measure'); + + Schema::dropIfExists('actions'); + } +}; diff --git a/docs/index.fr.md b/docs/index.fr.md index bae657cb..3228ac67 100644 --- a/docs/index.fr.md +++ b/docs/index.fr.md @@ -3,7 +3,7 @@ ### Qu’est-ce que Deming ? -Deming est un outil Open Source conçu pour aider les RSSI à mettre en place et à maintenir leur système de management de la sécurité de l'information. Grâce à cette application, les RSSI peuvent facilement planifier et suivre la mise en œuvre des contrôles de sécurité et le cycle d'amélioration continue requis par la norme ISO 27001. L'application est conçue pour être facile à utiliser et à personnaliser, avec une interface utilisateur intuitive. +Deming est un outil Open Source conçu pour aider les RSSI à maintenir leur système de management de la sécurité de l'information. Grâce à cette application, les RSSI peuvent facilement planifier et suivre la mise en œuvre des contrôles de sécurité et le cycle d'amélioration continue. L'application est conçue pour être facile à utiliser et à personnaliser, avec une interface utilisateur intuitive. Deming offre des fonctionnalités telles que la [gestion des mesures de sécurité](measures.fr.md), diff --git a/docs/index.md b/docs/index.md index e0307f16..20b2c97b 100644 --- a/docs/index.md +++ b/docs/index.md @@ -3,7 +3,7 @@ ### What is Deming? -Deming is an Open Source tool designed to help CISOs set up and maintain their information security management system. Using this app, CISOs can easily plan and track the implementation of security controls and the continuous improvement cycle required by ISO 27001. The app is designed to be easy to use and customize, with a intuitive user interface. +Deming is an Open Source tool designed to help CISOs maintain their information security management system. Using this app, CISOs can easily plan and track the implementation of security controls and the continuous improvement cycle. The app is designed to be easy to use and customize, with a intuitive user interface. Deming offers features such as [security measures management](measures.md), diff --git a/resources/lang/en/common.php b/resources/lang/en/common.php index ff4b3fa4..e7fbb8c0 100644 --- a/resources/lang/en/common.php +++ b/resources/lang/en/common.php @@ -7,6 +7,7 @@ 'check' => 'Check', 'create' => 'Create', 'clone' => 'Copy', + 'close' => 'Close', 'delete' => 'Delete', 'download' => 'Download', 'edit' => 'Edit', diff --git a/resources/lang/en/cruds.php b/resources/lang/en/cruds.php index 6ac9ee4b..d30baa23 100644 --- a/resources/lang/en/cruds.php +++ b/resources/lang/en/cruds.php @@ -12,9 +12,11 @@ ], 'action' => [ 'index' => 'Action plans', - 'show' => 'Action Plan', + 'show' => 'Action plan', + 'edit' => 'Edit action plan', + 'title' => 'Actions', 'fields' => [ - 'clause' => 'Clause', + 'clauses' => 'Clauses', 'name' => 'Name', 'scope' => 'Scope', 'action' => 'Action plan', @@ -23,7 +25,24 @@ 'note' => 'Score', 'objective' => 'Objective', 'observation' => 'Observation', + 'justification' => 'Justification', 'action_plan' => 'Action Plan', + 'reference' => 'Ref', + 'type' => 'Type', + 'due_date' => 'Due date', + 'choose_type' => 'Choose type', + 'choose_scope' => 'Choose scope', + 'remediation' => 'Remediation', + 'criticity' => 'Criticity', + 'cause' => 'Reason', + 'clauses' => 'Clauses', + 'owners' => 'Owners', + 'status' => 'Status', + 'status_open' => 'Open', + 'status_closed' => 'Closed', + 'status_rejected' => 'Rejected', + 'status_all' => 'All', + 'close_date' => 'Close date', ], ], 'attribute' => [ @@ -160,6 +179,7 @@ 'measures_export' => 'Export security measures', 'controls_export' => 'Export controls', 'import' => 'Import', + 'actions_export' => 'Export action plans', ], 'imports' => [ 'index' => 'Import', diff --git a/resources/lang/fr/common.php b/resources/lang/fr/common.php index ea3ed1e3..de1be185 100644 --- a/resources/lang/fr/common.php +++ b/resources/lang/fr/common.php @@ -6,6 +6,7 @@ 'cancel' => 'Annuler', 'check' => 'Vérifier', 'clone' => 'Copier', + 'close' => 'Fermer', 'create' => 'Créer', 'delete' => 'Supprimer', 'download' => 'Télécharger', diff --git a/resources/lang/fr/cruds.php b/resources/lang/fr/cruds.php index 90f82424..05d7d866 100644 --- a/resources/lang/fr/cruds.php +++ b/resources/lang/fr/cruds.php @@ -13,6 +13,8 @@ 'action' => [ 'index' => 'Liste des plans d\'action', 'show' => 'Plan d\'action', + 'edit' => 'Modifier un plan d\'action', + 'title' => 'Actions', 'fields' => [ 'clause' => 'Clause', 'name' => 'Nom', @@ -23,7 +25,23 @@ 'note' => 'Score', 'objective' => 'Objectif', 'observation' => 'Observation', - 'action_plan' => 'Plan d\'actions' + 'action_plan' => 'Plan d\'actions', + 'reference' => 'Ref', + 'type' => 'Type', + 'due_date' => 'Date due', + 'choose_type' => 'Choisir un type', + 'choose_scope' => 'Choisir un périmètre', + 'remediation' => 'Remédiation', + 'justification' => 'Justification', + 'criticity' => 'Criticité', + 'cause' => 'Cause', + 'clauses' => 'Clauses', + 'owners' => 'Responsables', + 'status_open' => 'Ouvert', + 'status_closed' => 'Fermé', + 'status_rejected' => 'Rejeté', + 'status_all' => 'Tous', + 'close_date' => 'Date de clôture', ], ], 'attribute' => [ @@ -159,6 +177,7 @@ 'domains_export'=> 'Exportation des domaines', 'measures_export' => 'Exportation des contrôles', 'controls_export' => 'Exportation des mesures de sécurité', + 'actions_export' => 'Exporter les plans d\'action', ], 'imports' => [ 'index' => 'Importer', diff --git a/resources/views/actions/close.blade.php b/resources/views/actions/close.blade.php new file mode 100644 index 00000000..17e45a05 --- /dev/null +++ b/resources/views/actions/close.blade.php @@ -0,0 +1,188 @@ +@extends("layout") + +@section("content") + + +
+
+ + @if (count($errors)) +
+
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+
+ @endif + +
+ @csrf + + +
+
+
+ {{ trans("cruds.action.fields.reference") }} +
+
+ {{ $action->reference }} +
+
+ {{ trans("cruds.action.fields.type") }} +
+
+ {{ $action->type }} +
+
+ {{ trans('cruds.action.fields.due_date') }} +
+
+ {{$action->due_date}} +
+
+ +
+
+ {{ trans("cruds.action.fields.clauses") }} +
+
+ @foreach($action->measures as $measure) + {{ $measure->clause }} + @if(!$loop->last) + , + @endif + @endforeach +
+
+ +
+
+ {{ trans('cruds.action.fields.name') }} +
+
+ @if ($action->control_id!==null) + + {{ $action->name }} + + @else + {{ $action->name }} + @endif +
+ @if ($action->scope!==null) +
+ {{ trans("cruds.control.fields.scope") }} +   + {{ $action->scope }} +
+ @endif +
+ +
+
+ {{ trans('cruds.action.fields.cause') }} +
+
+
{{ $action->cause }}
+
+
+ +
+
+ +
+
+ {{ trans('cruds.action.fields.remediation') }} +
+
+ {!! \Parsedown::instance()->text($action->remediation) !!} +
+
+ +
+
+ {{ trans('cruds.action.fields.status') }} +
+
+ +
+
+ {{ trans('cruds.action.fields.close_date') }} +
+
+ +
+
+
+
+ {{ trans('cruds.action.fields.justification') }} +
+
+ +
+
+ +
+
+ {{ trans('cruds.action.fields.owners') }} +
+
+ @foreach($action->owners as $owner) + {{ $owner->name }} + @if ($action->owners->last()!=$owner) + , + @endif + @endforeach +
+
+ +
+
+ +
+
+
+
+ @if ($action->status==0) + + @endif +   + + +   + {{ trans("common.cancel") }} + +
+
+
+
+
+
+ + + +@endsection diff --git a/resources/views/actions/create.blade.php b/resources/views/actions/create.blade.php new file mode 100644 index 00000000..3edcdfec --- /dev/null +++ b/resources/views/actions/create.blade.php @@ -0,0 +1,167 @@ +@extends("layout") + +@section("content") + + +
+
+ + @if (count($errors)) +
+
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+
+ @endif + +
+ @csrf + +
+
+
+ {{ trans("cruds.action.fields.reference") }} +
+
+ + + + + + + + +
+ + + {{ trans("cruds.action.fields.type") }} + + + + {{ trans('cruds.action.fields.due_date') }} + + +
+
+
+ +
+
+ {{ trans('cruds.action.fields.clauses') }} +
+
+ +
+
+ +
+
+ {{ trans("cruds.action.fields.name") }} +
+
+ +
+
+ {{ trans("cruds.action.fields.scope") }} +
+
+ +
+
+ +
+
+ {{ trans('cruds.action.fields.cause') }} +
+
+ +
+
+ +
+
+ +
+
+ {{ trans('cruds.action.fields.remediation') }} +
+
+ +
+
+ +
+
+ {{ trans('cruds.action.fields.owners') }} +
+
+ +
+
+ +
+
+ +
+
+
+
+ +   + + +   + {{ trans("common.cancel") }} + +
+
+
+
+
+
+ + + +@endsection diff --git a/resources/views/actions/edit.blade.php b/resources/views/actions/edit.blade.php new file mode 100644 index 00000000..49d694f1 --- /dev/null +++ b/resources/views/actions/edit.blade.php @@ -0,0 +1,203 @@ +@extends("layout") + +@section("content") + + +
+
+ + @if (count($errors)) +
+
+
    + @foreach ($errors->all() as $error) +
  • {{ $error }}
  • + @endforeach +
+
+
+ @endif + +
+ @csrf + + +
+
+
+ {{ trans("cruds.action.fields.reference") }} +
+
+ + + + + + + + +
+ + + {{ trans("cruds.action.fields.type") }} + + + + {{ trans('cruds.action.fields.due_date') }} + + +
+
+
+ +
+
+ {{ trans('cruds.action.fields.clauses') }} +
+
+ +
+
+ +
+
+ {{ trans("cruds.action.fields.name") }} +
+
+ +
+
+ {{ trans("cruds.action.fields.scope") }} +
+
+ +
+
+ +
+
+ {{ trans('cruds.action.fields.cause') }} +
+
+ +
+
+ +
+
+ +
+
+ {{ trans('cruds.action.fields.remediation') }} +
+
+ +
+
+ +
+
+ {{ trans('cruds.action.fields.status') }} +
+
+ +
+
+ {{ trans('cruds.action.fields.close_date') }} +
+
+ +
+
+ +
+
+ {{ trans('cruds.action.fields.justification') }} +
+
+ +
+
+ +
+
+ {{ trans('cruds.action.fields.owners') }} +
+
+ +
+
+ +
+
+ +
+
+
+
+ +   + + +   + {{ trans("common.cancel") }} + +
+
+
+
+
+
+ + + +@endsection diff --git a/resources/views/actions/index.blade.php b/resources/views/actions/index.blade.php index ee10a99f..ea3248c7 100644 --- a/resources/views/actions/index.blade.php +++ b/resources/views/actions/index.blade.php @@ -3,58 +3,140 @@ @section("content")
-
-
-
- +
+
+
+ +
+
+ + + {{ trans("cruds.action.fields.status_open") }} + + + + + {{ trans("cruds.action.fields.status_closed") }} + + + + + {{ trans("cruds.action.fields.status_all") }} + +
+
+
+
+ +
+
+ @if ((Auth::User()->role==1)||(Auth::User()->role==2)) + + +   + {{ trans('common.new') }} + + @endif +
+
+
+ + + +
- - + + + + - - - + @foreach($actions as $action) - - - - - - + + + + + + @endforeach diff --git a/resources/views/actions/show.blade.php b/resources/views/actions/show.blade.php index 28c047af..40e76083 100644 --- a/resources/views/actions/show.blade.php +++ b/resources/views/actions/show.blade.php @@ -24,18 +24,39 @@ @endif - + @csrf
- {{ trans("cruds.control.fields.clauses") }} + {{ trans("cruds.action.fields.reference") }} +
+
+ {{ $action->reference }} +
+
+ {{ trans("cruds.action.fields.type") }} +
+
+ {{ $action->type }} +
+
+ {{ trans('cruds.action.fields.due_date') }} +
+
+ {{$action->due_date}} +
+
+ +
+
+ {{ trans("cruds.action.fields.clauses") }}
@foreach($action->measures as $measure) - {{ $measure['clause'] }} + {{ $measure->clause }} @if(!$loop->last) , @endif @@ -47,11 +68,17 @@
{{ trans('cruds.action.fields.name') }}
-
- {{ $action->name }} +
+ @if ($action->control_id!==null) + + {{ $action->name }} + + @else + {{ $action->name }} + @endif
@if ($action->scope!==null) -
+
{{ trans("cruds.control.fields.scope") }}   {{ $action->scope }} @@ -61,39 +88,75 @@
- {{ trans('cruds.action.fields.objective') }} + {{ trans('cruds.action.fields.cause') }}
-
{{ $action->objective }}
+
{{ $action->cause }}
-
-
- {{ trans('cruds.action.fields.observation') }} -
-
-
{{ $action->observations }}
-
-
+
+
- {{ trans('cruds.action.fields.next_date') }} + {{ trans('cruds.action.fields.remediation') }}
-
- +
+ @if ($action->status==0) + + @else + {!! \Parsedown::instance()->text($action->remediation) !!} + @endif
+ @if ($action->status!=0) +
+
+ {{ trans('cruds.action.fields.status') }} +
+
+ @if ($action->status==0) + {{ trans('cruds.action.fields.status_open') }} + @elseif ($action->status==1) + {{ trans('cruds.action.fields.status_closed') }} + @elseif ($action->status==2) + {{ trans('cruds.action.fields.status_rejected') }} + @else + {{ $action->status }} + @endif +
+
+ {{ trans('cruds.action.fields.close_date') }} +
+
+ {{ $action->close_date}} +
+
- {{ trans('cruds.action.fields.action_plan') }} + {{ trans('cruds.action.fields.justification') }}
- + {!! \Parsedown::instance()->text($action->justification) !!}
+ @endif + +
+
+ {{ trans('cruds.action.fields.owners') }} +
+
+ @foreach($action->owners as $owner) + {{ $owner->name }} + @if ($action->owners->last()!=$owner) + , + @endif + @endforeach +
+
@@ -102,22 +165,31 @@
- @if (Auth::User()->role==1) + @if ($action->status==0) - @endif - +   + + +   + {{ trans("common.close") }} + +   + @endif + + +   + {{ trans("common.edit") }} +   -
- - + + +   + {{ trans("common.cancel") }} +
@@ -127,7 +199,7 @@
{{ trans('cruds.action.fields.clause') }}{{ trans('cruds.action.fields.action') }}{{ trans('cruds.action.fields.reference') }}{{ trans('cruds.action.fields.type') }}{{ trans('cruds.action.fields.status') }}{{ trans('cruds.action.fields.name') }} {{ trans('cruds.action.fields.scope') }}{{ trans('cruds.action.fields.plan_date') }}{{ trans('cruds.action.fields.next_date') }}{{ trans('cruds.action.fields.note') }}{{ trans('cruds.action.fields.due_date') }}
- @foreach($action->measures as $measure) - - {{ $measure['clause'] }} - - @endforeach - - {{ $action->name }} - {!! \Parsedown::instance()->text($action->action_plan) !!} - {{ $action->scope }}{{ $action->plan_date }}{{ $action->next_date }} -
- @if ($action->score==1) - 😡 - @elseif ($action->score==2) - 😐 - @elseif ($action->score==3) - 😀 - @else - ○ - @endif -
-
+ {{ $action->reference }} + + {{ $action->type }} + + @if ($action->status==0) + {{ trans('cruds.action.fields.status_open') }} + @elseif ($action->status==1) + {{ trans('cruds.action.fields.status_closed') }} + @elseif ($action->status==2) + {{ trans('cruds.action.fields.status_rejected') }} + @else + {{ $action->status }} + @endif + + {{ $action->name }} + {!! \Parsedown::instance()->text($action->cause) !!} + + {{ $action->scope }} + + {{ $action->due_date }} +