diff --git a/ROADMAP.md b/ROADMAP.md
index 62daee6..d892b36 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
diff --git a/app/Exports/ActionsExport.php b/app/Exports/ActionsExport.php
new file mode 100644
index 0000000..f04061e
--- /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 385ee22..7c04293 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.action.title') .
+ '-' .
+ now()->format('Y-m-d Hi') .
+ '.xlsx'
+ );
+ }
+
}
diff --git a/app/Http/Controllers/HomeController.php b/app/Http/Controllers/HomeController.php
index 69b27d2..d46d1a1 100644
--- a/app/Http/Controllers/HomeController.php
+++ b/app/Http/Controllers/HomeController.php
@@ -145,10 +145,8 @@ public function index(Request $request)
// Count number of action plans
$action_plans_count =
- DB::table('controls as c1')
- ->leftjoin('controls as c2', 'c1.id', '=', 'c2.next_id')
- ->whereNull('c1.realisation_date')
- ->whereIn('c2.score', [1, 2])
+ DB::table('actions')
+ ->where('status',0)
->count();
$request->session()->put('action_plans_count', $action_plans_count);
diff --git a/app/Models/Action.php b/app/Models/Action.php
new file mode 100644
index 0000000..de4d4db
--- /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 81f92d0..f6b3c90 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 d39badf..e94c839 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 0000000..fc47d98
--- /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 bae657c..3228ac6 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 e0307f1..20b2c97 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 ff4b3fa..e7fbb8c 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 6ac9ee4..d30baa2 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 ea3ed1e..de1be18 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 90f8242..05d7d86 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 0000000..17e45a0
--- /dev/null
+++ b/resources/views/actions/close.blade.php
@@ -0,0 +1,188 @@
+@extends("layout")
+
+@section("content")
+
+
+
+
+
+ @if (count($errors))
+
+ @endif
+
+
+
+
+
+
+
+@endsection
diff --git a/resources/views/actions/create.blade.php b/resources/views/actions/create.blade.php
new file mode 100644
index 0000000..3edcdfe
--- /dev/null
+++ b/resources/views/actions/create.blade.php
@@ -0,0 +1,167 @@
+@extends("layout")
+
+@section("content")
+
+
+
+
+
+ @if (count($errors))
+
+ @endif
+
+
+
+
+
+
+
+@endsection
diff --git a/resources/views/actions/edit.blade.php b/resources/views/actions/edit.blade.php
new file mode 100644
index 0000000..49d694f
--- /dev/null
+++ b/resources/views/actions/edit.blade.php
@@ -0,0 +1,203 @@
+@extends("layout")
+
+@section("content")
+
+
+
+
+
+ @if (count($errors))
+
+ @endif
+
+
+
+
+
+
+
+@endsection
diff --git a/resources/views/actions/index.blade.php b/resources/views/actions/index.blade.php
index ee10a99..ea3248c 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") }}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
- {{ 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($actions as $action)
-
- @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 }}
+ |
@endforeach
diff --git a/resources/views/actions/show.blade.php b/resources/views/actions/show.blade.php
index 28c047a..40e7608 100644
--- a/resources/views/actions/show.blade.php
+++ b/resources/views/actions/show.blade.php
@@ -24,18 +24,39 @@
@endif
-