mirror of
https://github.com/snipe/snipe-it.git
synced 2024-11-09 23:24:06 -08:00
ADDED: Password rules for complexity, min length, rejecting common passwords
This commit is contained in:
parent
1d7e243d0a
commit
9bda62d295
|
@ -8,6 +8,7 @@ use App\Http\Transformers\UsersTransformer;
|
|||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Requests\SaveUserRequest;
|
||||
|
||||
class UsersController extends Controller
|
||||
{
|
||||
|
@ -102,7 +103,7 @@ class UsersController extends Controller
|
|||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(Request $request)
|
||||
public function store(SaveUserRequest $request)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$user = new User;
|
||||
|
@ -139,7 +140,7 @@ class UsersController extends Controller
|
|||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
public function update(SaveUserRequest $request, $id)
|
||||
{
|
||||
$this->authorize('edit', User::class);
|
||||
$user = User::findOrFail($id);
|
||||
|
|
|
@ -462,6 +462,15 @@ class SettingsController extends Controller
|
|||
|
||||
}
|
||||
|
||||
$setting->pwd_secure_uncommon = (int) $request->input('pwd_secure_uncommon');
|
||||
$setting->pwd_secure_min = (int) $request->input('pwd_secure_min');
|
||||
$setting->pwd_secure_complexity = '';
|
||||
|
||||
if ($request->has('pwd_secure_complexity')) {
|
||||
$setting->pwd_secure_complexity = implode('|', $request->input('pwd_secure_complexity'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($setting->save()) {
|
||||
return redirect()->route('settings.index')
|
||||
|
|
|
@ -12,9 +12,7 @@ use App\Models\Company;
|
|||
use App\Models\Location;
|
||||
use App\Models\License;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Http\Requests\SaveUserRequest;
|
||||
use App\Http\Requests\UpdateUserRequest;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use App\Models\User;
|
||||
use App\Models\Ldap;
|
||||
|
@ -23,7 +21,6 @@ use Config;
|
|||
use Crypt;
|
||||
use DB;
|
||||
use HTML;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Input;
|
||||
use Lang;
|
||||
use League\Csv\Reader;
|
||||
|
@ -169,7 +166,7 @@ class UsersController extends Controller
|
|||
* @since [v1.8]
|
||||
* @return string JSON
|
||||
*/
|
||||
public function apiStore(Request $request)
|
||||
public function apiStore(SaveUserRequest $request)
|
||||
{
|
||||
$this->authorize('create', User::class);
|
||||
|
||||
|
@ -270,7 +267,7 @@ class UsersController extends Controller
|
|||
* @param int $id
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(UpdateUserRequest $request, $id = null)
|
||||
public function update(SaveUserRequest $request, $id = null)
|
||||
{
|
||||
// We need to reverse the UI specific logic for our
|
||||
// permissions here before we update the user.
|
||||
|
@ -309,14 +306,11 @@ class UsersController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
// Do we want to update the user password?
|
||||
if ($request->has('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
if ($request->has('username')) {
|
||||
$user->username = e($request->input('username'));
|
||||
$user->username = $request->input('username');
|
||||
}
|
||||
$user->email = e($request->input('email'));
|
||||
$user->email = $request->input('email');
|
||||
|
||||
|
||||
// Update the user
|
||||
|
@ -334,6 +328,12 @@ class UsersController extends Controller
|
|||
$user->notes = $request->input('notes');
|
||||
$user->department_id = $request->input('department_id', null);
|
||||
|
||||
|
||||
// Do we want to update the user password?
|
||||
if ($request->has('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
// Strip out the superuser permission if the user isn't a superadmin
|
||||
$permissions_array = $request->input('permission');
|
||||
|
||||
|
|
|
@ -3,6 +3,7 @@
|
|||
namespace App\Http\Requests;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
use App\Models\Setting;
|
||||
|
||||
class SaveUserRequest extends Request
|
||||
{
|
||||
|
@ -23,12 +24,35 @@ class SaveUserRequest extends Request
|
|||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'first_name' => 'required|string|min:1',
|
||||
'email' => 'email',
|
||||
'password' => 'required|min:6',
|
||||
'password_confirm' => 'sometimes|required_with:password',
|
||||
'username' => 'required|string|min:2|unique:users,username,NULL,deleted_at',
|
||||
];
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
$rules = [];
|
||||
$security_rules = '';
|
||||
|
||||
$rules['first_name'] = 'required|string|min:1';
|
||||
$rules['username'] = 'required|string|min:1|unique_undeleted';
|
||||
|
||||
// Check if they have uncommon password enforcement selected in settings
|
||||
if ($settings->pwd_secure_uncommon == 1) {
|
||||
$security_rules .= '|dumbpwd';
|
||||
}
|
||||
|
||||
// Check for any secure password complexity rules that may have been selected
|
||||
if ($settings->pwd_secure_complexity!='') {
|
||||
$security_rules .= '|'.$settings->pwd_secure_complexity;
|
||||
}
|
||||
|
||||
|
||||
if ((\Route::currentRouteName()=='api.users.update') || (\Route::currentRouteName()=='users.update')) {
|
||||
$rules['password'] = 'nullable|min:'.$settings->pwd_secure_min.$security_rules;
|
||||
} else {
|
||||
$rules['password'] = 'required|min:'.$settings->pwd_secure_min.$security_rules;
|
||||
}
|
||||
|
||||
$rules['password_confirm'] = 'sometimes|required_with:password';
|
||||
|
||||
return $rules;
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,32 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Http\Requests\Request;
|
||||
|
||||
class UpdateUserRequest extends Request
|
||||
{
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
* @return bool
|
||||
*/
|
||||
public function authorize()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array
|
||||
*/
|
||||
public function rules()
|
||||
{
|
||||
return [
|
||||
'first_name' => 'required|string|min:1',
|
||||
'email' => 'email',
|
||||
'password_confirm' => 'sometimes|required_with:password',
|
||||
];
|
||||
}
|
||||
}
|
|
@ -44,6 +44,7 @@ class Setting extends Model
|
|||
"ldap_auth_filter_query" => 'sometimes|required_if:ldap_enabled,1|nullable',
|
||||
"ldap_version" => 'sometimes|required_if:ldap_enabled,1|nullable',
|
||||
"thumbnail_max_h" => 'numeric|max:500|min:25',
|
||||
"pwd_secure_min" => "numeric|required|min:5",
|
||||
];
|
||||
|
||||
protected $fillable = ['site_name','email_domain','email_format','username_format'];
|
||||
|
@ -158,4 +159,34 @@ class Setting extends Model
|
|||
// In the future this may want to be adapted for individual notifications.
|
||||
return $this->slack_endpoint;
|
||||
}
|
||||
|
||||
public function passwordComplexityStringToArray()
|
||||
{
|
||||
|
||||
$this->pwd_secure_complexity = 'numbers|letters|case_diff';
|
||||
$complexity_array_split = array();
|
||||
$complexity_array = array();
|
||||
|
||||
if (($this->pwd_secure_complexity) && ($this->pwd_secure_complexity!='')) {
|
||||
$complexity_array_split = explode('|',$this->pwd_secure_complexity);
|
||||
}
|
||||
|
||||
for ($x = 0; $x < count($complexity_array_split); $x++) {
|
||||
$complexity_array[$complexity_array_split[$x]] = 1;
|
||||
}
|
||||
|
||||
return $complexity_array;
|
||||
|
||||
}
|
||||
|
||||
public static function passwordComplexityToFormattedString($array) {
|
||||
// $array = array();
|
||||
$string = '';
|
||||
for ($x = 0; $x <= count($array); $x++) {
|
||||
$string .= '|'.$array[$x];
|
||||
}
|
||||
|
||||
return $string;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -51,9 +51,9 @@ class User extends SnipeModel implements AuthenticatableContract, CanResetPasswo
|
|||
protected $rules = [
|
||||
'first_name' => 'required|string|min:1',
|
||||
'username' => 'required|string|min:1|unique_undeleted',
|
||||
'email' => 'email',
|
||||
'email' => 'email|nullable',
|
||||
'password' => 'required|min:6',
|
||||
'locale' => 'max:10'
|
||||
'locale' => 'max:10|nullable'
|
||||
];
|
||||
|
||||
|
||||
|
|
|
@ -24,8 +24,10 @@
|
|||
"neitanod/forceutf8": "^2.0",
|
||||
"patchwork/utf8": "~1.2",
|
||||
"pragmarx/google2fa": "^1.0",
|
||||
"schuppo/password-strength": "~1.5",
|
||||
"spatie/laravel-backup": "^3.0.0",
|
||||
"tecnickcom/tc-lib-barcode": "^1.15",
|
||||
"unicodeveloper/laravel-password": "^1.0",
|
||||
"watson/validating": "^3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
|
|
107
composer.lock
generated
107
composer.lock
generated
|
@ -4,7 +4,7 @@
|
|||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#composer-lock-the-lock-file",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "dd84e08e5e7eca2c1e032c6357ca2500",
|
||||
"content-hash": "da7d8408e0c3434a6131340252d2d228",
|
||||
"packages": [
|
||||
{
|
||||
"name": "aws/aws-sdk-php",
|
||||
|
@ -2888,6 +2888,56 @@
|
|||
],
|
||||
"time": "2017-08-04T13:39:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "schuppo/password-strength",
|
||||
"version": "v1.9",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/schuppo/PasswordStrengthPackage.git",
|
||||
"reference": "184d65517eb438651b491b116df8895238005b79"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/schuppo/PasswordStrengthPackage/zipball/184d65517eb438651b491b116df8895238005b79",
|
||||
"reference": "184d65517eb438651b491b116df8895238005b79",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/support": "~5.0",
|
||||
"illuminate/translation": "^5.1",
|
||||
"php": ">=5.4.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"illuminate/validation": "~5.0",
|
||||
"phpunit/phpunit": "^4.8"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-0": {
|
||||
"Schuppo\\PasswordStrength": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Oliver Schupp",
|
||||
"email": "oliver.schupp@yahoo.de"
|
||||
}
|
||||
],
|
||||
"description": "This package provides a validator for ensuring strong passwords in Laravel 4 applications.",
|
||||
"keywords": [
|
||||
"laravel",
|
||||
"laravel 5",
|
||||
"laravel5",
|
||||
"password",
|
||||
"password strength",
|
||||
"validation"
|
||||
],
|
||||
"time": "2016-10-05T09:57:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "spatie/db-dumper",
|
||||
"version": "1.5.1",
|
||||
|
@ -4171,6 +4221,61 @@
|
|||
"homepage": "https://github.com/tijsverkoyen/CssToInlineStyles",
|
||||
"time": "2016-09-20T12:50:39+00:00"
|
||||
},
|
||||
{
|
||||
"name": "unicodeveloper/laravel-password",
|
||||
"version": "1.0.2",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/unicodeveloper/laravel-password.git",
|
||||
"reference": "5c3bdc977c4b8065350caf2e57371b069ef6f5b4"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/unicodeveloper/laravel-password/zipball/5c3bdc977c4b8065350caf2e57371b069ef6f5b4",
|
||||
"reference": "5c3bdc977c4b8065350caf2e57371b069ef6f5b4",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": "~5.6|~7.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "~4.0||~5.0",
|
||||
"scrutinizer/ocular": "~1.1",
|
||||
"squizlabs/php_codesniffer": "~2.3"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.0-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Unicodeveloper\\DumbPassword\\": "src"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": ":Prosper Otemuyiwa",
|
||||
"email": "prosperotemuyiwa@gmail.com",
|
||||
"homepage": "http://goodheads.io",
|
||||
"role": "Developer"
|
||||
}
|
||||
],
|
||||
"description": "Protect your users from entering dumb and common passwords",
|
||||
"homepage": "https://github.com/unicodeveloper/laravel-password",
|
||||
"keywords": [
|
||||
"dumb",
|
||||
"passwords",
|
||||
"security",
|
||||
"unicodeveloper"
|
||||
],
|
||||
"time": "2017-04-27T07:35:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "vlucas/phpdotenv",
|
||||
"version": "v2.4.0",
|
||||
|
|
|
@ -220,6 +220,8 @@ return [
|
|||
PragmaRX\Google2FA\Vendor\Laravel\ServiceProvider::class,
|
||||
Laravel\Passport\PassportServiceProvider::class,
|
||||
Laravel\Tinker\TinkerServiceProvider::class,
|
||||
Unicodeveloper\DumbPassword\DumbPasswordServiceProvider::class,
|
||||
Schuppo\PasswordStrength\PasswordStrengthServiceProvider::class,
|
||||
|
||||
|
||||
/*
|
||||
|
|
|
@ -0,0 +1,36 @@
|
|||
<?php
|
||||
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
|
||||
class AddSecurePasswordOptions extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->boolean('pwd_secure_uncommon')->default('0');
|
||||
$table->string('pwd_secure_complexity')->nullable()->default(NULL);
|
||||
$table->integer('pwd_secure_min')->default('8');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->dropColumn('pwd_secure_uncommon');
|
||||
$table->dropColumn('pwd_secure_complexity');
|
||||
$table->dropColumn('pwd_secure_min');
|
||||
});
|
||||
}
|
||||
}
|
|
@ -73,6 +73,12 @@ return array(
|
|||
'php' => 'PHP Version',
|
||||
'php_gd_info' => 'You must install php-gd to display QR codes, see install instructions.',
|
||||
'php_gd_warning' => 'PHP Image Processing and GD plugin is NOT installed.',
|
||||
'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_uncommon' => 'Prevent common passwords',
|
||||
'pwd_secure_uncommon_help' => 'This will disallow users from using common passwords from the top 10,000 passwoerds reported in breaches.',
|
||||
'qr_help' => 'Enable QR Codes first to set this',
|
||||
'qr_text' => 'QR Code Text',
|
||||
'setting' => 'Setting',
|
||||
|
|
|
@ -36,6 +36,7 @@ return array(
|
|||
"exists" => "The selected :attribute is invalid.",
|
||||
"email_array" => "One or more email addresses is invalid.",
|
||||
"hashed_pass" => "Your current password is incorrect",
|
||||
'dumbpwd' => 'That password is too common.',
|
||||
"image" => "The :attribute must be an image.",
|
||||
"in" => "The selected :attribute is invalid.",
|
||||
"integer" => "The :attribute must be an integer.",
|
||||
|
|
|
@ -14,11 +14,6 @@
|
|||
{{-- Page content --}}
|
||||
@section('content')
|
||||
|
||||
<style>
|
||||
.checkbox label {
|
||||
padding-right: 40px;
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
{{ Form::open(['method' => 'POST', 'files' => true, 'class' => 'form-horizontal', 'role' => 'form' ]) }}
|
||||
|
@ -58,6 +53,68 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Min characters -->
|
||||
<div class="form-group {{ $errors->has('pwd_secure_min') ? 'error' : '' }}">
|
||||
<div class="col-md-3">
|
||||
{{ Form::label('pwd_secure_min', trans('admin/settings/general.pwd_secure_min')) }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ Form::text('pwd_secure_min', Input::old('pwd_secure_min', $setting->pwd_secure_min), array('class' => 'form-control', 'style'=>'width: 50px;')) }}
|
||||
|
||||
{!! $errors->first('pwd_secure_min', '<span class="alert-msg">:message</span>') !!}
|
||||
<p class="help-block">
|
||||
{{ trans('admin/settings/general.pwd_secure_min_help') }}
|
||||
</p>
|
||||
|
||||
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
<!-- Common Passwords -->
|
||||
<div class="form-group {{ $errors->has('pwd_secure_uncommon') ? 'error' : '' }}">
|
||||
<div class="col-md-3">
|
||||
{{ Form::label('pwd_secure_text',
|
||||
trans('admin/settings/general.pwd_secure_uncommon')) }}
|
||||
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ Form::checkbox('pwd_secure_uncommon', '1', Input::old('pwd_secure_uncommon', $setting->pwd_secure_uncommon),array('class' => 'minimal')) }}
|
||||
{{ Form::label('pwd_secure_uncommon', trans('general.yes')) }}
|
||||
{!! $errors->first('pwd_secure_uncommon', '<span class="alert-msg">:message</span>') !!}
|
||||
<p class="help-block">
|
||||
{{ trans('admin/settings/general.pwd_secure_uncommon_help') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.form-group -->
|
||||
|
||||
<!-- Common Passwords -->
|
||||
<div class="form-group">
|
||||
<div class="col-md-3">
|
||||
{{ Form::label('pwd_secure_complexity', trans('admin/settings/general.pwd_secure_complexity')) }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
|
||||
{{ Form::checkbox("pwd_secure_complexity['letters']", 'letters', Input::old('pwd_secure_uncommon', strpos($setting->pwd_secure_complexity, 'letters')!==false), array('class' => 'minimal')) }}
|
||||
Require at least one letter <br>
|
||||
|
||||
{{ Form::checkbox("pwd_secure_complexity['numbers']", 'numbers', Input::old('pwd_secure_uncommon', strpos($setting->pwd_secure_complexity, 'numbers')!==false), array('class' => 'minimal')) }}
|
||||
Require at least one number<br>
|
||||
|
||||
{{ Form::checkbox("pwd_secure_complexity['symbols']", 'symbols', Input::old('pwd_secure_uncommon', strpos($setting->pwd_secure_complexity, 'symbols')!==false), array('class' => 'minimal')) }}
|
||||
Require at least one symbol<br>
|
||||
|
||||
{{ Form::checkbox("pwd_secure_complexity['case_diff']", 'case_diff', Input::old('pwd_secure_uncommon', strpos($setting->pwd_secure_complexity, 'case_diff')!==false), array('class' => 'minimal')) }}
|
||||
Require at least one uppercase and one lowercase
|
||||
|
||||
<p class="help-block">
|
||||
{{ trans('admin/settings/general.pwd_secure_complexity_help') }}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
<!-- /.form-group -->
|
||||
|
||||
|
||||
</div>
|
||||
|
||||
|
|
Loading…
Reference in a new issue