Merge remote-tracking branch 'origin/develop'

# Conflicts:
#	app/Http/Controllers/Auth/ResetPasswordController.php
#	config/version.php
This commit is contained in:
snipe 2020-11-03 11:49:34 -08:00
commit 4d003ac97a
26 changed files with 141 additions and 32 deletions

View file

@ -125,6 +125,7 @@ PRIVATE_AWS_BUCKET_ROOT=null
# --------------------------------------------
LOGIN_MAX_ATTEMPTS=5
LOGIN_LOCKOUT_DURATION=60
RESET_PASSWORD_LINK_EXPIRES=900
# --------------------------------------------
# OPTIONAL: MISC

View file

@ -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;

View file

@ -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')) {

View file

@ -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');
}

View file

@ -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)]);
}
}
}

View file

@ -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'));
}
}
});

View file

@ -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

View file

@ -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'] = [

View file

@ -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

View file

@ -62,11 +62,9 @@ class RequestAssetNotification extends Notification
$notifyBy = [];
if (Setting::getSettings()->slack_endpoint!='') {
\Log::debug('use slack');
$notifyBy[] = 'slack';
}
$notifyBy[] = 'mail';
return $notifyBy;

View file

@ -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);
});

View file

@ -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,
];

BIN
public/css/signature-pad.min.css vendored Executable file

Binary file not shown.

View file

@ -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',

View file

@ -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',

View file

@ -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.',
/*
|--------------------------------------------------------------------------

View file

@ -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',

View file

@ -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',

View file

@ -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',

View file

@ -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',

View file

@ -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',

View file

@ -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',

View file

@ -11,7 +11,7 @@
@section('content')
<link rel="stylesheet" href="{{ mix('css/signature-pad.min.css') }}">
<link rel="stylesheet" href="{{ mix('css/build/signature-pad.min.css') }}">
<style>
.form-horizontal .control-label, .form-horizontal .radio, .form-horizontal .checkbox, .form-horizontal .radio-inline, .form-horizontal .checkbox-inline {

View file

@ -31,11 +31,11 @@
<div class="form-group{{ $errors->has('email') ? ' has-error' : '' }}">
<div class="form-group{{ $errors->has('username') ? ' has-error' : '' }}">
<div class="col-md-12">
<input type="email" class="form-control" name="email" value="{{ old('email') }}" placeholder="{{ trans('admin/users/table.email') }}" aria-label="email">
{!! $errors->first('email', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
<input type="text" class="form-control" name="username" value="{{ old('username') }}" placeholder="{{ trans('admin/users/table.username') }}" aria-label="username">
{!! $errors->first('username', '<span class="alert-msg"><i class="fa fa-times"></i> :message</span>') !!}
</div>
</div>

View file

@ -99,6 +99,10 @@
</div>
<div class="col-md-9">
{{ Form::checkbox("pwd_secure_complexity['disallow_same_pwd_as_user_fields']", 'disallow_same_pwd_as_user_fields', old('disallow_same_pwd_as_user_fields', strpos($setting->pwd_secure_complexity, 'disallow_same_pwd_as_user_fields')!==false), array('class' => 'minimal', 'aria-label'=>'pwd_secure_complexity')) }}
Password cannot be the same as first name, last name, email, or username<br>
{{ Form::checkbox("pwd_secure_complexity['letters']", 'letters', old('pwd_secure_uncommon', strpos($setting->pwd_secure_complexity, 'letters')!==false), array('class' => 'minimal', 'aria-label'=>'pwd_secure_complexity')) }}
Require at least one letter <br>

View file

@ -122,7 +122,7 @@ echo "\n";
echo "--------------------------------------------------------\n";
echo "Step 6: Updating composer dependencies:\n";
echo "(This may take an moment.)\n";
echo "(This may take a moment.)\n";
echo "--------------------------------------------------------\n\n";