diff --git a/.env.example b/.env.example index b85385d559..af0e127eef 100644 --- a/.env.example +++ b/.env.example @@ -125,6 +125,7 @@ PRIVATE_AWS_BUCKET_ROOT=null # -------------------------------------------- LOGIN_MAX_ATTEMPTS=5 LOGIN_LOCKOUT_DURATION=60 +RESET_PASSWORD_LINK_EXPIRES=900 # -------------------------------------------- # OPTIONAL: MISC diff --git a/app/Console/Commands/ResetDemoSettings.php b/app/Console/Commands/ResetDemoSettings.php index ad422a613d..80e6bc173b 100644 --- a/app/Console/Commands/ResetDemoSettings.php +++ b/app/Console/Commands/ResetDemoSettings.php @@ -64,7 +64,7 @@ class ResetDemoSettings extends Command $settings->thumbnail_max_h = '30'; $settings->locale = 'en'; $settings->version_footer = 'on'; - $settings->support_footer = 'on'; + $settings->support_footer = null; $settings->saml_enabled = '0'; $settings->saml_sp_entitiyid = '0'; $settings->saml_sp_acs_url = null; diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index a130eaa1db..63ed6ccfc3 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -67,7 +67,9 @@ class UsersController extends Controller if (($request->filled('deleted')) && ($request->input('deleted')=='true')) { - $users = $users->GetDeleted(); + $users = $users->onlyTrashed(); + } elseif (($request->filled('all')) && ($request->input('deleted')=='true')) { + $users = $users->withTrashed(); } if ($request->filled('company_id')) { diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php index 6c33c999cd..d54ca4ed09 100644 --- a/app/Http/Controllers/Auth/ForgotPasswordController.php +++ b/app/Http/Controllers/Auth/ForgotPasswordController.php @@ -5,7 +5,6 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; use Illuminate\Foundation\Auth\SendsPasswordResetEmails; use Illuminate\Http\Request; -use Illuminate\Support\Facades\Validator; class ForgotPasswordController extends Controller { @@ -60,7 +59,7 @@ class ForgotPasswordController extends Controller */ $request->validate([ - 'email' => ['required', 'email', 'max:255'], + 'username' => ['required', 'max:255'], ]); @@ -74,16 +73,16 @@ class ForgotPasswordController extends Controller */ $response = $this->broker()->sendResetLink( array_merge( - $request->only('email'), + $request->only('username'), ['activated' => '1'], ['ldap_import' => '0'] ) ); if ($response === \Password::RESET_LINK_SENT) { - \Log::info('Password reset attempt: User '.$request->input('email').' found, password reset sent'); + \Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent'); } else { - \Log::info('Password reset attempt: User '.$request->input('email').' not found or user is inactive'); + \Log::info('Password reset attempt: User matching username '.$request->input('username').' NOT FOUND or user is inactive'); } diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php index 76f8db430a..92b86fd737 100644 --- a/app/Http/Controllers/Auth/ResetPasswordController.php +++ b/app/Http/Controllers/Auth/ResetPasswordController.php @@ -3,9 +3,13 @@ namespace App\Http\Controllers\Auth; use App\Http\Controllers\Controller; +use App\Http\Requests\SaveUserRequest; use App\Models\Setting; +use App\Models\User; use Illuminate\Foundation\Auth\ResetsPasswords; use Illuminate\Http\Request; +use Illuminate\Validation\Rule; +use Illuminate\Validation\Validator; class ResetPasswordController extends Controller { @@ -29,6 +33,8 @@ class ResetPasswordController extends Controller */ protected $redirectTo = '/'; + protected $username = 'username'; + /** * Create a new controller instance. * @@ -44,7 +50,7 @@ class ResetPasswordController extends Controller return [ 'token' => 'required', 'username' => 'required', - 'password' => 'required|confirmed|'.Setting::passwordComplexityRulesSaving('update'), + 'password' => 'confirmed|'.Setting::passwordComplexityRulesSaving('store'), ]; } @@ -55,7 +61,7 @@ class ResetPasswordController extends Controller 'username', 'password', 'password_confirmation', 'token' ); } - + public function showResetForm(Request $request, $token = null) { @@ -67,11 +73,48 @@ class ResetPasswordController extends Controller ); } + + public function reset(Request $request) + { + + $messages = [ + 'password.not_in' => trans('validation.disallow_same_pwd_as_user_fields'), + ]; + + $request->validate($this->rules(), $request->all(), $this->validationErrorMessages()); + + // Check to see if the user even exists + $user = User::where('username', '=', $request->input('username'))->first(); + + $broker = $this->broker(); + if (strpos(Setting::passwordComplexityRulesSaving('store'), 'disallow_same_pwd_as_user_fields') !== FALSE) { + $request->validate( + [ + 'password' => 'required|notIn:["'.$user->email.'","'.$user->username.'","'.$user->first_name.'","'.$user->last_name.'"' + ], $messages); + + } + + + $response = $broker->reset( + $this->credentials($request), function ($user, $password) { + $this->resetPassword($user, $password); + } + ); + + return $response == \Password::PASSWORD_RESET + ? $this->sendResetResponse($request, $response) + : $this->sendResetFailedResponse($request, $response); + } + + protected function sendResetFailedResponse(Request $request, $response) { return redirect()->back() ->withInput(['username'=> $request->input('username')]) - ->withErrors(['username' => trans($response)]); + ->withErrors(['username' => trans($response), 'password' => trans($response)]); } -} \ No newline at end of file + + +} diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 787037cfb1..35ede27cb5 100755 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -156,6 +156,28 @@ class ProfileController extends Controller if (!Hash::check($request->input('current_password'), $user->password)) { $validator->errors()->add('current_password', trans('validation.hashed_pass')); } + + // This checks to make sure that the user's password isn't the same as their username, + // email address, first name or last name (see https://github.com/snipe/snipe-it/issues/8661) + // While this is handled via SaveUserRequest form request in other places, we have to do this manually + // here because we don't have the username, etc form fields available in the profile password change + // form. + + // There may be a more elegant way to do this in the future. + + // First let's see if that option is enabled in the settings + if (strpos(Setting::passwordComplexityRulesSaving('store'), 'disallow_same_pwd_as_user_fields') !== FALSE) { + if (($request->input('password') == $user->username) || + ($request->input('password') == $user->email) || + ($request->input('password') == $user->first_name) || + ($request->input('password') == $user->last_name)) + { + $validator->errors()->add('password', trans('validation.disallow_same_pwd_as_user_fields')); + } + } + + + }); diff --git a/app/Http/Controllers/ViewAssetsController.php b/app/Http/Controllers/ViewAssetsController.php index 37bc95b590..1525e73dbb 100755 --- a/app/Http/Controllers/ViewAssetsController.php +++ b/app/Http/Controllers/ViewAssetsController.php @@ -10,8 +10,7 @@ use App\Models\User; use App\Notifications\RequestAssetCancelation; use App\Notifications\RequestAssetNotification; use Illuminate\Support\Facades\Auth; -use Illuminate\Support\Facades\Input; -use Redirect; +use Illuminate\Http\Request; /** * This controller handles all actions related to the ability for users diff --git a/app/Http/Transformers/UsersTransformer.php b/app/Http/Transformers/UsersTransformer.php index 5f844d5883..9a8b0a098f 100644 --- a/app/Http/Transformers/UsersTransformer.php +++ b/app/Http/Transformers/UsersTransformer.php @@ -54,7 +54,6 @@ class UsersTransformer 'activated' => ($user->activated =='1') ? true : false, 'two_factor_activated' => ($user->two_factor_active()) ? true : false, 'two_factor_enrolled' => ($user->two_factor_active_and_enrolled()) ? true : false, - 'assets_count' => (int) $user->assets_count, 'licenses_count' => (int) $user->licenses_count, 'accessories_count' => (int) $user->accessories_count, @@ -63,6 +62,7 @@ class UsersTransformer 'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($user->updated_at, 'datetime'), 'last_login' => Helper::getFormattedDateObject($user->last_login, 'datetime'), + 'deleted_at' => ($user->deleted_at) ? Helper::getFormattedDateObject($user->deleted_at, 'datetime') : null, ]; $permissions_array['available_actions'] = [ diff --git a/app/Models/User.php b/app/Models/User.php index d5868ce600..cbf887adb7 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -26,10 +26,13 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo use UniqueUndeletedTrait; use Notifiable; use Presentable; + use Searchable; + protected $dates = ['deleted_at']; protected $hidden = ['password','remember_token','permissions','reset_password_code','persist_code']; protected $table = 'users'; protected $injectUniqueIdentifier = true; + protected $fillable = [ 'activated', 'address', @@ -78,7 +81,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'location_id' => 'exists:locations,id|nullable', ]; - use Searchable; /** * The attributes that should be included when searching the model. @@ -107,7 +109,8 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'groups' => ['name'], 'company' => ['name'], 'manager' => ['first_name', 'last_name', 'username'] - ]; + ]; + /** * Check user permissions diff --git a/app/Notifications/RequestAssetNotification.php b/app/Notifications/RequestAssetNotification.php index 8c0c7d8505..b78f5eeb93 100644 --- a/app/Notifications/RequestAssetNotification.php +++ b/app/Notifications/RequestAssetNotification.php @@ -62,11 +62,9 @@ class RequestAssetNotification extends Notification $notifyBy = []; if (Setting::getSettings()->slack_endpoint!='') { - \Log::debug('use slack'); $notifyBy[] = 'slack'; } - $notifyBy[] = 'mail'; return $notifyBy; diff --git a/app/Providers/ValidationServiceProvider.php b/app/Providers/ValidationServiceProvider.php index b8e028226e..2a675fa8d1 100644 --- a/app/Providers/ValidationServiceProvider.php +++ b/app/Providers/ValidationServiceProvider.php @@ -91,6 +91,42 @@ class ValidationServiceProvider extends ServiceProvider }); + // This ONLY works for create/update user forms, since the Update Profile Password form doesn't + // include any of these additional validator fields + Validator::extend('disallow_same_pwd_as_user_fields', function ($attribute, $value, $parameters, $validator) { + + $data = $validator->getData(); + + if (array_key_exists("username", $data)) { + if ($data['username'] == $data['password']) { + return false; + } + } + + if (array_key_exists("email", $data)) { + if ($data['email'] == $data['password']) { + return false; + } + } + + if (array_key_exists("first_name", $data)) { + if ($data['first_name'] == $data['password']) { + return false; + } + } + + if (array_key_exists("last_name", $data)) { + if ($data['last_name'] == $data['password']) { + return false; + } + } + + + return true; + + + }); + Validator::extend('letters', function ($attribute, $value, $parameters) { return preg_match('/\pL/', $value); }); diff --git a/config/auth.php b/config/auth.php index d8a161f9f4..41ce176d16 100644 --- a/config/auth.php +++ b/config/auth.php @@ -102,7 +102,7 @@ return [ 'provider' => 'users', 'email' => 'auth.emails.password', 'table' => 'password_resets', - 'expire' => env('LOGIN_LOCKOUT_DURATION', 60), + 'expire' => env('RESET_PASSWORD_LINK_EXPIRES', 900), 'throttle' => env('LOGIN_MAX_ATTEMPTS', 60), ], ], @@ -120,4 +120,5 @@ return [ 'password_timeout' => 10800, + ]; diff --git a/public/css/signature-pad.min.css b/public/css/signature-pad.min.css new file mode 100755 index 0000000000..218b9c2365 Binary files /dev/null and b/public/css/signature-pad.min.css differ diff --git a/resources/lang/en-GB/admin/settings/general.php b/resources/lang/en-GB/admin/settings/general.php index 9ee50e1769..78496051c2 100644 --- a/resources/lang/en-GB/admin/settings/general.php +++ b/resources/lang/en-GB/admin/settings/general.php @@ -101,7 +101,7 @@ return array( 'pwd_secure_complexity' => 'Password Complexity', 'pwd_secure_complexity_help' => 'Select whichever password complexity rules you wish to enforce.', 'pwd_secure_min' => 'Password minimum characters', - 'pwd_secure_min_help' => 'Minimum permitted value is 5', + 'pwd_secure_min_help' => 'Minimum permitted value is 8', 'pwd_secure_uncommon' => 'Prevent common passwords', 'pwd_secure_uncommon_help' => 'This will disallow users from using common passwords from the top 10,000 passwords reported in breaches.', 'qr_help' => 'Enable QR Codes first to set this', diff --git a/resources/lang/en/admin/settings/general.php b/resources/lang/en/admin/settings/general.php index d9a62aedbb..82be53c897 100644 --- a/resources/lang/en/admin/settings/general.php +++ b/resources/lang/en/admin/settings/general.php @@ -113,7 +113,7 @@ return array( 'pwd_secure_complexity' => 'Password Complexity', 'pwd_secure_complexity_help' => 'Select whichever password complexity rules you wish to enforce.', 'pwd_secure_min' => 'Password minimum characters', - 'pwd_secure_min_help' => 'Minimum permitted value is 5', + 'pwd_secure_min_help' => 'Minimum permitted value is 8', 'pwd_secure_uncommon' => 'Prevent common passwords', 'pwd_secure_uncommon_help' => 'This will disallow users from using common passwords from the top 10,000 passwords reported in breaches.', 'qr_help' => 'Enable QR Codes first to set this', diff --git a/resources/lang/en/validation.php b/resources/lang/en/validation.php index 31ba3761e8..7e584d67ea 100644 --- a/resources/lang/en/validation.php +++ b/resources/lang/en/validation.php @@ -99,6 +99,7 @@ return array( 'url' => 'The :attribute format is invalid.', "unique_undeleted" => "The :attribute must be unique.", "import_field_empty" => "The value of the Import Field shouldn't be empty", + "disallow_same_pwd_as_user_fields" => 'The password cannot be the same as the username, email address, or first or last name.', /* |-------------------------------------------------------------------------- diff --git a/resources/lang/is/admin/settings/general.php b/resources/lang/is/admin/settings/general.php index 252589705d..f40e9aea57 100644 --- a/resources/lang/is/admin/settings/general.php +++ b/resources/lang/is/admin/settings/general.php @@ -101,7 +101,7 @@ return array( 'pwd_secure_complexity' => 'Password Complexity', 'pwd_secure_complexity_help' => 'Select whichever password complexity rules you wish to enforce.', 'pwd_secure_min' => 'Password minimum characters', - 'pwd_secure_min_help' => 'Minimum permitted value is 5', + 'pwd_secure_min_help' => 'Minimum permitted value is 8', 'pwd_secure_uncommon' => 'Prevent common passwords', 'pwd_secure_uncommon_help' => 'This will disallow users from using common passwords from the top 10,000 passwords reported in breaches.', 'qr_help' => 'Enable QR Codes first to set this', diff --git a/resources/lang/iu/admin/settings/general.php b/resources/lang/iu/admin/settings/general.php index 252589705d..f40e9aea57 100644 --- a/resources/lang/iu/admin/settings/general.php +++ b/resources/lang/iu/admin/settings/general.php @@ -101,7 +101,7 @@ return array( 'pwd_secure_complexity' => 'Password Complexity', 'pwd_secure_complexity_help' => 'Select whichever password complexity rules you wish to enforce.', 'pwd_secure_min' => 'Password minimum characters', - 'pwd_secure_min_help' => 'Minimum permitted value is 5', + 'pwd_secure_min_help' => 'Minimum permitted value is 8', 'pwd_secure_uncommon' => 'Prevent common passwords', 'pwd_secure_uncommon_help' => 'This will disallow users from using common passwords from the top 10,000 passwords reported in breaches.', 'qr_help' => 'Enable QR Codes first to set this', diff --git a/resources/lang/sr-CS/admin/settings/general.php b/resources/lang/sr-CS/admin/settings/general.php index fe7e1335c8..3fe2190dc0 100644 --- a/resources/lang/sr-CS/admin/settings/general.php +++ b/resources/lang/sr-CS/admin/settings/general.php @@ -101,7 +101,7 @@ return array( 'pwd_secure_complexity' => 'Password Complexity', 'pwd_secure_complexity_help' => 'Select whichever password complexity rules you wish to enforce.', 'pwd_secure_min' => 'Password minimum characters', - 'pwd_secure_min_help' => 'Minimum permitted value is 5', + 'pwd_secure_min_help' => 'Minimum permitted value is 8', 'pwd_secure_uncommon' => 'Prevent common passwords', 'pwd_secure_uncommon_help' => 'This will disallow users from using common passwords from the top 10,000 passwords reported in breaches.', 'qr_help' => 'Enable QR Codes first to set this', diff --git a/resources/lang/tl/admin/settings/general.php b/resources/lang/tl/admin/settings/general.php index debefb1fb6..9298581291 100644 --- a/resources/lang/tl/admin/settings/general.php +++ b/resources/lang/tl/admin/settings/general.php @@ -101,7 +101,7 @@ return array( 'pwd_secure_complexity' => 'Password Complexity', 'pwd_secure_complexity_help' => 'Select whichever password complexity rules you wish to enforce.', 'pwd_secure_min' => 'Password minimum characters', - 'pwd_secure_min_help' => 'Minimum permitted value is 5', + 'pwd_secure_min_help' => 'Minimum permitted value is 8', 'pwd_secure_uncommon' => 'Prevent common passwords', 'pwd_secure_uncommon_help' => 'This will disallow users from using common passwords from the top 10,000 passwords reported in breaches.', 'qr_help' => 'Enable QR Codes first to set this', diff --git a/resources/lang/uk/admin/settings/general.php b/resources/lang/uk/admin/settings/general.php index 9ffacc1c53..abe32ae08c 100644 --- a/resources/lang/uk/admin/settings/general.php +++ b/resources/lang/uk/admin/settings/general.php @@ -103,7 +103,7 @@ return array( 'pwd_secure_complexity' => 'Складність пароля', 'pwd_secure_complexity_help' => 'Select whichever password complexity rules you wish to enforce.', 'pwd_secure_min' => 'Мінімальна кількість символів в паролі', - 'pwd_secure_min_help' => 'Minimum permitted value is 5', + 'pwd_secure_min_help' => 'Minimum permitted value is 8', 'pwd_secure_uncommon' => 'Prevent common passwords', 'pwd_secure_uncommon_help' => 'This will disallow users from using common passwords from the top 10,000 passwords reported in breaches.', 'qr_help' => 'Enable QR Codes first to set this', diff --git a/resources/lang/ur-PK/admin/settings/general.php b/resources/lang/ur-PK/admin/settings/general.php index 252589705d..f40e9aea57 100644 --- a/resources/lang/ur-PK/admin/settings/general.php +++ b/resources/lang/ur-PK/admin/settings/general.php @@ -101,7 +101,7 @@ return array( 'pwd_secure_complexity' => 'Password Complexity', 'pwd_secure_complexity_help' => 'Select whichever password complexity rules you wish to enforce.', 'pwd_secure_min' => 'Password minimum characters', - 'pwd_secure_min_help' => 'Minimum permitted value is 5', + 'pwd_secure_min_help' => 'Minimum permitted value is 8', 'pwd_secure_uncommon' => 'Prevent common passwords', 'pwd_secure_uncommon_help' => 'This will disallow users from using common passwords from the top 10,000 passwords reported in breaches.', 'qr_help' => 'Enable QR Codes first to set this', diff --git a/resources/views/account/accept-asset.blade.php b/resources/views/account/accept-asset.blade.php index a695a5e61b..780b9408e8 100644 --- a/resources/views/account/accept-asset.blade.php +++ b/resources/views/account/accept-asset.blade.php @@ -11,7 +11,7 @@ @section('content') - +