From d1de34394e5be8e087e208902a2314d8db073a94 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 19 Oct 2017 10:37:30 -0700 Subject: [PATCH 01/13] Removed stupid count method --- .../Controllers/StatuslabelsController.php | 8 ++--- app/Models/Statuslabel.php | 31 +++++++++++++------ 2 files changed, 24 insertions(+), 15 deletions(-) diff --git a/app/Http/Controllers/StatuslabelsController.php b/app/Http/Controllers/StatuslabelsController.php index dc46f283b0..0b075d6e79 100755 --- a/app/Http/Controllers/StatuslabelsController.php +++ b/app/Http/Controllers/StatuslabelsController.php @@ -200,17 +200,15 @@ class StatuslabelsController extends Controller { // Check if the Statuslabel exists if (is_null($statuslabel = Statuslabel::find($statuslabelId))) { - // Redirect to the blogs management page return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.not_found')); } - - if ($statuslabel->has_assets() == 0) { + // Check that there are no assets associated + if ($statuslabel->assets()->count() == 0) { $statuslabel->delete(); - // Redirect to the statuslabels management page return redirect()->route('statuslabels.index')->with('success', trans('admin/statuslabels/message.delete.success')); } - // Redirect to the asset management page + return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.assoc_assets')); } diff --git a/app/Models/Statuslabel.php b/app/Models/Statuslabel.php index 2bb92dec41..c650521ca0 100755 --- a/app/Models/Statuslabel.php +++ b/app/Models/Statuslabel.php @@ -29,16 +29,6 @@ class Statuslabel extends SnipeModel protected $fillable = ['name', 'deployable', 'pending', 'archived']; - /** - * Show count of assets with status label - * - * @todo Remove this. It's dumb. - * @return \Illuminate\Support\Collection - */ - public function has_assets() - { - return $this->hasMany('\App\Models\Asset', 'status_id')->count(); - } /** * Get assets with associated status label @@ -64,6 +54,27 @@ class Statuslabel extends SnipeModel } } + public function scopePending() + { + return $this->where('pending', '=', 1) + ->where('archived', '=', 0) + ->where('deployable', '=', 0); + } + + public function scopeArchived() + { + return $this->where('pending', '=', 0) + ->where('archived', '=', 1) + ->where('deployable', '=', 0); + } + + public function scopeDeployable() + { + return $this->where('pending', '=', 0) + ->where('archived', '=', 0) + ->where('deployable', '=', 1); + } + public static function getStatuslabelTypesForDB($type) { From 707c4db8817da0e7948db213148fd878f1874c43 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 19 Oct 2017 10:39:08 -0700 Subject: [PATCH 02/13] API: Check there are no assets associated before allowing delete --- app/Http/Controllers/Api/StatuslabelsController.php | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/app/Http/Controllers/Api/StatuslabelsController.php b/app/Http/Controllers/Api/StatuslabelsController.php index 045d587bdf..f85ae68169 100644 --- a/app/Http/Controllers/Api/StatuslabelsController.php +++ b/app/Http/Controllers/Api/StatuslabelsController.php @@ -137,8 +137,14 @@ class StatuslabelsController extends Controller $this->authorize('delete', Statuslabel::class); $statuslabel = Statuslabel::findOrFail($id); $this->authorize('delete', $statuslabel); - $statuslabel->delete(); - return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/statuslabels/message.delete.success'))); + + // Check that there are no assets associated + if ($statuslabel->assets()->count() == 0) { + $statuslabel->delete(); + return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/statuslabels/message.delete.success'))); + } + + return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/statuslabels/message.assoc_assets'))); } From a9753eb64671064242f4a751fe2657231c5629a7 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 19 Oct 2017 10:48:15 -0700 Subject: [PATCH 03/13] Include asset count in status labels overview --- app/Http/Controllers/Api/StatuslabelsController.php | 2 +- app/Http/Transformers/StatuslabelsTransformer.php | 1 + resources/views/statuslabels/index.blade.php | 1 + 3 files changed, 3 insertions(+), 1 deletion(-) diff --git a/app/Http/Controllers/Api/StatuslabelsController.php b/app/Http/Controllers/Api/StatuslabelsController.php index f85ae68169..9860beea20 100644 --- a/app/Http/Controllers/Api/StatuslabelsController.php +++ b/app/Http/Controllers/Api/StatuslabelsController.php @@ -22,7 +22,7 @@ class StatuslabelsController extends Controller public function index(Request $request) { $this->authorize('view', Statuslabel::class); - $allowed_columns = ['id','name','created_at']; + $allowed_columns = ['id','name','created_at', 'assets_count']; $statuslabels = Statuslabel::withCount('assets'); diff --git a/app/Http/Transformers/StatuslabelsTransformer.php b/app/Http/Transformers/StatuslabelsTransformer.php index 7eb3be4f4d..fa2b4f75a5 100644 --- a/app/Http/Transformers/StatuslabelsTransformer.php +++ b/app/Http/Transformers/StatuslabelsTransformer.php @@ -26,6 +26,7 @@ class StatuslabelsTransformer 'type' => $statuslabel->getStatuslabelType(), 'color' => ($statuslabel->color) ? e($statuslabel->color) : null, 'show_in_nav' => ($statuslabel->show_in_nav=='1') ? true : false, + 'assets_count' => (int) $statuslabel->assets_count, 'notes' => e($statuslabel->notes), 'created_at' => Helper::getFormattedDateObject($statuslabel->created_at, 'datetime'), 'updated_at' => Helper::getFormattedDateObject($statuslabel->updated_at, 'datetime'), diff --git a/resources/views/statuslabels/index.blade.php b/resources/views/statuslabels/index.blade.php index bcc9466c11..2f267041ed 100755 --- a/resources/views/statuslabels/index.blade.php +++ b/resources/views/statuslabels/index.blade.php @@ -32,6 +32,7 @@ {{ trans('general.id') }} {{ trans('admin/statuslabels/table.name') }} {{ trans('admin/statuslabels/table.status_type') }} + {{ trans('general.assets') }} {{ trans('admin/statuslabels/table.color') }} {{ trans('admin/statuslabels/table.show_in_nav') }} {{ trans('table.actions') }} From 2e11a983c88066f6c3b5b796acdf3b2e594bc8b5 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 19 Oct 2017 10:52:30 -0700 Subject: [PATCH 04/13] Nicer card display of status type explanations --- resources/views/statuslabels/index.blade.php | 26 +++++++++++++++++--- 1 file changed, 22 insertions(+), 4 deletions(-) diff --git a/resources/views/statuslabels/index.blade.php b/resources/views/statuslabels/index.blade.php index 2f267041ed..e5d568eba0 100755 --- a/resources/views/statuslabels/index.blade.php +++ b/resources/views/statuslabels/index.blade.php @@ -48,10 +48,28 @@

{{ trans('admin/statuslabels/table.about') }}

{{ trans('admin/statuslabels/table.info') }}

-

{{ trans('admin/statuslabels/table.deployable') }}: {!! trans('admin/statuslabels/message.help.deployable') !!}

-

Pending: {{ trans('admin/statuslabels/message.help.pending') }}

-

Undeployable: {{ trans('admin/statuslabels/message.help.undeployable') }}

-

Archived: {{ trans('admin/statuslabels/message.help.archived') }}

+
+
+

{{ trans('admin/statuslabels/table.deployable') }}: {!! trans('admin/statuslabels/message.help.deployable') !!}

+
+
+ +
+
+

Pending: {{ trans('admin/statuslabels/message.help.pending') }}

+
+
+
+
+

Undeployable: {{ trans('admin/statuslabels/message.help.undeployable') }}

+
+
+ +
+
+

Archived: {{ trans('admin/statuslabels/message.help.archived') }}

+
+
From b379656d553e56b9f2782dc25a1ef657467f44eb Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 19 Oct 2017 11:06:55 -0700 Subject: [PATCH 05/13] Adds more consistent visual display of status label types --- resources/views/statuslabels/index.blade.php | 30 ++++++++++++++++---- 1 file changed, 24 insertions(+), 6 deletions(-) diff --git a/resources/views/statuslabels/index.blade.php b/resources/views/statuslabels/index.blade.php index e5d568eba0..2a057bae8b 100755 --- a/resources/views/statuslabels/index.blade.php +++ b/resources/views/statuslabels/index.blade.php @@ -31,7 +31,7 @@ {{ trans('general.id') }} {{ trans('admin/statuslabels/table.name') }} - {{ trans('admin/statuslabels/table.status_type') }} + {{ trans('admin/statuslabels/table.status_type') }} {{ trans('general.assets') }} {{ trans('admin/statuslabels/table.color') }} {{ trans('admin/statuslabels/table.show_in_nav') }} @@ -92,12 +92,30 @@ } } - function undeployableFormatter(value, row) { - if ((value) && (value!='deployable')) { - return '' + value + ' '; - } else { - return '' + value + ' '; + function statusLabelTypeFormatter (row, value) { + switch (value.type) { + case 'deployed': + text_color = 'blue'; + icon_style = 'fa-circle'; + break; + case 'deployable': + text_color = 'green'; + icon_style = 'fa-circle'; + break; + case 'pending': + text_color = 'orange'; + icon_style = 'fa-circle'; + break; + default: + text_color = 'red'; + icon_style = 'fa-times'; } + + var typename_lower = value.type; + var typename = typename_lower.charAt(0).toUpperCase() + typename_lower.slice(1); + return ' ' + typename; + + } @stop From 287b150b7f57c78ea044360e5daaa3498d9590bd Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 19 Oct 2017 11:29:58 -0700 Subject: [PATCH 06/13] =?UTF-8?q?Show=20disabled=20delete=20button=20if=20?= =?UTF-8?q?thing=20can=E2=80=99t=20be=20deleted?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- resources/views/partials/bootstrap-table.blade.php | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/resources/views/partials/bootstrap-table.blade.php b/resources/views/partials/bootstrap-table.blade.php index 209ec3bd5f..cb2ab5cc48 100644 --- a/resources/views/partials/bootstrap-table.blade.php +++ b/resources/views/partials/bootstrap-table.blade.php @@ -198,12 +198,16 @@ $('.snipe-table').bootstrapTable({ + ' data-toggle="modal" ' + ' data-content="{{ trans('general.sure_to_delete') }} ' + row.name + '?" ' + ' data-title="{{ trans('general.delete') }}" onClick="return false;">' - + ''; + + ' '; + } else { + actions += ' '; } if ((row.available_actions) && (row.available_actions.restore === true)) { actions += ' '; } + + actions +=''; return actions; }; From 7e8d670f81e86466a2d148d207ea14271e703013 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 19 Oct 2017 11:41:35 -0700 Subject: [PATCH 07/13] Disable delete buttons if there are assets, etc --- app/Http/Transformers/CategoriesTransformer.php | 2 +- app/Http/Transformers/StatuslabelsTransformer.php | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/app/Http/Transformers/CategoriesTransformer.php b/app/Http/Transformers/CategoriesTransformer.php index edb56c0127..213793c90a 100644 --- a/app/Http/Transformers/CategoriesTransformer.php +++ b/app/Http/Transformers/CategoriesTransformer.php @@ -39,7 +39,7 @@ class CategoriesTransformer $permissions_array['available_actions'] = [ 'update' => Gate::allows('update', Category::class) ? true : false, - 'delete' => Gate::allows('delete', Category::class) ? true : false, + 'delete' => (Gate::allows('delete', Category::class) && ($category->assets_count == 0) && ($category->accessories_count == 0) && ($category->consumables_count == 0) && ($category->components_count == 0)) ? true : false, ]; $array += $permissions_array; diff --git a/app/Http/Transformers/StatuslabelsTransformer.php b/app/Http/Transformers/StatuslabelsTransformer.php index fa2b4f75a5..e7b356deb2 100644 --- a/app/Http/Transformers/StatuslabelsTransformer.php +++ b/app/Http/Transformers/StatuslabelsTransformer.php @@ -34,7 +34,7 @@ class StatuslabelsTransformer $permissions_array['available_actions'] = [ 'update' => Gate::allows('update', Statuslabel::class) ? true : false, - 'delete' => Gate::allows('delete', Statuslabel::class) ? true : false, + 'delete' => (Gate::allows('delete', Statuslabel::class) && ($statuslabel->assets_count == 0)) ? true : false, ]; $array += $permissions_array; From f6a38e848a3ab163836cfa5ca1f504aa12e91e78 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 19 Oct 2017 11:44:42 -0700 Subject: [PATCH 08/13] Allows sorting by whether or not the category requires acceptance --- app/Presenters/CategoryPresenter.php | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/app/Presenters/CategoryPresenter.php b/app/Presenters/CategoryPresenter.php index 4b545b82de..75a9845dd8 100644 --- a/app/Presenters/CategoryPresenter.php +++ b/app/Presenters/CategoryPresenter.php @@ -72,7 +72,7 @@ class CategoryPresenter extends Presenter ], [ "field" => "require_acceptance", "searchable" => false, - "sortable" => false, + "sortable" => true, "title" => trans('admin/categories/table.require_acceptance'), "visible" => true, "formatter" => 'trueFalseFormatter', From 54000ff69fd367cd6883fa10863d7d387b290893 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 19 Oct 2017 11:48:09 -0700 Subject: [PATCH 09/13] Allows sorting by number of assets, etc in category --- app/Http/Controllers/Api/CategoriesController.php | 4 ++-- app/Presenters/CategoryPresenter.php | 8 ++++---- 2 files changed, 6 insertions(+), 6 deletions(-) diff --git a/app/Http/Controllers/Api/CategoriesController.php b/app/Http/Controllers/Api/CategoriesController.php index 82f34754ad..58f6dd0a14 100644 --- a/app/Http/Controllers/Api/CategoriesController.php +++ b/app/Http/Controllers/Api/CategoriesController.php @@ -20,7 +20,7 @@ class CategoriesController extends Controller public function index(Request $request) { $this->authorize('view', Category::class); - $allowed_columns = ['id', 'name','category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email']; + $allowed_columns = ['id', 'name','category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email', 'assets_count', 'accessories_count', 'consumables_count', 'components_count']; $categories = Category::select(['id', 'created_at', 'updated_at', 'name','category_type','use_default_eula','eula_text', 'require_acceptance','checkin_email']) ->withCount('assets', 'accessories', 'consumables', 'components'); @@ -32,7 +32,7 @@ class CategoriesController extends Controller $offset = $request->input('offset', 0); $limit = $request->input('limit', 50); $order = $request->input('order') === 'asc' ? 'asc' : 'desc'; - $sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at'; + $sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count'; $categories->orderBy($sort, $order); $total = $categories->count(); diff --git a/app/Presenters/CategoryPresenter.php b/app/Presenters/CategoryPresenter.php index 75a9845dd8..42303f8e43 100644 --- a/app/Presenters/CategoryPresenter.php +++ b/app/Presenters/CategoryPresenter.php @@ -41,25 +41,25 @@ class CategoryPresenter extends Presenter ], [ "field" => "assets_count", "searchable" => false, - "sortable" => false, + "sortable" => true, "title" => trans('general.assets'), "visible" => true ], [ "field" => "accessories_count", "searchable" => false, - "sortable" => false, + "sortable" => true, "title" => trans('general.accessories'), "visible" => true ], [ "field" => "consumables_count", "searchable" => false, - "sortable" => false, + "sortable" => true, "title" => trans('general.consumables'), "visible" => true ], [ "field" => "components_count", "searchable" => false, - "sortable" => false, + "sortable" => true, "title" => trans('general.components'), "visible" => true ], [ From e185dc68af19cc78ddb33fe3e16e6811cec44670 Mon Sep 17 00:00:00 2001 From: snipe Date: Thu, 19 Oct 2017 12:22:27 -0700 Subject: [PATCH 10/13] Fixes #4240 - allows admins to use custom password reset URL --- app/Http/Controllers/SettingsController.php | 1 + app/Models/Setting.php | 1 + ..._120002_add_custom_forgot_password_url.php | 32 +++++++++++++++++++ resources/lang/en/admin/settings/general.php | 4 +++ resources/views/auth/login.blade.php | 8 ++++- .../views/auth/passwords/email.blade.php | 7 ++++ resources/views/settings/ldap.blade.php | 19 ++++++++++- 7 files changed, 70 insertions(+), 2 deletions(-) create mode 100644 database/migrations/2017_10_19_120002_add_custom_forgot_password_url.php diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php index 2cbf5cd289..1d1296c4cf 100755 --- a/app/Http/Controllers/SettingsController.php +++ b/app/Http/Controllers/SettingsController.php @@ -826,6 +826,7 @@ class SettingsController extends Controller $setting->is_ad = $request->input('is_ad', '0'); $setting->ldap_tls = $request->input('ldap_tls', '0'); $setting->ldap_pw_sync = $request->input('ldap_pw_sync', '0'); + $setting->custom_forgot_pass_url = $request->input('custom_forgot_pass_url'); if ($setting->save()) { return redirect()->route('settings.index') diff --git a/app/Models/Setting.php b/app/Models/Setting.php index 1404c4e1f5..b0d032da90 100755 --- a/app/Models/Setting.php +++ b/app/Models/Setting.php @@ -38,6 +38,7 @@ class Setting extends Model "pwd_secure_min" => "numeric|required|min:5", "audit_warning_days" => "numeric|nullable", "audit_interval" => "numeric|nullable", + "custom_forgot_pass_url" => "url|nullable", ]; protected $fillable = ['site_name','email_domain','email_format','username_format']; diff --git a/database/migrations/2017_10_19_120002_add_custom_forgot_password_url.php b/database/migrations/2017_10_19_120002_add_custom_forgot_password_url.php new file mode 100644 index 0000000000..7a1776e257 --- /dev/null +++ b/database/migrations/2017_10_19_120002_add_custom_forgot_password_url.php @@ -0,0 +1,32 @@ +string('custom_forgot_pass_url')->nullable()->default(null); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('settings', function (Blueprint $table) { + $table->dropColumn('custom_forgot_pass_url'); + }); + } +} diff --git a/resources/lang/en/admin/settings/general.php b/resources/lang/en/admin/settings/general.php index 1beed4ea5e..3dd1efe702 100644 --- a/resources/lang/en/admin/settings/general.php +++ b/resources/lang/en/admin/settings/general.php @@ -23,6 +23,8 @@ return array( 'confirm_purge_help' => 'Enter the text "DELETE" in the box below to purge your deleted records. This action cannot be undone.', 'custom_css' => 'Custom CSS', 'custom_css_help' => 'Enter any custom CSS overrides you would like to use. Do not include the <style></style> tags.', + 'custom_forgot_pass_url' => 'Custom Password Reset URL', + 'custom_forgot_pass_url_help' => 'This replaces the built-in forgotten password URL on the login screen, useful to direct people to internal or hosted LDAP password reset functionality. It will effectively disable local user forgotten password functionality.', 'default_currency' => 'Default Currency', 'default_eula_text' => 'Default EULA', 'default_language' => 'Default Language', @@ -44,6 +46,8 @@ return array( 'ldap_enabled' => 'LDAP enabled', 'ldap_integration' => 'LDAP Integration', 'ldap_settings' => 'LDAP Settings', + 'ldap_login_test_help' => 'Enter a valid LDAP username and password to test whether your LDAP login is configured correctly.', + 'ldap_login_sync_help' => 'This only tests that LDAP can sync correctly. If your LDAP Authentication query is not correct, users may still not be able to login.', 'ldap_server' => 'LDAP Server', 'ldap_server_help' => 'This should start with ldap:// (for unencrypted or TLS) or ldaps:// (for SSL)', 'ldap_server_cert' => 'LDAP SSL certificate validation', diff --git a/resources/views/auth/login.blade.php b/resources/views/auth/login.blade.php index e6d4316f4f..114ea6b21d 100755 --- a/resources/views/auth/login.blade.php +++ b/resources/views/auth/login.blade.php @@ -63,7 +63,13 @@ diff --git a/resources/views/auth/passwords/email.blade.php b/resources/views/auth/passwords/email.blade.php index 853b6e0108..d2e1cd344b 100644 --- a/resources/views/auth/passwords/email.blade.php +++ b/resources/views/auth/passwords/email.blade.php @@ -3,6 +3,11 @@ {{-- Page content --}} @section('content') + + @if ($snipeSettings->custom_forgot_pass_url) + {{ trans('auth/general.forgot_password') }} + @else +
{!! csrf_field() !!}
@@ -50,5 +55,7 @@
+ + @endif @stop diff --git a/resources/views/settings/ldap.blade.php b/resources/views/settings/ldap.blade.php index 705fdcafc9..10e4d919a2 100644 --- a/resources/views/settings/ldap.blade.php +++ b/resources/views/settings/ldap.blade.php @@ -377,12 +377,29 @@
-

Enter a valid LDAP username and password to test whether your LDAP login is configured correctly.

+

{{ trans('admin/settings/general.ldap_login_test_help') }}

@endif + +
+
+ {{ Form::label('custom_forgot_pass_url', trans('admin/settings/general.custom_forgot_pass_url')) }} +
+
+ @if (config('app.lock_passwords')===true) + {{ Form::text('custom_forgot_pass_url', Input::old('custom_forgot_pass_url', $setting->custom_forgot_pass_url), array('class' => 'form-control', 'disabled'=>'disabled','placeholder' => 'https://my.ldapserver-forgotpass.com')) }} + @else + {{ Form::text('custom_forgot_pass_url', Input::old('custom_forgot_pass_url', $setting->custom_forgot_pass_url), array('class' => 'form-control','placeholder' => 'https://my.ldapserver-forgotpass.com')) }} + @endif +

{{ trans('admin/settings/general.custom_forgot_pass_url_help') }}

+ {!! $errors->first('custom_forgot_pass_url', ':message') !!} +
+
+ +