Skip to content

Commit 85c9f3f

Browse files
committed
FOUR-12572 Password Policy Configuration - Password expiration
1 parent 2c7f411 commit 85c9f3f

10 files changed

Lines changed: 69 additions & 4 deletions

File tree

‎ProcessMaker/Http/Controllers/Api/ChangePasswordController.php‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace ProcessMaker\Http\Controllers\Api;
44

5+
use Carbon\Carbon;
56
use Exception;
67
use Illuminate\Http\Request;
78
use Illuminate\Support\Facades\Auth;
@@ -35,6 +36,10 @@ public function update(Request $request)
3536

3637
$user->setAttribute('password', Hash::make($request->json('password')));
3738
$user->setAttribute('force_change_password', 0);
39+
$user->setAttribute('password_changed_at', Carbon::now()->toDateTimeString());
40+
41+
// Remove login error message related to password expired if exists
42+
session()->forget('login-error');
3843

3944
try {
4045
$user = $user->save();

‎ProcessMaker/Http/Controllers/Api/UserController.php‎

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace ProcessMaker\Http\Controllers\Api;
44

5+
use Carbon\Carbon;
56
use Illuminate\Auth\Access\AuthorizationException;
67
use Illuminate\Http\Request;
78
use Illuminate\Support\Facades\Auth;
@@ -167,6 +168,10 @@ public function store(Request $request)
167168

168169
if (isset($fields['password'])) {
169170
$fields['password'] = Hash::make($fields['password']);
171+
$fields['password_changed_at'] = Carbon::now()->toDateTimeString();
172+
173+
// Remove login error message related to password expired if exists
174+
session()->forget('login-error');
170175
}
171176

172177
$user->fill($fields);
@@ -301,6 +306,10 @@ public function update(User $user, Request $request)
301306
$fields = $request->json()->all();
302307
if (isset($fields['password'])) {
303308
$fields['password'] = Hash::make($fields['password']);
309+
$fields['password_changed_at'] = Carbon::now()->toDateTimeString();
310+
311+
// Remove login error message related to password expired if exists
312+
session()->forget('login-error');
304313
}
305314
$original = $user->getOriginal();
306315
$user->fill($fields);

‎ProcessMaker/Http/Middleware/VerifyChangePasswordNeeded.php‎

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22

33
namespace ProcessMaker\Http\Middleware;
44

5+
use Carbon\Carbon;
56
use Closure;
67
use Illuminate\Support\Facades\Auth;
78

@@ -20,11 +21,28 @@ public function handle($request, Closure $next)
2021
return redirect()->route('password.change');
2122
}
2223

24+
if ($this->checkPasswordExpiration()) {
25+
// Set the error message
26+
session()->put('login-error', _('Your password has expired.'));
27+
28+
// Redirect to change password screen
29+
return redirect()->route('password.change');
30+
}
31+
2332
return $next($request);
2433
}
2534

2635
public function checkForForceChangePassword()
2736
{
2837
return Auth::user() && Auth::user()->force_change_password;
2938
}
39+
40+
public function checkPasswordExpiration()
41+
{
42+
$validationRequired = config('password-policies.expiration_days') &&
43+
Auth::user() && Auth::user()->password_changed_at;
44+
45+
return $validationRequired &&
46+
(Carbon::now()->diffInDays(Auth::user()->password_changed_at) >= config('password-policies.expiration_days'));
47+
}
3048
}

‎ProcessMaker/Models/User.php‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -122,6 +122,7 @@ class User extends Authenticatable implements HasMedia
122122
'manager_id',
123123
'schedule',
124124
'force_change_password',
125+
'password_changed_at',
125126
];
126127

127128
protected $appends = [

‎config/password-policies.php‎

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,6 @@
66
'numbers' => env('PASSWORD_POLICY_NUMBERS', true),
77
'uppercase' => env('PASSWORD_POLICY_UPPERCASE', true),
88
'special' => env('PASSWORD_POLICY_SPECIAL', true),
9-
//'expiration_days' => env('PASSWORD_POLICY_EXPIRATION_DAYS', 0), // 0 never expires
9+
'expiration_days' => env('PASSWORD_POLICY_EXPIRATION_DAYS', null),
1010
'login_attempts' => env('PASSWORD_POLICY_LOGIN_ATTEMPTS', 5),
1111
];
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
<?php
2+
3+
use Illuminate\Database\Migrations\Migration;
4+
use Illuminate\Database\Schema\Blueprint;
5+
use Illuminate\Support\Facades\Schema;
6+
7+
return new class extends Migration
8+
{
9+
/**
10+
* Run the migrations.
11+
*/
12+
public function up(): void
13+
{
14+
Schema::table('users', function (Blueprint $table) {
15+
$table->timestamp('password_changed_at')->nullable();
16+
});
17+
}
18+
19+
/**
20+
* Reverse the migrations.
21+
*/
22+
public function down(): void
23+
{
24+
Schema::table('users', function (Blueprint $table) {
25+
$table->dropColumn('password_changed_at');
26+
});
27+
}
28+
};

‎resources/lang/de.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1801,5 +1801,6 @@
18011801
"This environment already contains an older version of the {{ item }} named '{{ name }}.'": "Diese Umgebung enthält bereits eine ältere Version des {{ item }} namens '{{ name }}'.",
18021802
"This environment already contains the same version of the {{ item }} named '{{ name }}.'": "Diese Umgebung enthält bereits die gleiche Version des {{ item }} namens '{{ name }}'.",
18031803
"Visit our Gallery for more Templates": "Besuchen Sie unsere Galerie für mehr Vorlagen",
1804-
"Start a new process from a blank canvas, a text description, or a preset template.": "Starten Sie einen neuen Prozess von einer leeren Leinwand, einer Textbeschreibung oder einer voreingestellten Vorlage."
1804+
"Start a new process from a blank canvas, a text description, or a preset template.": "Starten Sie einen neuen Prozess von einer leeren Leinwand, einer Textbeschreibung oder einer voreingestellten Vorlage.",
1805+
"Your password has expired.": "Your password has expired."
18051806
}

‎resources/lang/en.json‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1870,6 +1870,7 @@
18701870
"Your account has been timed out for security.": "Your account has been timed out for security.",
18711871
"Your password has been reset!": "Your password has been reset!",
18721872
"Your password has been updated.": "Your password has been updated.",
1873+
"Your password has expired.": "Your password has expired.",
18731874
"Your PMQL contains invalid syntax.": "Your PMQL contains invalid syntax.",
18741875
"Your PMQL search could not be completed.": "Your PMQL search could not be completed.",
18751876
"Your profile was saved.": "Your profile was saved.",

‎resources/lang/es.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1802,5 +1802,6 @@
18021802
"This environment already contains an older version of the {{ item }} named '{{ name }}.'": "Este entorno ya contiene una versión más antigua del {{ item }} llamado '{{ name }}'.",
18031803
"This environment already contains the same version of the {{ item }} named '{{ name }}.'": "Este entorno ya contiene la misma versión del {{ item }} llamado '{{ name }}'.",
18041804
"Visit our Gallery for more Templates": "Visita nuestra Galería para más Plantillas",
1805-
"Start a new process from a blank canvas, a text description, or a preset template.": "Inicie un nuevo proceso desde un lienzo en blanco, una descripción de texto o una plantilla preestablecida."
1805+
"Start a new process from a blank canvas, a text description, or a preset template.": "Inicie un nuevo proceso desde un lienzo en blanco, una descripción de texto o una plantilla preestablecida.",
1806+
"Your password has expired.": "Tu contraseña ha expirado."
18061807
}

‎resources/lang/fr.json‎

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1801,5 +1801,6 @@
18011801
"This environment already contains an older version of the {{ item }} named '{{ name }}.'": "Cet environnement contient déjà une version plus ancienne de {{ item }} nommé '{{ name }}'.",
18021802
"This environment already contains the same version of the {{ item }} named '{{ name }}.'": "Cet environnement contient déjà la même version de l'{{ item }} nommé '{{ name }}'.",
18031803
"Visit our Gallery for more Templates": "Visitez notre Galerie pour plus de Modèles",
1804-
"Start a new process from a blank canvas, a text description, or a preset template.": "Démarrez un nouveau processus à partir d'une toile vierge, d'une description textuelle ou d'un modèle prédéfini."
1804+
"Start a new process from a blank canvas, a text description, or a preset template.": "Démarrez un nouveau processus à partir d'une toile vierge, d'une description textuelle ou d'un modèle prédéfini.",
1805+
"Your password has expired.": "Your password has expired."
18051806
}

0 commit comments

Comments
 (0)