diff --git a/.all-contributorsrc b/.all-contributorsrc index 547fd4539..82ae115c8 100644 --- a/.all-contributorsrc +++ b/.all-contributorsrc @@ -2837,6 +2837,15 @@ "contributions": [ "code" ] + }, + { + "login": "AndrewSav", + "name": "Andrew Savinykh", + "avatar_url": "https://avatars.githubusercontent.com/u/658865?v=4", + "profile": "https://github.com/AndrewSav", + "contributions": [ + "code" + ] } ] } diff --git a/README.md b/README.md index 1818aa1f8..a881f3a3a 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ ![Build Status](https://app.chipperci.com/projects/0e5f8979-31eb-4ee6-9abf-050b76ab0383/status/master) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![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/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![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-312-orange.svg?style=flat-square)](#contributors) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk) [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev) +[![All Contributors](https://img.shields.io/badge/all_contributors-313-orange.svg?style=flat-square)](#contributors) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk) [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev) ## Snipe-IT - Open Source Asset Management System @@ -140,7 +140,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken | [
Christian Weirich](https://github.com/chrisweirich)
[💻](https://github.com/snipe/snipe-it/commits?author=chrisweirich "Code") | [
denzfarid](https://github.com/denzfarid)
| [
ntbutler-nbcs](https://github.com/ntbutler-nbcs)
[💻](https://github.com/snipe/snipe-it/commits?author=ntbutler-nbcs "Code") | [
Naveen](https://naveensrinivasan.dev)
[💻](https://github.com/snipe/snipe-it/commits?author=naveensrinivasan "Code") | [
Mike Roquemore](https://github.com/mikeroq)
[💻](https://github.com/snipe/snipe-it/commits?author=mikeroq "Code") | [
Daniel Reeder](https://github.com/reederda)
[🌍](#translation-reederda "Translation") [🌍](#translation-reederda "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=reederda "Code") | [
vickyjaura183](https://github.com/vickyjaura183)
[💻](https://github.com/snipe/snipe-it/commits?author=vickyjaura183 "Code") | | [
Peace](https://github.com/julian-piehl)
[💻](https://github.com/snipe/snipe-it/commits?author=julian-piehl "Code") | [
Kyle Gordon](https://github.com/kylegordon)
[💻](https://github.com/snipe/snipe-it/commits?author=kylegordon "Code") | [
Katharina Drexel](http://www.bfh.ch)
[💻](https://github.com/snipe/snipe-it/commits?author=sunflowerbofh "Code") | [
David Sferruzza](https://david.sferruzza.fr/)
[💻](https://github.com/snipe/snipe-it/commits?author=dsferruzza "Code") | [
Rick Nelson](https://github.com/rnelsonee)
[💻](https://github.com/snipe/snipe-it/commits?author=rnelsonee "Code") | [
BasO12](https://github.com/BasO12)
[💻](https://github.com/snipe/snipe-it/commits?author=BasO12 "Code") | [
Vautia](https://github.com/Vautia)
[💻](https://github.com/snipe/snipe-it/commits?author=Vautia "Code") | | [
Chris Hartjes](http://www.littlehart.net/atthekeyboard)
[💻](https://github.com/snipe/snipe-it/commits?author=chartjes "Code") | [
geo-chen](https://github.com/geo-chen)
[💻](https://github.com/snipe/snipe-it/commits?author=geo-chen "Code") | [
Phan Nguyen](https://github.com/nh314)
[💻](https://github.com/snipe/snipe-it/commits?author=nh314 "Code") | [
Iisakki Jaakkola](https://github.com/StarlessNights)
[💻](https://github.com/snipe/snipe-it/commits?author=StarlessNights "Code") | [
Ikko Ashimine](https://bandism.net/)
[💻](https://github.com/snipe/snipe-it/commits?author=eltociear "Code") | [
Lukas Fehling](https://github.com/lukasfehling)
[💻](https://github.com/snipe/snipe-it/commits?author=lukasfehling "Code") | [
Fernando Almeida](https://github.com/fernando-almeida)
[💻](https://github.com/snipe/snipe-it/commits?author=fernando-almeida "Code") | -| [
akemidx](https://github.com/akemidx)
[💻](https://github.com/snipe/snipe-it/commits?author=akemidx "Code") | [
Oguz Bilgic](http://oguz.site)
[💻](https://github.com/snipe/snipe-it/commits?author=oguzbilgic "Code") | [
Scooter Crawford](https://github.com/scoo73r)
[💻](https://github.com/snipe/snipe-it/commits?author=scoo73r "Code") | [
subdriven](https://github.com/subdriven)
[💻](https://github.com/snipe/snipe-it/commits?author=subdriven "Code") | +| [
akemidx](https://github.com/akemidx)
[💻](https://github.com/snipe/snipe-it/commits?author=akemidx "Code") | [
Oguz Bilgic](http://oguz.site)
[💻](https://github.com/snipe/snipe-it/commits?author=oguzbilgic "Code") | [
Scooter Crawford](https://github.com/scoo73r)
[💻](https://github.com/snipe/snipe-it/commits?author=scoo73r "Code") | [
subdriven](https://github.com/subdriven)
[💻](https://github.com/snipe/snipe-it/commits?author=subdriven "Code") | [
Andrew Savinykh](https://github.com/AndrewSav)
[💻](https://github.com/snipe/snipe-it/commits?author=AndrewSav "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/CheckoutLicenseToAllUsers.php b/app/Console/Commands/CheckoutLicenseToAllUsers.php index d655b5ace..c81408442 100644 --- a/app/Console/Commands/CheckoutLicenseToAllUsers.php +++ b/app/Console/Commands/CheckoutLicenseToAllUsers.php @@ -56,7 +56,7 @@ class CheckoutLicenseToAllUsers extends Command return false; } - $users = User::whereNull('deleted_at')->with('licenses')->get(); + $users = User::whereNull('deleted_at')->where('autoassign_licenses', '==', 1)->with('licenses')->get(); if ($users->count() > $license->getAvailSeatsCountAttribute()) { $this->info('You do not have enough free seats to complete this task, so we will check out as many as we can. '); diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index 2a3499255..0c6ab8834 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -121,6 +121,7 @@ class UsersController extends Controller $user->created_by = Auth::user()->id; $user->start_date = $request->input('start_date', null); $user->end_date = $request->input('end_date', null); + $user->autoassign_licenses= $request->input('autoassign_licenses', 1); // Strip out the superuser permission if the user isn't a superadmin $permissions_array = $request->input('permission'); @@ -274,6 +275,7 @@ class UsersController extends Controller $user->website = $request->input('website', null); $user->start_date = $request->input('start_date', null); $user->end_date = $request->input('end_date', null); + $user->autoassign_licenses = $request->input('autoassign_licenses', 1); // Update the location of any assets checked out to this user Asset::where('assigned_type', User::class) diff --git a/app/Models/License.php b/app/Models/License.php index d3c4d8a1c..b715adf18 100755 --- a/app/Models/License.php +++ b/app/Models/License.php @@ -368,7 +368,7 @@ class License extends Depreciable */ public function assignedusers() { - return $this->belongsToMany(\App\Models\User::class, 'license_seats', 'assigned_to', 'license_id'); + return $this->belongsToMany(\App\Models\User::class, 'license_seats', 'license_id', 'assigned_to'); } /** diff --git a/app/Models/User.php b/app/Models/User.php index 1f57f9190..73a30b229 100644 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -285,7 +285,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo */ public function assets() { - return $this->morphMany(\App\Models\Asset::class, 'assigned', 'assigned_type', 'assigned_to')->withTrashed(); + return $this->morphMany(\App\Models\Asset::class, 'assigned', 'assigned_type', 'assigned_to')->withTrashed()->orderBy('id'); } /** @@ -313,7 +313,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo public function accessories() { return $this->belongsToMany(\App\Models\Accessory::class, 'accessories_users', 'assigned_to', 'accessory_id') - ->withPivot('id', 'created_at', 'note')->withTrashed(); + ->withPivot('id', 'created_at', 'note')->withTrashed()->orderBy('accessory_id'); } /** diff --git a/composer.json b/composer.json index 4e71debc6..abcf675b1 100644 --- a/composer.json +++ b/composer.json @@ -61,12 +61,13 @@ "nunomaduro/collision": "^5.4", "onelogin/php-saml": "^3.4", "paragonie/constant_time_encoding": "^2.3", - "symfony/polyfill-mbstring": "^1.22", + "paragonie/sodium_compat": "^1.19", "phpdocumentor/reflection-docblock": "^5.1", "phpspec/prophecy": "^1.10", "pragmarx/google2fa-laravel": "^1.3", "rollbar/rollbar-laravel": "^7.0", "spatie/laravel-backup": "^6.16", + "symfony/polyfill-mbstring": "^1.22", "tecnickcom/tc-lib-barcode": "^1.15", "unicodeveloper/laravel-password": "^1.0", "watson/validating": "^6.1" diff --git a/composer.lock b/composer.lock index b9022ba84..525c6f866 100644 --- a/composer.lock +++ b/composer.lock @@ -4,7 +4,6 @@ "Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies", "This file is @generated automatically" ], - "content-hash": "9bd2bbbd4b08d23336364da3d3a4561a", "packages": [ { "name": "alek13/slack", @@ -6299,6 +6298,92 @@ }, "time": "2020-10-15T08:29:30+00:00" }, + { + "name": "paragonie/sodium_compat", + "version": "v1.19.0", + "source": { + "type": "git", + "url": "https://github.com/paragonie/sodium_compat.git", + "reference": "cb15e403ecbe6a6cc515f855c310eb6b1872a933" + }, + "dist": { + "type": "zip", + "url": "https://api.github.com/repos/paragonie/sodium_compat/zipball/cb15e403ecbe6a6cc515f855c310eb6b1872a933", + "reference": "cb15e403ecbe6a6cc515f855c310eb6b1872a933", + "shasum": "" + }, + "require": { + "paragonie/random_compat": ">=1", + "php": "^5.2.4|^5.3|^5.4|^5.5|^5.6|^7|^8" + }, + "require-dev": { + "phpunit/phpunit": "^3|^4|^5|^6|^7|^8|^9" + }, + "suggest": { + "ext-libsodium": "PHP < 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security.", + "ext-sodium": "PHP >= 7.0: Better performance, password hashing (Argon2i), secure memory management (memzero), and better security." + }, + "type": "library", + "autoload": { + "files": [ + "autoload.php" + ] + }, + "notification-url": "https://packagist.org/downloads/", + "license": [ + "ISC" + ], + "authors": [ + { + "name": "Paragon Initiative Enterprises", + "email": "security@paragonie.com" + }, + { + "name": "Frank Denis", + "email": "jedisct1@pureftpd.org" + } + ], + "description": "Pure PHP implementation of libsodium; uses the PHP extension if it exists", + "keywords": [ + "Authentication", + "BLAKE2b", + "ChaCha20", + "ChaCha20-Poly1305", + "Chapoly", + "Curve25519", + "Ed25519", + "EdDSA", + "Edwards-curve Digital Signature Algorithm", + "Elliptic Curve Diffie-Hellman", + "Poly1305", + "Pure-PHP cryptography", + "RFC 7748", + "RFC 8032", + "Salpoly", + "Salsa20", + "X25519", + "XChaCha20-Poly1305", + "XSalsa20-Poly1305", + "Xchacha20", + "Xsalsa20", + "aead", + "cryptography", + "ecdh", + "elliptic curve", + "elliptic curve cryptography", + "encryption", + "libsodium", + "php", + "public-key cryptography", + "secret-key cryptography", + "side-channel resistant" + ], + "support": { + "issues": "https://github.com/paragonie/sodium_compat/issues", + "source": "https://github.com/paragonie/sodium_compat/tree/v1.19.0" + }, + "time": "2022-09-26T03:40:35+00:00" + }, { "name": "phenx/php-font-lib", "version": "0.5.4", diff --git a/database/migrations/2022_11_15_232525_adds_should_autoassign_bool_to_users_table.php b/database/migrations/2022_11_15_232525_adds_should_autoassign_bool_to_users_table.php new file mode 100644 index 000000000..b728e1f22 --- /dev/null +++ b/database/migrations/2022_11_15_232525_adds_should_autoassign_bool_to_users_table.php @@ -0,0 +1,32 @@ +boolean('autoassign_licenses')->nullable(false)->default(1); + }); + } + + /** + * Reverse the migrations. + * + * @return void + */ + public function down() + { + Schema::table('users', function (Blueprint $table) { + $table->dropColumn('autoassign_licenses'); + }); + } +} diff --git a/resources/lang/en/admin/users/general.php b/resources/lang/en/admin/users/general.php index ff482b8eb..bdd9401da 100644 --- a/resources/lang/en/admin/users/general.php +++ b/resources/lang/en/admin/users/general.php @@ -19,6 +19,8 @@ return [ 'print_assigned' => 'Print All Assigned', 'email_assigned' => 'Email List of All Assigned', 'user_notified' => 'User has been emailed a list of their currently assigned items.', + 'auto_assign_label' => 'Include this user when auto-assigning eligible licenses', + 'auto_assign_help' => 'Skip this user in auto assignment of licenses', 'software_user' => 'Software Checked out to :name', 'send_email_help' => 'You must provide an email address for this user to send them credentials. Emailing credentials can only be done on user creation. Passwords are stored in a one-way hash and cannot be retrieved once saved.', 'view_user' => 'View User :name', @@ -41,4 +43,9 @@ return [ 'remote' => 'Remote', 'remote_help' => 'This can be useful if you need to filter by remote users who never or rarely come into your physical locations.', 'not_remote_label' => 'This is not a remote user', -]; \ No newline at end of file + 'create_user' => 'Create a user', + 'create_user_page_explanation' => 'This is the account information you will use to access the site for the first time.', + 'email_credentials' => 'Email credentials', + 'email_credentials_text' => 'Email my credentials to the email address above', + 'next_save_user' => 'Next: Save User', +]; diff --git a/resources/views/notifications/markdown/user-inventory.blade.php b/resources/views/notifications/markdown/user-inventory.blade.php index d59733854..c7dfba9a3 100644 --- a/resources/views/notifications/markdown/user-inventory.blade.php +++ b/resources/views/notifications/markdown/user-inventory.blade.php @@ -9,9 +9,18 @@ ## {{ $assets->count() }} {{ trans('general.assets') }} - + @foreach($assets as $asset) - + + + + + @if (($snipeSettings->show_images_in_email =='1') && $asset->getImageUrl()) + + @endif + @endforeach
{{ trans('mail.name') }} {{ trans('mail.asset_tag') }}{{ trans('admin/hardware/table.serial') }}
{{ trans('mail.name') }} {{ trans('mail.asset_tag') }}{{ trans('admin/hardware/table.serial') }}
{{ $asset->present()->name }} {{ $asset->asset_tag }} {{ $asset->serial }}
{{ $asset->present()->name }} {{ $asset->asset_tag }} {{ $asset->serial }} + Asset +
@endif @@ -20,9 +29,16 @@ ## {{ $accessories->count() }} {{ trans('general.accessories') }} - + @foreach($accessories as $accessory) - + + + @if (($snipeSettings->show_images_in_email =='1') && $accessory->getImageUrl()) + + @endif + @endforeach
{{ trans('mail.name') }}
{{ trans('mail.name') }}
{{ $accessory->name }}
{{ $accessory->name }} + Accessory +
@endif @@ -33,7 +49,9 @@ @foreach($licenses as $license) - + + + @endforeach
{{ $license->name }}
{{ $license->name }}
@endif diff --git a/resources/views/setup/user.blade.php b/resources/views/setup/user.blade.php index eaa74fb85..a45d37a3e 100644 --- a/resources/views/setup/user.blade.php +++ b/resources/views/setup/user.blade.php @@ -1,15 +1,14 @@ @extends('layouts/setup') -{{-- TODO: Translate --}} -{{-- Page title --}} +{{ trans('admin/user/table.createuser') }} @section('title') -Create a User :: +{{ trans('admin/user/general.create_user') }} :: @parent @stop {{-- Page content --}} @section('content') -

This is the account information you'll use to access the site for the first time.

+

{{ trans('admin/user/general.create_user_page_explanation') }}

{{ csrf_field() }} @@ -157,10 +156,10 @@ Create a User ::
- +
@@ -168,7 +167,7 @@ Create a User :: @stop @section('button') - +
@parent @stop diff --git a/resources/views/users/edit.blade.php b/resources/views/users/edit.blade.php index adfa261ca..3a85874b9 100755 --- a/resources/views/users/edit.blade.php +++ b/resources/views/users/edit.blade.php @@ -384,6 +384,19 @@ + +
+
+ +

{{ trans('admin/users/general.auto_assign_help') }} +

+
+
+ @include ('partials.forms.edit.location-select', ['translated_name' => trans('general.location'), 'fieldname' => 'location_id']) diff --git a/routes/api.php b/routes/api.php index 37bc3baa8..2429ffa85 100644 --- a/routes/api.php +++ b/routes/api.php @@ -1162,6 +1162,17 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'throttle:api']], functi )->name('api.activity.index'); }); // end reports api routes + /** + * Version API routes + */ + + Route::get('/version', function () { + return response()->json( + [ + 'version' => config('version.app_version'), + ], 200); + }); // end version api routes + Route::fallback(function () { return response()->json( @@ -1172,5 +1183,4 @@ Route::group(['prefix' => 'v1', 'middleware' => ['api', 'throttle:api']], functi ], 404); }); // end fallback routes - }); // end API routes diff --git a/upgrade.php b/upgrade.php index ca71a6184..69ab2ffda 100644 --- a/upgrade.php +++ b/upgrade.php @@ -176,6 +176,10 @@ $required_exts_array = 'zip', ]; +$recommended_exts_array = + [ + 'sodium', //note that extensions need to be in BOTH the $required_exts_array and this one to be 'optional' + ]; $ext_missing = ''; $ext_installed = ''; @@ -205,8 +209,10 @@ foreach ($required_exts_array as $required_ext) { } // If this isn't an either/or option, just add it to the string of errors conventionally - } else { + } elseif (!in_array($required_ext, $recommended_exts_array)){ $ext_missing .= '✘ MISSING PHP EXTENSION: '.$required_ext."\n"; + } else { + $ext_installed .= '- '.$required_ext." is *NOT* installed, but is recommended...\n"; } // The required extension string was found in the array of installed extensions - yay!