diff --git a/.all-contributorsrc b/.all-contributorsrc
index e54cd35f99..60e3c89e88 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -782,6 +782,15 @@
"contributions": [
"doc"
]
+ },
+ {
+ "login": "TonisOrmisson",
+ "name": "TΓ΅nis Ormisson",
+ "avatar_url": "https://avatars1.githubusercontent.com/u/6357451?v=4",
+ "profile": "http://andmemasin.eu",
+ "contributions": [
+ "code"
+ ]
}
]
}
diff --git a/README.md b/README.md
index 5dbd277ad6..f4840f508b 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
[![Build Status](https://travis-ci.org/snipe/snipe-it.svg?branch=develop)](https://travis-ci.org/snipe/snipe-it) [![Stories in Ready](https://badge.waffle.io/snipe/snipe-it.png?label=ready+for+dev&title=Ready+for+development)](http://waffle.io/snipe/snipe-it) [![Maintenance](https://img.shields.io/maintenance/yes/2017.svg)]() [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Gitter](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeyhead.svg?style=social)](https://twitter.com/snipeyhead) [![Zenhub](https://img.shields.io/badge/Shipping_faster_with-ZenHub-5e60ba.svg)](https://zenhub.io) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
-[![All Contributors](https://img.shields.io/badge/all_contributors-84-orange.svg?style=flat-square)](#contributors)
+[![All Contributors](https://img.shields.io/badge/all_contributors-85-orange.svg?style=flat-square)](#contributors)
## Snipe-IT - Open Source Asset Management System
@@ -68,6 +68,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [
Gil Rutkowski](http://FlashingCursor.com)
[π»](https://github.com/snipe/snipe-it/commits?author=flashingcursor "Code") | [
Desmond Morris](http://www.desmondmorris.com)
[π»](https://github.com/snipe/snipe-it/commits?author=desmondmorris "Code") | [
Nick Peelman](http://peelman.us)
[π»](https://github.com/snipe/snipe-it/commits?author=peelman "Code") | [
Abraham Vegh](https://abrahamvegh.com)
[π»](https://github.com/snipe/snipe-it/commits?author=abrahamvegh "Code") | [
Mohamed Rashid](https://github.com/rashivkp)
[π](https://github.com/snipe/snipe-it/commits?author=rashivkp "Documentation") | [
Kasey](http://hinchk.github.io)
[π»](https://github.com/snipe/snipe-it/commits?author=HinchK "Code") | [
Brett](https://github.com/BrettFagerlund)
[β οΈ](https://github.com/snipe/snipe-it/commits?author=BrettFagerlund "Tests") |
| [
Jason Spriggs](http://jasonspriggs.com)
[π»](https://github.com/snipe/snipe-it/commits?author=jasonspriggs "Code") | [
Nate Felton](http://n8felton.wordpress.com)
[π»](https://github.com/snipe/snipe-it/commits?author=n8felton "Code") | [
Manasses Ferreira](http://homepages.dcc.ufmg.br/~manassesferreira)
[π»](https://github.com/snipe/snipe-it/commits?author=manassesferreira "Code") | [
Steve](https://github.com/steveelwood)
[β οΈ](https://github.com/snipe/snipe-it/commits?author=steveelwood "Tests") | [
matc](http://twitter.com/matc)
[β οΈ](https://github.com/snipe/snipe-it/commits?author=matc "Tests") | [
Cole R. Davis](http://www.davisracingteam.com)
[β οΈ](https://github.com/snipe/snipe-it/commits?author=VanillaNinjaD "Tests") | [
gibsonjoshua55](https://github.com/gibsonjoshua55)
[π»](https://github.com/snipe/snipe-it/commits?author=gibsonjoshua55 "Code") |
| [
Robin Temme](https://github.com/zwerch)
[π»](https://github.com/snipe/snipe-it/commits?author=zwerch "Code") | [
Iman](https://github.com/imanghafoori1)
[π»](https://github.com/snipe/snipe-it/commits?author=imanghafoori1 "Code") | [
Richard Hofman](https://github.com/richardhofman6)
[π»](https://github.com/snipe/snipe-it/commits?author=richardhofman6 "Code") | [
gizzmojr](https://github.com/gizzmojr)
[π»](https://github.com/snipe/snipe-it/commits?author=gizzmojr "Code") | [
Jenny Li](https://github.com/imjennyli)
[π](https://github.com/snipe/snipe-it/commits?author=imjennyli "Documentation") | [
Geoff Young](https://github.com/GeoffYoung)
[π»](https://github.com/snipe/snipe-it/commits?author=GeoffYoung "Code") | [
Elliot Blackburn](http://www.elliotblackburn.com)
[π](https://github.com/snipe/snipe-it/commits?author=BlueHatbRit "Documentation") |
+| [
TΓ΅nis Ormisson](http://andmemasin.eu)
[π»](https://github.com/snipe/snipe-it/commits?author=TonisOrmisson "Code") |
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
diff --git a/app/Console/Commands/RecryptFromMcrypt.php b/app/Console/Commands/RecryptFromMcrypt.php
index 7437708207..60599bafae 100644
--- a/app/Console/Commands/RecryptFromMcrypt.php
+++ b/app/Console/Commands/RecryptFromMcrypt.php
@@ -48,6 +48,7 @@ class RecryptFromMcrypt extends Command
// If not, we can try to use the current APP_KEY if looks like it's old
$legacy_key = env('LEGACY_APP_KEY');
$key_parts = explode(':', $legacy_key);
+ $legacy_cipher = env('LEGACY_CIPHER');
$errors = array();
if (!$legacy_key) {
@@ -60,6 +61,7 @@ class RecryptFromMcrypt extends Command
if (strlen($legacy_key) == 32) {
$legacy_length_check = true;
} elseif (array_key_exists('1', $key_parts) && (strlen($key_parts[1])==44)) {
+ $legacy_key = base64_decode($key_parts[1],true);
$legacy_length_check = true;
} else {
$legacy_length_check = false;
@@ -91,13 +93,17 @@ class RecryptFromMcrypt extends Command
}
- $mcrypter = new McryptEncrypter($legacy_key);
+ if($legacy_cipher){
+ $mcrypter = new McryptEncrypter($legacy_key,$legacy_cipher);
+ }else{
+ $mcrypter = new McryptEncrypter($legacy_key);
+ }
$settings = Setting::getSettings();
if ($settings->ldap_password=='') {
$this->comment('INFO: No LDAP password found. Skipping... ');
}
-
+ /** @var CustomField[] $custom_fields */
$custom_fields = CustomField::where('field_encrypted','=', 1)->get();
$this->comment('INFO: Retrieving encrypted custom fields...');
@@ -110,32 +116,22 @@ class RecryptFromMcrypt extends Command
// Get all assets with a value in any of the fields that were encrypted
+ /** @var Asset[] $assets */
$assets = $query->get();
$bar = $this->output->createProgressBar(count($assets));
- foreach ($custom_fields as $encrypted_field) {
-
- // Try to decrypt the payload using the legacy app key
- try {
- $decrypted_field = $mcrypter->decrypt($encrypted_field);
- $this->comment($decrypted_field);
- } catch (\Exception $e) {
- $errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
- }
- $bar->advance();
- }
-
foreach ($assets as $asset) {
foreach ($custom_fields as $encrypted_field) {
+ $columnName = $encrypted_field->db_column;
// Make sure the value isn't null
- if ($asset->{$encrypted_field}!='') {
+ if ($asset->{$columnName}!='') {
// Try to decrypt the payload using the legacy app key
try {
- $decrypted_field = $mcrypter->decrypt($asset->{$encrypted_field});
- $asset->{$encrypted_field} = \Crypt::encrypt($decrypted_field);
+ $decrypted_field = $mcrypter->decrypt($asset->{$columnName});
+ $asset->{$columnName} = \Crypt::encrypt($decrypted_field);
$this->comment($decrypted_field);
} catch (\Exception $e) {
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
diff --git a/app/Http/Controllers/Api/SuppliersController.php b/app/Http/Controllers/Api/SuppliersController.php
index 22f35f47de..99a60c6a93 100644
--- a/app/Http/Controllers/Api/SuppliersController.php
+++ b/app/Http/Controllers/Api/SuppliersController.php
@@ -113,8 +113,22 @@ class SuppliersController extends Controller
public function destroy($id)
{
$this->authorize('delete', Supplier::class);
- $supplier = Supplier::findOrFail($id);
+ $supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances','assets', 'licenses')->findOrFail($id);
$this->authorize('delete', $supplier);
+
+
+ if ($supplier->assets_count > 0) {
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_assets', ['asset_count' => (int) $supplier->assets_count])));
+ }
+
+ if ($supplier->asset_maintenances_count > 0) {
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_maintenances', ['asset_maintenances_count' => $supplier->asset_maintenances_count])));
+ }
+
+ if ($supplier->licenses_count > 0) {
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_licenses', ['licenses_count' => (int) $supplier->licenses_count])));
+ }
+
$supplier->delete();
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/suppliers/message.delete.success')));
diff --git a/app/Http/Controllers/LicensesController.php b/app/Http/Controllers/LicensesController.php
index 232a8e8957..84891a21e8 100755
--- a/app/Http/Controllers/LicensesController.php
+++ b/app/Http/Controllers/LicensesController.php
@@ -187,6 +187,7 @@ class LicensesController extends Controller
$license->termination_date = $request->input('termination_date');
$license->seats = e($request->input('seats'));
$license->manufacturer_id = $request->input('manufacturer_id');
+ $license->supplier_id = $request->input('supplier_id');
if ($license->save()) {
return redirect()->route('licenses.show', ['license' => $licenseId])->with('success', trans('admin/licenses/message.update.success'));
diff --git a/app/Http/Controllers/SuppliersController.php b/app/Http/Controllers/SuppliersController.php
index a6e8552df9..04657e06a2 100755
--- a/app/Http/Controllers/SuppliersController.php
+++ b/app/Http/Controllers/SuppliersController.php
@@ -189,23 +189,29 @@ class SuppliersController extends Controller
*/
public function destroy($supplierId)
{
- // Check if the supplier exists
- if (is_null($supplier = Supplier::find($supplierId))) {
- // Redirect to the suppliers page
+ if (is_null($supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances','assets','licenses')->find($supplierId))) {
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.not_found'));
}
- if ($supplier->num_assets() == 0) {
- // Delete the supplier
- $supplier->delete();
- // Redirect to the suppliers management page
- return redirect()->route('suppliers.index')->with(
- 'success',
- trans('admin/suppliers/message.delete.success')
- );
+
+ if ($supplier->assets_count > 0) {
+ return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_assets', ['asset_count' => (int) $supplier->assets_count]));
}
- // Redirect to the asset management page
- return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.assoc_users'));
+
+ if ($supplier->asset_maintenances_count > 0) {
+ return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_maintenances', ['asset_maintenances_count' => $supplier->asset_maintenances_count]));
+ }
+
+ if ($supplier->licenses_count > 0) {
+ return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_licenses', ['licenses_count' => (int) $supplier->licenses_count]));
+ }
+
+ $supplier->delete();
+ return redirect()->route('suppliers.index')->with('success',
+ trans('admin/suppliers/message.delete.success')
+ );
+
+
}
diff --git a/app/Presenters/AccessoryPresenter.php b/app/Presenters/AccessoryPresenter.php
index 3ee9dc2145..5032fdb540 100644
--- a/app/Presenters/AccessoryPresenter.php
+++ b/app/Presenters/AccessoryPresenter.php
@@ -96,6 +96,7 @@ class AccessoryPresenter extends Presenter
"searchable" => true,
"sortable" => true,
"title" => trans('general.purchase_cost'),
+ "footerFormatter" => 'sumFormatter',
], [
"field" => "order_number",
"searchable" => true,
diff --git a/app/Presenters/AssetPresenter.php b/app/Presenters/AssetPresenter.php
index 53188aa237..ba030b05cd 100644
--- a/app/Presenters/AssetPresenter.php
+++ b/app/Presenters/AssetPresenter.php
@@ -139,6 +139,7 @@ class AssetPresenter extends Presenter
"searchable" => true,
"sortable" => true,
"title" => trans('general.purchase_cost'),
+ "footerFormatter" => 'sumFormatter',
], [
"field" => "order_number",
"searchable" => true,
diff --git a/app/Presenters/ComponentPresenter.php b/app/Presenters/ComponentPresenter.php
index b9493ab996..1a62db667e 100644
--- a/app/Presenters/ComponentPresenter.php
+++ b/app/Presenters/ComponentPresenter.php
@@ -85,6 +85,7 @@ class ComponentPresenter extends Presenter
"sortable" => true,
"title" => trans('general.purchase_cost'),
"visible" => true,
+ "footerFormatter" => 'sumFormatter',
],
];
diff --git a/app/Presenters/ConsumablePresenter.php b/app/Presenters/ConsumablePresenter.php
index 88e13ff58d..2b542912af 100644
--- a/app/Presenters/ConsumablePresenter.php
+++ b/app/Presenters/ConsumablePresenter.php
@@ -89,6 +89,7 @@ class ConsumablePresenter extends Presenter
"sortable" => true,
"title" => trans('general.purchase_cost'),
"visible" => true,
+ "footerFormatter" => 'sumFormatter',
],[
"field" => "change",
"searchable" => false,
diff --git a/app/Presenters/LicensePresenter.php b/app/Presenters/LicensePresenter.php
index 1814427c2e..fb0da5ccd8 100644
--- a/app/Presenters/LicensePresenter.php
+++ b/app/Presenters/LicensePresenter.php
@@ -98,6 +98,7 @@ class LicensePresenter extends Presenter
"sortable" => true,
"visible" => false,
"title" => trans('general.purchase_cost'),
+ "footerFormatter" => 'sumFormatter',
], [
"field" => "purchase_order",
"searchable" => true,
diff --git a/resources/lang/en/admin/suppliers/message.php b/resources/lang/en/admin/suppliers/message.php
index df4bc41af3..cea332748f 100644
--- a/resources/lang/en/admin/suppliers/message.php
+++ b/resources/lang/en/admin/suppliers/message.php
@@ -3,7 +3,7 @@
return array(
'does_not_exist' => 'Supplier does not exist.',
- 'assoc_users' => 'This supplier is currently associated with at least one model and cannot be deleted. Please update your models to no longer reference this supplier and try again. ',
+
'create' => array(
'error' => 'Supplier was not created, please try again.',
@@ -18,7 +18,10 @@ return array(
'delete' => array(
'confirm' => 'Are you sure you wish to delete this supplier?',
'error' => 'There was an issue deleting the supplier. Please try again.',
- 'success' => 'Supplier was deleted successfully.'
+ 'success' => 'Supplier was deleted successfully.',
+ 'assoc_assets' => 'This supplier is currently associated with :asset_count asset(s) and cannot be deleted. Please update your assets to no longer reference this supplier and try again. ',
+ 'assoc_licenses' => 'This supplier is currently associated with :licenses_count licences(s) and cannot be deleted. Please update your licenses to no longer reference this supplier and try again. ',
+ 'assoc_maintenances' => 'This supplier is currently associated with :asset_maintenances_count asset maintenances(s) and cannot be deleted. Please update your asset maintenances to no longer reference this supplier and try again. ',
)
);
diff --git a/resources/views/accessories/index.blade.php b/resources/views/accessories/index.blade.php
index 819932dcd8..be1378156e 100755
--- a/resources/views/accessories/index.blade.php
+++ b/resources/views/accessories/index.blade.php
@@ -42,6 +42,7 @@
@include ('partials.bootstrap-table', [
'exportFile' => 'accessories-export',
'search' => true,
+ 'showFooter' => true,
'columns' => \App\Presenters\AccessoryPresenter::dataTableLayout()
])
@stop
diff --git a/resources/views/components/index.blade.php b/resources/views/components/index.blade.php
index cd68175177..c49599d018 100644
--- a/resources/views/components/index.blade.php
+++ b/resources/views/components/index.blade.php
@@ -45,7 +45,7 @@
@stop
@section('moar_scripts')
-@include ('partials.bootstrap-table', ['exportFile' => 'components-export', 'search' => true, 'columns' => \App\Presenters\ComponentPresenter::dataTableLayout()])
+@include ('partials.bootstrap-table', ['exportFile' => 'components-export', 'search' => true, 'showFooter' => true, 'columns' => \App\Presenters\ComponentPresenter::dataTableLayout()])
diff --git a/resources/views/consumables/index.blade.php b/resources/views/consumables/index.blade.php
index 68d0913195..feeb2367e3 100644
--- a/resources/views/consumables/index.blade.php
+++ b/resources/views/consumables/index.blade.php
@@ -40,5 +40,5 @@
@stop
@section('moar_scripts')
-@include ('partials.bootstrap-table', ['exportFile' => 'consumables-export', 'search' => true,'columns' => \App\Presenters\ConsumablePresenter::dataTableLayout()])
+@include ('partials.bootstrap-table', ['exportFile' => 'consumables-export', 'search' => true,'showFooter' => true, 'columns' => \App\Presenters\ConsumablePresenter::dataTableLayout()])
@stop
diff --git a/resources/views/hardware/index.blade.php b/resources/views/hardware/index.blade.php
index 18de1d12d1..1057dc380b 100755
--- a/resources/views/hardware/index.blade.php
+++ b/resources/views/hardware/index.blade.php
@@ -101,6 +101,7 @@
@include ('partials.bootstrap-table', [
'exportFile' => 'assets-export',
'search' => true,
+ 'showFooter' => true,
'columns' => \App\Presenters\AssetPresenter::dataTableLayout()
])
diff --git a/resources/views/licenses/index.blade.php b/resources/views/licenses/index.blade.php
index 683ca2eb15..d236cea3f9 100755
--- a/resources/views/licenses/index.blade.php
+++ b/resources/views/licenses/index.blade.php
@@ -45,6 +45,7 @@
@include ('partials.bootstrap-table', [
'exportFile' => 'licenses-export',
'search' => true,
+ 'showFooter' => true,
'columns' => \App\Presenters\LicensePresenter::dataTableLayout()])
@stop
diff --git a/resources/views/partials/bootstrap-table.blade.php b/resources/views/partials/bootstrap-table.blade.php
index 896cb97caf..2d14246a06 100644
--- a/resources/views/partials/bootstrap-table.blade.php
+++ b/resources/views/partials/bootstrap-table.blade.php
@@ -38,6 +38,9 @@ $('.snipe-table').bootstrapTable({
cookie: true,
cookieExpire: '2y',
showExport: true,
+ @if (isset($showFooter))
+ showFooter: true,
+ @endif
showColumns: true,
trimOnSearch: false,
@@ -202,7 +205,7 @@ $('.snipe-table').bootstrapTable({
}
- // This handles
+ // This handles the icons and display of polymorphic entries
function polymorphicItemFormatter(value) {
var item_destination = '';
@@ -419,6 +422,15 @@ $('.snipe-table').bootstrapTable({
}
}
+ function sumFormatter(data) {
+ var field = this.field;
+ var total_sum = data.reduce(function(sum, row) {
+ return (sum) + (parseFloat(row[field]) || 0);
+ }, 0);
+ return total_sum.toFixed(2);
+ }
+
+
$(function () {
$('#bulkEdit').click(function () {
var selectedIds = $('.snipe-table').bootstrapTable('getSelections');
@@ -429,7 +441,9 @@ $('.snipe-table').bootstrapTable({
});
});
- // This is necessary to make the bootstrap tooltips work inside of the wenzhixin/bootstrap-table formatters
+
+ // This is necessary to make the bootstrap tooltips work inside of the
+ // wenzhixin/bootstrap-table formatters
$(function() {
$('#table').on('post-body.bs.table', function () {
$('[data-tooltip="true"]').tooltip({
@@ -439,4 +453,6 @@ $('.snipe-table').bootstrapTable({
});
+
+
diff --git a/resources/views/reports/asset_maintenances.blade.php b/resources/views/reports/asset_maintenances.blade.php
index 31d61e0b76..e84d3d81f7 100644
--- a/resources/views/reports/asset_maintenances.blade.php
+++ b/resources/views/reports/asset_maintenances.blade.php
@@ -14,81 +14,32 @@
{{ trans('admin/companies/table.title') }} | +{{ trans('general.id') }} | +{{ trans('admin/asset_maintenances/table.asset_name') }} | +{{ trans('general.supplier') }} | +{{ trans('admin/asset_maintenances/form.asset_maintenance_type') }} | +{{ trans('admin/asset_maintenances/form.title') }} | +{{ trans('admin/asset_maintenances/form.start_date') }} | +{{ trans('admin/asset_maintenances/form.completion_date') }} | +{{ trans('admin/asset_maintenances/form.asset_maintenance_time') }} | +{{ trans('admin/asset_maintenances/form.cost') }} | +{{ trans('general.admin') }} | +{{ trans('admin/asset_maintenances/form.notes') }} | +
---|