Compare commits

..

4 Commits

Author SHA1 Message Date
snipe
f98f978502 Fixed typos
Signed-off-by: snipe <snipe@snipe.net>
2024-12-11 16:53:15 +00:00
snipe
a0bbafeb30 Removed unused code
Signed-off-by: snipe <snipe@snipe.net>
2024-12-10 14:35:22 +00:00
snipe
dbd33e1a34 Check for specific error message
Signed-off-by: snipe <snipe@snipe.net>
2024-12-10 14:34:16 +00:00
snipe
8afba32169 Validate group data
Signed-off-by: snipe <snipe@snipe.net>
2024-12-10 14:23:23 +00:00
926 changed files with 6806 additions and 13464 deletions

View File

@@ -3235,42 +3235,6 @@
"contributions": [
"code"
]
},
{
"login": "sgross-emlix",
"name": "Sebastian Groß",
"avatar_url": "https://avatars.githubusercontent.com/u/143394709?v=4",
"profile": "https://github.com/sgross-emlix",
"contributions": [
"code"
]
},
{
"login": "AnouarTouati",
"name": "Anouar Touati",
"avatar_url": "https://avatars.githubusercontent.com/u/41107778?v=4",
"profile": "https://github.com/AnouarTouati",
"contributions": [
"code"
]
},
{
"login": "aHVzY2g",
"name": "aHVzY2g",
"avatar_url": "https://avatars.githubusercontent.com/u/25596663?v=4",
"profile": "https://github.com/aHVzY2g",
"contributions": [
"code"
]
},
{
"login": "brlin-tw",
"name": "林博仁 Buo-ren Lin",
"avatar_url": "https://avatars.githubusercontent.com/u/13408130?v=4",
"profile": "https://brlin.me",
"contributions": [
"code"
]
}
]
}

View File

@@ -11,7 +11,7 @@ MYSQL_ROOT_PASSWORD=changeme1234
# REQUIRED: BASIC APP SETTINGS
# --------------------------------------------
APP_ENV=develop
APP_DEBUG=true
APP_DEBUG=false
# please regenerate the APP_KEY value by calling `docker-compose run --rm snipeit bash` and then `php artisan key:generate --show` and then copy paste the value here
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
APP_URL=http://localhost:8000
@@ -158,7 +158,7 @@ RESET_PASSWORD_LINK_EXPIRES=900
# --------------------------------------------
# OPTIONAL: MISC
# --------------------------------------------
LOG_CHANNEL=single
LOG_CHANNEL=stderr
LOG_MAX_DAYS=10
APP_LOCKED=false
APP_CIPHER=AES-256-CBC

View File

@@ -1,7 +1,7 @@
# --------------------------------------------
# REQUIRED: DOCKER SPECIFIC SETTINGS
# --------------------------------------------
APP_VERSION=
APP_VERSION=v6.4.1
APP_PORT=8000
# --------------------------------------------
@@ -9,7 +9,7 @@ APP_PORT=8000
# --------------------------------------------
APP_ENV=production
APP_DEBUG=false
# Please regenerate the APP_KEY value by calling `docker compose run --rm app php artisan key:generate --show`. Copy paste the value here
# Please regenerate the APP_KEY value by calling `docker compose run --rm snipeit php artisan key:generate --show`. Copy paste the value here
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
APP_URL=http://localhost:8000
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones - TZ identifier

View File

@@ -80,12 +80,6 @@ MAIL_BACKUP_NOTIFICATION_ADDRESS=null
BACKUP_ENV=true
ALLOW_BACKUP_DELETE=false
ALLOW_DATA_PURGE=false
ALL_BACKUP_KEEP_DAYS=7
DAILY_BACKUP_KEEP_DAYS=16
WEEKLY_BACKUP_KEEP_WEEKS=8
MONTHLY_BACKUP_KEEP_MONTHS=4
YEARLY_BACKUP_KEEP_YEARS=2
BACKUP_PURGE_OLDEST_AT_MEGS=5000
# --------------------------------------------
# OPTIONAL: SESSION SETTINGS

View File

@@ -52,8 +52,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars.githubusercontent.com/u/47315739?v=4" width="110px;"/><br /><sub>bilias</sub>](https://github.com/bilias)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bilias "Code") | [<img src="https://avatars.githubusercontent.com/u/2565989?v=4" width="110px;"/><br /><sub>coach1988</sub>](https://github.com/coach1988)<br />[💻](https://github.com/snipe/snipe-it/commits?author=coach1988 "Code") | [<img src="https://avatars.githubusercontent.com/u/11910225?v=4" width="110px;"/><br /><sub>MrM</sub>](https://github.com/mauro-miatello)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mauro-miatello "Code") | [<img src="https://avatars.githubusercontent.com/u/60405354?v=4" width="110px;"/><br /><sub>koiakoia</sub>](https://github.com/koiakoia)<br />[💻](https://github.com/snipe/snipe-it/commits?author=koiakoia "Code") | [<img src="https://avatars.githubusercontent.com/u/5323832?v=4" width="110px;"/><br /><sub>Mustafa Online</sub>](https://github.com/mustafa-online)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mustafa-online "Code") | [<img src="https://avatars.githubusercontent.com/u/104601439?v=4" width="110px;"/><br /><sub>franceslui</sub>](https://github.com/franceslui)<br />[💻](https://github.com/snipe/snipe-it/commits?author=franceslui "Code") | [<img src="https://avatars.githubusercontent.com/u/125313163?v=4" width="110px;"/><br /><sub>Q4kK</sub>](https://github.com/Q4kK)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Q4kK "Code") |
| [<img src="https://avatars.githubusercontent.com/u/55590532?v=4" width="110px;"/><br /><sub>squintfox</sub>](https://github.com/squintfox)<br />[💻](https://github.com/snipe/snipe-it/commits?author=squintfox "Code") | [<img src="https://avatars.githubusercontent.com/u/1380084?v=4" width="110px;"/><br /><sub>Jeff Clay</sub>](https://github.com/jeffclay)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jeffclay "Code") | [<img src="https://avatars.githubusercontent.com/u/52716446?v=4" width="110px;"/><br /><sub>Phil J R</sub>](https://github.com/PP-JN-RL)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PP-JN-RL "Code") | [<img src="https://avatars.githubusercontent.com/u/1496725?v=4" width="110px;"/><br /><sub>i_virus</sub>](https://www.corelight.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chandanchowdhury "Code") | [<img src="https://avatars.githubusercontent.com/u/1020541?v=4" width="110px;"/><br /><sub>Paul Grime</sub>](https://github.com/gitgrimbo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gitgrimbo "Code") | [<img src="https://avatars.githubusercontent.com/u/922815?v=4" width="110px;"/><br /><sub>Lee Porte</sub>](https://leeporte.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=LeePorte "Code") | [<img src="https://avatars.githubusercontent.com/u/23613427?v=4" width="110px;"/><br /><sub>BRYAN </sub>](https://github.com/bryanlopezinc)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Code") [⚠️](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Tests") |
| [<img src="https://avatars.githubusercontent.com/u/64061710?v=4" width="110px;"/><br /><sub>U-H-T</sub>](https://github.com/U-H-T)<br />[💻](https://github.com/snipe/snipe-it/commits?author=U-H-T "Code") | [<img src="https://avatars.githubusercontent.com/u/5395363?v=4" width="110px;"/><br /><sub>Matt Tyree</sub>](https://github.com/Tyree)<br />[📖](https://github.com/snipe/snipe-it/commits?author=Tyree "Documentation") | [<img src="https://avatars.githubusercontent.com/u/292081?v=4" width="110px;"/><br /><sub>Florent Bervas</sub>](http://spoontux.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FlorentDotMe "Code") | [<img src="https://avatars.githubusercontent.com/u/4498077?v=4" width="110px;"/><br /><sub>Daniel Albertsen</sub>](https://ditscheri.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dbakan "Code") | [<img src="https://avatars.githubusercontent.com/u/100710244?v=4" width="110px;"/><br /><sub>r-xyz</sub>](https://github.com/r-xyz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=r-xyz "Code") | [<img src="https://avatars.githubusercontent.com/u/47491036?v=4" width="110px;"/><br /><sub>Steven Mainor</sub>](https://github.com/DrekiDegga)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DrekiDegga "Code") | [<img src="https://avatars.githubusercontent.com/u/65785975?v=4" width="110px;"/><br /><sub>arne-kroeger</sub>](https://github.com/arne-kroeger)<br />[💻](https://github.com/snipe/snipe-it/commits?author=arne-kroeger "Code") |
| [<img src="https://avatars.githubusercontent.com/u/167117705?v=4" width="110px;"/><br /><sub>Glukose1</sub>](https://github.com/Glukose1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Glukose1 "Code") | [<img src="https://avatars.githubusercontent.com/u/1197791?v=4" width="110px;"/><br /><sub>Scarzy</sub>](https://github.com/Scarzy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Scarzy "Code") | [<img src="https://avatars.githubusercontent.com/u/37372069?v=4" width="110px;"/><br /><sub>setpill</sub>](https://github.com/setpill)<br />[💻](https://github.com/snipe/snipe-it/commits?author=setpill "Code") | [<img src="https://avatars.githubusercontent.com/u/3755203?v=4" width="110px;"/><br /><sub>swift2512</sub>](https://github.com/swift2512)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aswift2512 "Bug reports") | [<img src="https://avatars.githubusercontent.com/u/6136439?v=4" width="110px;"/><br /><sub>Darren Rainey</sub>](https://darrenraineys.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DarrenRainey "Code") | [<img src="https://avatars.githubusercontent.com/u/133033121?v=4" width="110px;"/><br /><sub>maciej-poleszczyk</sub>](https://github.com/maciej-poleszczyk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=maciej-poleszczyk "Code") | [<img src="https://avatars.githubusercontent.com/u/143394709?v=4" width="110px;"/><br /><sub>Sebastian Groß</sub>](https://github.com/sgross-emlix)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sgross-emlix "Code") |
| [<img src="https://avatars.githubusercontent.com/u/41107778?v=4" width="110px;"/><br /><sub>Anouar Touati</sub>](https://github.com/AnouarTouati)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AnouarTouati "Code") | [<img src="https://avatars.githubusercontent.com/u/25596663?v=4" width="110px;"/><br /><sub>aHVzY2g</sub>](https://github.com/aHVzY2g)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aHVzY2g "Code") | [<img src="https://avatars.githubusercontent.com/u/13408130?v=4" width="110px;"/><br /><sub>林博仁 Buo-ren Lin</sub>](https://brlin.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=brlin-tw "Code") |
| [<img src="https://avatars.githubusercontent.com/u/167117705?v=4" width="110px;"/><br /><sub>Glukose1</sub>](https://github.com/Glukose1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Glukose1 "Code") | [<img src="https://avatars.githubusercontent.com/u/1197791?v=4" width="110px;"/><br /><sub>Scarzy</sub>](https://github.com/Scarzy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Scarzy "Code") | [<img src="https://avatars.githubusercontent.com/u/37372069?v=4" width="110px;"/><br /><sub>setpill</sub>](https://github.com/setpill)<br />[💻](https://github.com/snipe/snipe-it/commits?author=setpill "Code") | [<img src="https://avatars.githubusercontent.com/u/3755203?v=4" width="110px;"/><br /><sub>swift2512</sub>](https://github.com/swift2512)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aswift2512 "Bug reports") | [<img src="https://avatars.githubusercontent.com/u/6136439?v=4" width="110px;"/><br /><sub>Darren Rainey</sub>](https://darrenraineys.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DarrenRainey "Code") | [<img src="https://avatars.githubusercontent.com/u/133033121?v=4" width="110px;"/><br /><sub>maciej-poleszczyk</sub>](https://github.com/maciej-poleszczyk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=maciej-poleszczyk "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!

View File

@@ -73,7 +73,7 @@ RUN mkdir -p /var/www/.composer && chown apache /var/www/.composer
# Install dependencies
USER apache
RUN COMPOSER_CACHE_DIR=/dev/null composer install --working-dir=/var/www/html
RUN COMPOSER_CACHE_DIR=/dev/null composer install --no-dev --working-dir=/var/www/html
USER root

View File

@@ -427,13 +427,7 @@ class LdapSync extends Command
$user->groups()->attach($ldap_default_group);
}
//updates assets location based on user's location
if ($user->wasChanged('location_id')) {
foreach ($user->assets as $asset) {
$asset->location_id = $user->location_id;
// TODO: somehow add note? "Asset Location Changed because of thing"
$asset->save();
}
}
Asset::where('assigned_to', '=', $user->id)->where('assigned_type', '=', User::class)->update(['location_id' => $user->location_id]);
} else {
foreach ($user->getErrors()->getMessages() as $key => $err) {

View File

@@ -59,7 +59,7 @@ class ObjectImportCommand extends Command
$classString = "App\\Importer\\{$class}Importer";
$importer = new $classString($filename);
$importer->setCallbacks([$this, 'log'], [$this, 'progress'], [$this, 'errorCallback'])
->setCreatedBy($this->option('user_id'))
->setUserId($this->option('user_id'))
->setUpdating($this->option('update'))
->setShouldNotify($this->option('send-welcome'))
->setUsernameFormat($this->option('username_format'));

View File

@@ -50,12 +50,12 @@ class ResetDemoSettings extends Command
$settings->alert_email = 'service@snipe-it.io';
$settings->login_note = 'Use `admin` / `password` to login to the demo.';
$settings->header_color = null;
$settings->label2_2d_type = 'QRCODE';
$settings->barcode_type = 'QRCODE';
$settings->default_currency = 'USD';
$settings->brand = 2;
$settings->ldap_enabled = 0;
$settings->full_multiple_companies_support = 0;
$settings->label2_1d_type = 'C128';
$settings->alt_barcode = 'C128';
$settings->skin = '';
$settings->email_domain = 'snipeitapp.com';
$settings->email_format = 'filastname';
@@ -65,7 +65,7 @@ class ResetDemoSettings extends Command
$settings->thumbnail_max_h = '30';
$settings->locale = 'en-US';
$settings->version_footer = 'on';
$settings->support_footer = 'on';
$settings->support_footer = null;
$settings->saml_enabled = '0';
$settings->saml_sp_x509cert = null;
$settings->saml_idp_metadata = null;

View File

@@ -51,8 +51,6 @@ class SQLStreamer {
/* we *could* have made the ^INSERT INTO blah VALUES$ turn on the capturing state, and closed it with
a ^(blahblah);$ but it's cleaner to not have to manage the state machine. We're just going to
assume that (blahblah), or (blahblah); are values for INSERT and are always acceptable. */
"<^/\*!40101 SET NAMES '?[a-zA-Z0-9_-]+'? \*/;$>" => false, //using weird delimiters (<,>) for readability. allow quoted or unquoted charsets
"<^/\*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE='NO_AUTO_VALUE_ON_ZERO' \*/;$>" => false, //same, now handle zero-values
];
foreach($allowed_statements as $statement => $statechange) {
@@ -372,7 +370,7 @@ class RestoreFromBackup extends Command
if ($this->option('sanitize-guess-prefix')) {
$prefix = SQLStreamer::guess_prefix($sql_contents);
$this->line($prefix);
return $this->info("Re-run this command with '--sanitize-with-prefix=".$prefix."' to see an attempt to sanitize your SQL.");
return $this->info("Re-run this command with '--sanitize-with-prefix=".$prefix."' to see an attempt to sanitze your SQL.");
}
// If we're doing --sql-stdout-only, handle that now so we don't have to open pipes to mysql and all of that silliness

View File

@@ -72,7 +72,7 @@ class SendAcceptanceReminder extends Command
$locale = $acceptance->assignedTo?->locale;
$email = $acceptance->assignedTo?->email;
if(!$email){
$this->info($acceptance->assignedTo?->present()->fullName().' has no email address.');
$this->info($acceptance->assignedTo->present()->fullName().' has no email address.');
}
$item_count = $unacceptedAssetGroup->count();

View File

@@ -1,28 +0,0 @@
<?php
namespace App\Events;
use App\Models\User;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Queue\SerializesModels;
class NoteAdded
{
use Dispatchable, SerializesModels;
public $itemNoteAddedOn;
public $note;
public $noteAddedBy;
/**
* Create a new event instance.
*
* @return void
*/
public function __construct($itemNoteAddedOn, User $noteAddedBy, $note)
{
$this->itemNoteAddedOn = $itemNoteAddedOn;
$this->note = $note;
$this->noteAddedBy = $noteAddedBy;
}
}

View File

@@ -184,9 +184,7 @@ class IconHelper
return 'fa-regular fa-id-card';
case 'department' :
return 'fa-solid fa-building-user';
case 'note':
case 'notes':
return 'fas fa-sticky-note';
}
}
}

View File

@@ -31,7 +31,7 @@ class AccessoriesController extends Controller
public function index() : View
{
$this->authorize('index', Accessory::class);
return view('accessories.index');
return view('accessories/index');
}
/**
@@ -100,7 +100,7 @@ class AccessoriesController extends Controller
if ($item = Accessory::find($accessoryId)) {
$this->authorize($item);
return view('accessories.edit', compact('item'))->with('category_type', 'accessory');
return view('accessories/edit', compact('item'))->with('category_type', 'accessory');
}
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
@@ -236,7 +236,7 @@ class AccessoriesController extends Controller
$accessory = Accessory::withCount('checkouts as checkouts_count')->find($accessoryID);
$this->authorize('view', $accessory);
if (isset($accessory->id)) {
return view('accessories.view', compact('accessory'));
return view('accessories/view', compact('accessory'));
}
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist', ['id' => $accessoryID]));

View File

@@ -51,7 +51,7 @@ class AccessoriesFilesController extends Controller
}
return redirect()->route('accessories.show', $accessory->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
return redirect()->route('accessories.show', $accessory->id)->with('success', trans('general.file_upload_success'));
}
@@ -90,7 +90,8 @@ class AccessoriesFilesController extends Controller
$log->delete();
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}
// Redirect to the licence management page

View File

@@ -75,23 +75,20 @@ class AccessoryCheckoutController extends Controller
$accessory->checkout_qty = $request->input('checkout_qty', 1);
for ($i = 0; $i < $accessory->checkout_qty; $i++) {
$accessory_checkout = new AccessoryCheckout([
AccessoryCheckout::create([
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'created_by' => auth()->id(),
'assigned_to' => $target->id,
'assigned_type' => $target::class,
'note' => $request->input('note'),
]);
$accessory_checkout->created_by = auth()->id();
$accessory_checkout->save();
}
event(new CheckoutableCheckedOut($accessory, $target, auth()->user(), $request->input('note')));
// Set this as user since we only allow checkout to user for this item type
$request->request->add(['checkout_to_type' => request('checkout_to_type')]);
$request->request->add(['assigned_to' => $target->id]);
$request->request->add(['assigned_user' => $target->id]);
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);

View File

@@ -40,13 +40,10 @@ class ActionlogController extends Controller
public function getStoredEula($filename) : Response | BinaryFileResponse | RedirectResponse
{
$this->authorize('view', \App\Models\Asset::class);
if (config('filesystems.default') == 's3_private') {
return redirect()->away(Storage::disk('s3_private')->temporaryUrl('private_uploads/eula-pdfs/'.$filename, now()->addMinutes(5)));
}
$file = config('app.private_uploads').'/eula-pdfs/'.$filename;
if (Storage::exists('private_uploads/eula-pdfs/'.$filename)) {
return response()->download(config('app.private_uploads').'/eula-pdfs/'.$filename);
return response()->download($file);
}
return redirect()->back()->with('error', trans('general.file_does_not_exist'));

View File

@@ -13,7 +13,6 @@ use App\Http\Transformers\SelectlistTransformer;
use App\Models\Accessory;
use App\Models\Company;
use App\Models\User;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
@@ -185,33 +184,39 @@ class AccessoriesController extends Controller
/**
* Get the list of checkouts for a specific accessory
* Display the specified resource.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return | array
* @return \Illuminate\Http\Response
*/
public function checkedout(Request $request, $id)
public function checkedout($id, Request $request)
{
$this->authorize('view', Accessory::class);
$accessory = Accessory::with('lastCheckout')->findOrFail($id);
$offset = request('offset', 0);
$limit = request('limit', 50);
// Total count of all checkouts for this asset
$accessory_checkouts = $accessory->checkouts();
$accessory_checkouts = $accessory->checkouts;
$total = $accessory_checkouts->count();
// Check for search text in the request
if ($request->filled('search')) {
$accessory_checkouts = $accessory_checkouts->TextSearch($request->input('search'));
if ($total < $offset) {
$offset = 0;
}
$total = $accessory_checkouts->count();
$accessory_checkouts = $accessory_checkouts->skip($offset)->take($limit)->get();
$accessory_checkouts = $accessory->checkouts()->skip($offset)->take($limit)->get();
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory_checkouts, $total);
if ($request->filled('search')) {
$accessory_checkouts = $accessory->checkouts()->TextSearch($request->input('search'))
->get();
$total = $accessory_checkouts->count();
}
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $accessory_checkouts, $total);
}
@@ -222,7 +227,7 @@ class AccessoriesController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
* @return \Illuminate\Http\JsonResponse
* @return \Illuminate\Http\Response
*/
public function update(ImageUploadRequest $request, $id)
{
@@ -244,7 +249,7 @@ class AccessoriesController extends Controller
* @author [A. Gianotto] [<snipe@snipe.net>]
* @since [v4.0]
* @param int $id
* @return \Illuminate\Http\JsonResponse
* @return \Illuminate\Http\Response
*/
public function destroy($id)
{
@@ -279,17 +284,14 @@ class AccessoriesController extends Controller
$accessory->checkout_qty = $request->input('checkout_qty', 1);
for ($i = 0; $i < $accessory->checkout_qty; $i++) {
$accessory_checkout = new AccessoryCheckout([
AccessoryCheckout::create([
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'created_by' => auth()->id(),
'assigned_to' => $target->id,
'assigned_type' => $target::class,
'note' => $request->input('note'),
]);
$accessory_checkout->created_by = auth()->id();
$accessory_checkout->save();
}
// Set this value to be able to pass the qty through to the event

View File

@@ -122,7 +122,7 @@ class AssetMaintenancesController extends Controller
* @version v1.0
* @since [v1.8]
*/
public function store(Request $request) : JsonResponse | array
public function store(Request $request) : JsonResponse
{
$this->authorize('update', Asset::class);
// create a new model instance
@@ -149,7 +149,7 @@ class AssetMaintenancesController extends Controller
* @version v1.0
* @since [v4.0]
*/
public function update(Request $request, $id) : JsonResponse | array
public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', Asset::class);
@@ -186,7 +186,7 @@ class AssetMaintenancesController extends Controller
* @version v1.0
* @since [v4.0]
*/
public function destroy($assetMaintenanceId) : JsonResponse | array
public function destroy($assetMaintenanceId) : JsonResponse
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
@@ -208,7 +208,7 @@ class AssetMaintenancesController extends Controller
* @version v1.0
* @since [v4.0]
*/
public function show($assetMaintenanceId) : JsonResponse | array
public function show($assetMaintenanceId) : JsonResponse
{
$this->authorize('view', Asset::class);
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);

View File

@@ -9,7 +9,6 @@ use App\Http\Controllers\Controller;
use App\Models\AssetModel;
use App\Models\Actionlog;
use App\Http\Requests\UploadFileRequest;
use App\Http\Transformers\AssetModelsTransformer;
use Illuminate\Http\JsonResponse;
use Illuminate\Support\Facades\Log;
use Symfony\Component\HttpFoundation\StreamedResponse;
@@ -69,15 +68,37 @@ class AssetModelFilesController extends Controller
/**
* List the files for an asset.
*
* @param int $assetmodel
* @param int $assetModelId
* @since [v7.0.12]
* @author [r-xyz]
*/
public function list($assetmodel_id) : JsonResponse | array
public function list($assetModelId = null) : JsonResponse
{
$assetmodel = AssetModel::with('uploads')->find($assetmodel_id);
$this->authorize('view', $assetmodel);
return (new AssetModelsTransformer)->transformAssetModelFiles($assetmodel, $assetmodel->uploads()->count());
// Start by checking if the asset being acted upon exists
if (! $assetModel = AssetModel::find($assetModelId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.does_not_exist')), 404);
}
// the asset is valid
if (isset($assetModel->id)) {
$this->authorize('view', $assetModel);
// Check that there are some uploads on this asset that can be listed
if ($assetModel->uploads->count() > 0) {
$files = array();
foreach ($assetModel->uploads as $upload) {
array_push($files, $upload);
}
// Give the list of files back to the user
return response()->json(Helper::formatStandardApiResponse('success', $files, trans('admin/models/message.upload.success')));
}
// There are no files.
return response()->json(Helper::formatStandardApiResponse('success', array(), trans('admin/models/message.upload.success')));
}
// Send back an error message
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.download.error')), 500);
}
/**

View File

@@ -6,7 +6,6 @@ use App\Events\CheckoutableCheckedIn;
use App\Http\Requests\StoreAssetRequest;
use App\Http\Requests\UpdateAssetRequest;
use App\Http\Traits\MigratesLegacyAssetLocations;
use App\Models\AccessoryCheckout;
use App\Models\CheckoutAcceptance;
use App\Models\LicenseSeat;
use Illuminate\Database\Eloquent\Builder;
@@ -27,9 +26,11 @@ use App\Models\License;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Route;
use App\View\Label;
@@ -128,7 +129,6 @@ class AssetsController extends Controller
$assets = Asset::select('assets.*')
->with(
'model',
'location',
'assetstatus',
'company',
@@ -140,7 +140,7 @@ class AssetsController extends Controller
'model.manufacturer',
'model.fieldset',
'supplier'
); // it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
); //it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
if ($filter_non_deprecable_assets) {
@@ -1214,27 +1214,6 @@ class AssetsController extends Controller
return (new AssetsTransformer)->transformRequestedAssets($assets, $total);
}
public function assignedAssets(Request $request, Asset $asset) : JsonResponse | array
{
return [];
// to do
}
public function assignedAccessories(Request $request, Asset $asset) : JsonResponse | array
{
$this->authorize('view', Asset::class);
$this->authorize('view', $asset);
$accessory_checkouts = AccessoryCheckout::AssetsAssigned()->with('adminuser')->with('accessories');
$offset = ($request->input('offset') > $accessory_checkouts->count()) ? $accessory_checkouts->count() : app('api_offset_value');
$limit = app('api_limit_value');
$total = $accessory_checkouts->count();
$accessory_checkouts = $accessory_checkouts->skip($offset)->take($limit)->get();
return (new AssetsTransformer)->transformCheckedoutAccessories($accessory_checkouts, $total);
}
/**
* Generate asset labels by tag
*

View File

@@ -72,9 +72,6 @@ class DepartmentsController extends Controller
case 'manager':
$departments->OrderManager($order);
break;
case 'company':
$departments->OrderCompany($order);
break;
default:
$departments->orderBy($sort, $order);
break;

View File

@@ -9,14 +9,12 @@ use App\Http\Transformers\ImportsTransformer;
use App\Models\Asset;
use App\Models\Company;
use App\Models\Import;
use Illuminate\Http\UploadedFile;
use Illuminate\Support\Facades\Artisan;
use Illuminate\Database\Eloquent\JsonEncodingException;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
use League\Csv\Reader;
use Onnov\DetectEncoding\EncodingDetector;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
use Illuminate\Support\Facades\Log;
use Illuminate\Http\JsonResponse;
@@ -47,8 +45,6 @@ class ImportController extends Controller
$path = config('app.private_uploads').'/imports';
$results = [];
$import = new Import;
$detector = new EncodingDetector();
foreach ($files as $file) {
if (! in_array($file->getMimeType(), [
'application/vnd.ms-excel',
@@ -59,6 +55,7 @@ class ImportController extends Controller
'text/comma-separated-values',
'text/tsv', ])) {
$results['error'] = 'File type must be CSV. Uploaded file is '.$file->getMimeType();
return response()->json(Helper::formatStandardApiResponse('error', null, $results['error']), 422);
}
@@ -66,25 +63,7 @@ class ImportController extends Controller
if (! ini_get('auto_detect_line_endings')) {
ini_set('auto_detect_line_endings', '1');
}
$file_contents = $file->getContent(); //TODO - this *does* load the whole file in RAM, but we need that to be able to 'iconv' it?
$encoding = $detector->getEncoding($file_contents);
$reader = null;
if (strcasecmp($encoding, 'UTF-8') != 0) {
$transliterated = iconv($encoding, 'UTF-8', $file_contents);
if ($transliterated !== false) {
$tmpname = tempnam(sys_get_temp_dir(), '');
$tmpresults = file_put_contents($tmpname, $transliterated);
if ($tmpresults !== false) {
$transliterated = null; //save on memory?
$newfile = new UploadedFile($tmpname, $file->getClientOriginalName(), null, null, true); //WARNING: this is enabling 'test mode' - which is gross, but otherwise the file won't be treated as 'uploaded'
if ($newfile->isValid()) {
$file = $newfile;
}
}
}
}
$reader = Reader::createFromFileObject($file->openFile('r')); //file pointer leak?
$file_contents = null; //try to save on memory, I guess?
try {
$import->header_row = $reader->fetchOne(0);

View File

@@ -3,20 +3,17 @@
namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\ImageUploadRequest;
use App\Http\Transformers\AccessoriesTransformer;
use App\Http\Controllers\Controller;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\LocationsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Accessory;
use App\Models\AccessoryCheckout;
use App\Models\Asset;
use App\Models\Location;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
use Illuminate\Http\JsonResponse;
class LocationsController extends Controller
{
@@ -31,28 +28,26 @@ class LocationsController extends Controller
{
$this->authorize('view', Location::class);
$allowed_columns = [
'accessories_count',
'id',
'name',
'address',
'address2',
'assets_count',
'assets_count',
'assigned_accessories_count',
'assigned_assets_count',
'assigned_assets_count',
'city',
'country',
'created_at',
'currency',
'id',
'image',
'ldap_ou',
'manager_id',
'name',
'rtd_assets_count',
'state',
'updated_at',
'users_count',
'country',
'zip',
'created_at',
'updated_at',
'manager_id',
'image',
'assigned_assets_count',
'users_count',
'assets_count',
'assigned_assets_count',
'assets_count',
'rtd_assets_count',
'currency',
'ldap_ou',
];
$locations = Location::with('parent', 'manager', 'children')->select([
@@ -73,11 +68,8 @@ class LocationsController extends Controller
'locations.image',
'locations.ldap_ou',
'locations.currency',
])
->withCount('assignedAssets as assigned_assets_count')
])->withCount('assignedAssets as assigned_assets_count')
->withCount('assets as assets_count')
->withCount('assignedAccessories as assigned_accessories_count')
->withCount('accessories as accessories_count')
->withCount('rtd_assets as rtd_assets_count')
->withCount('children as children_count')
->withCount('users as users_count');
@@ -232,17 +224,7 @@ class LocationsController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, $location->getErrors()));
}
public function assets(Request $request, Location $location) : JsonResponse | array
{
$this->authorize('view', Asset::class);
$this->authorize('view', $location);
$assets = Asset::where('location_id', '=', $location->id)->with('model', 'model.category', 'assetstatus', 'location', 'company', 'defaultLoc');
$assets = $assets->get();
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
}
public function assignedAssets(Request $request, Location $location) : JsonResponse | array
{
$this->authorize('view', Asset::class);
$this->authorize('view', $location);
@@ -251,20 +233,6 @@ class LocationsController extends Controller
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
}
public function assignedAccessories(Request $request, Location $location) : JsonResponse | array
{
$this->authorize('view', Accessory::class);
$this->authorize('view', $location);
$accessory_checkouts = AccessoryCheckout::LocationAssigned()->with('adminuser')->with('accessories');
$offset = ($request->input('offset') > $accessory_checkouts->count()) ? $accessory_checkouts->count() : app('api_offset_value');
$limit = app('api_limit_value');
$total = $accessory_checkouts->count();
$accessory_checkouts = $accessory_checkouts->skip($offset)->take($limit)->get();
return (new LocationsTransformer)->transformCheckedoutAccessories($accessory_checkouts, $total);
}
/**
* Remove the specified resource from storage.
*

View File

@@ -1,43 +0,0 @@
<?php
namespace App\Http\Controllers\Api;
use App\Events\NoteAdded;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\Asset;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Validation\Rule;
class NotesController extends Controller
{
public function store(Request $request)
{
$validated = $request->validate([
'note' => 'required|string|max:500',
'type' => [
'required',
Rule::in(['asset']),
],
]);
// This can be made dynamic by using $request->input('type') to determine which model type to add the note to.
// For now, we are only placing this on Assets
$item = Asset::findOrFail($request->input("id"));
$this->authorize('update', $item);
event(new NoteAdded($item, Auth::user(), $validated['note']));
return response()->json(Helper::formatStandardApiResponse('success'));
}
public function update(Request $request)
{
}
public function destroy(Request $request)
{
}
}

View File

@@ -20,7 +20,6 @@ use App\Models\License;
use App\Models\User;
use App\Notifications\CurrentInventory;
use Illuminate\Support\Facades\Auth;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
@@ -81,16 +80,7 @@ class UsersController extends Controller
'users.website',
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy', 'managesUsers', 'managedLocations')
->withCount([
'assets as assets_count' => function(Builder $query) {
$query->withoutTrashed();
},
'licenses as licenses_count',
'accessories as accessories_count',
'consumables as consumables_count',
'managesUsers as manages_users_count',
'managedLocations as manages_locations_count'
]);
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count');
if ($request->filled('search') != '') {

View File

@@ -44,10 +44,10 @@ class AssetModelsFilesController extends Controller
$model->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->withFragment('files')->with('success', trans('general.file_upload_success'));
return redirect()->back()->with('success', trans('general.file_upload_success'));
}
return redirect()->back()->withFragment('files')->with('error', trans('admin/hardware/message.upload.nofiles'));
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
}
/**
@@ -119,10 +119,11 @@ class AssetModelsFilesController extends Controller
}
$log->delete();
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
return redirect()->back()->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}
// Redirect to the hardware management page

View File

@@ -45,7 +45,7 @@ class AssetFilesController extends Controller
$asset->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.upload.success'));
return redirect()->back()->with('success', trans('admin/hardware/message.upload.success'));
}
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
@@ -97,19 +97,25 @@ class AssetFilesController extends Controller
*/
public function destroy($assetId = null, $fileId = null) : RedirectResponse
{
if ($asset = Asset::find($assetId)) {
$this->authorize('update', $asset);
$rel_path = 'private_uploads/assets';
$asset = Asset::find($assetId);
$this->authorize('update', $asset);
$rel_path = 'private_uploads/assets';
if ($log = Actionlog::find($fileId)) {
// the asset is valid
if (isset($asset->id)) {
$this->authorize('update', $asset);
$log = Actionlog::find($fileId);
if ($log) {
if (Storage::exists($rel_path.'/'.$log->filename)) {
Storage::delete($rel_path.'/'.$log->filename);
}
$log->delete();
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
return redirect()->back()->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->route('hardware.show', ['hardware' => $asset])->with('error', trans('general.log_record_not_found'));
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));

View File

@@ -538,7 +538,7 @@ class AssetsController extends Controller
if ($settings->qr_code == '1') {
$asset = Asset::withTrashed()->find($assetId);
if ($asset) {
$size = Helper::barcodeDimensions($settings->label2_2d_type);
$size = Helper::barcodeDimensions($settings->barcode_type);
$qr_file = public_path().'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png';
if (isset($asset->id, $asset->asset_tag)) {
@@ -548,7 +548,7 @@ class AssetsController extends Controller
return response()->file($qr_file, $header);
} else {
$barcode = new \Com\Tecnick\Barcode\Barcode();
$barcode_obj = $barcode->getBarcodeObj($settings->label2_2d_type, route('hardware.show', $asset->id), $size['height'], $size['width'], 'black', [-2, -2, -2, -2]);
$barcode_obj = $barcode->getBarcodeObj($settings->barcode_type, route('hardware.show', $asset->id), $size['height'], $size['width'], 'black', [-2, -2, -2, -2]);
file_put_contents($qr_file, $barcode_obj->getPngData());
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
@@ -573,7 +573,7 @@ class AssetsController extends Controller
{
$settings = Setting::getSettings();
if ($asset = Asset::withTrashed()->find($assetId)) {
$barcode_file = public_path().'/uploads/barcodes/'.str_slug($settings->label2_1d_type).'-'.str_slug($asset->asset_tag).'.png';
$barcode_file = public_path().'/uploads/barcodes/'.str_slug($settings->alt_barcode).'-'.str_slug($asset->asset_tag).'.png';
if (isset($asset->id, $asset->asset_tag)) {
if (file_exists($barcode_file)) {
@@ -586,7 +586,7 @@ class AssetsController extends Controller
$barcode = new \Com\Tecnick\Barcode\Barcode();
try {
$barcode_obj = $barcode->getBarcodeObj($settings->label2_1d_type, $asset->asset_tag, ($barcode_width < 300 ? $barcode_width : 300), 50);
$barcode_obj = $barcode->getBarcodeObj($settings->alt_barcode, $asset->asset_tag, ($barcode_width < 300 ? $barcode_width : 300), 50);
file_put_contents($barcode_file, $barcode_obj->getPngData());
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
@@ -865,8 +865,8 @@ class AssetsController extends Controller
public function quickScan()
{
$this->authorize('audit', Asset::class);
$settings = Setting::getSettings();
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
$dt = Carbon::now()->addMonths(12)->toDateString();
return view('hardware/quickscan')->with('next_audit_date', $dt);
}
@@ -883,6 +883,7 @@ class AssetsController extends Controller
$this->authorize('audit', Asset::class);
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
$asset = Asset::findOrFail($id);
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt)->with('locations_list');
}

View File

@@ -50,14 +50,14 @@ class ForgotPasswordController extends Controller
*/
public function sendResetLinkEmail(Request $request)
{
/**
* Let's set a max character count here to prevent potential
* buffer overflow issues with attackers sending very large
* payloads through. The addition of the string rule prevents attackers
* sending arrays through and causing 500s
* payloads through.
*/
$request->validate([
'username' => ['required', 'max:255', 'string'],
'username' => ['required', 'max:255'],
]);
/**

View File

@@ -103,24 +103,22 @@ class ResetPasswordController extends Controller
], $messages);
}
if ($user->ldap_import != '1') {
// set the response
$response = $broker->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
});
// set the response
$response = $broker->reset(
$this->credentials($request), function ($user, $password) {
$this->resetPassword($user, $password);
});
// Check if the password reset above actually worked
if ($response == \Password::PASSWORD_RESET) {
Log::debug('Password reset for ' . $user->username . ' worked');
return redirect()->guest('login')->with('success', trans('passwords.reset'));
}
Log::debug('Password reset for ' . $user->username . ' FAILED - this user exists but the token is not valid');
return redirect()->back()->withInput($request->only('email'))->with('success', trans('passwords.reset'));
// Check if the password reset above actually worked
if ($response == \Password::PASSWORD_RESET) {
Log::debug('Password reset for '.$user->username.' worked');
return redirect()->guest('login')->with('success', trans('passwords.reset'));
}
Log::debug('Password reset for '.$user->username.' FAILED - this user exists but the token is not valid');
return redirect()->back()->withInput($request->only('email'))->with('success', trans('passwords.reset'));
}

View File

@@ -50,7 +50,7 @@ class ComponentsFilesController extends Controller
}
return redirect()->route('components.show', $component->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
return redirect()->route('components.show', $component->id)->with('success', trans('general.file_upload_success'));
}
@@ -91,7 +91,7 @@ class ComponentsFilesController extends Controller
$log->delete();
return redirect()->back()->withFragment('files')
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}

View File

@@ -50,7 +50,7 @@ class ConsumablesController extends Controller
{
$this->authorize('create', Consumable::class);
return view('consumables.edit')->with('category_type', 'consumable')
return view('consumables/edit')->with('category_type', 'consumable')
->with('item', new Consumable);
}

View File

@@ -48,7 +48,7 @@ class ConsumablesFilesController extends Controller
}
return redirect()->route('consumables.show', $consumable->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
return redirect()->route('consumables.show', $consumable->id)->with('success', trans('general.file_upload_success'));
}
@@ -89,7 +89,7 @@ class ConsumablesFilesController extends Controller
$log->delete();
return redirect()->back()->withFragment('files')
return redirect()->back()
->with('success', trans('admin/hardware/message.deletefile.success'));
}

View File

@@ -104,7 +104,7 @@ class CustomFieldsController extends Controller
"auto_add_to_fieldsets" => $request->get("auto_add_to_fieldsets", 0),
"show_in_listview" => $request->get("show_in_listview", 0),
"show_in_requestable_list" => $request->get("show_in_requestable_list", 0),
"created_by" => auth()->id()
"user_id" => auth()->id()
]);

View File

@@ -71,7 +71,7 @@ class LicenseCheckinController extends Controller
if (! $license->reassignable) {
// Not allowed to checkin
Session::flash('error', trans('admin/licenses/message.checkin.not_reassignable') . '.');
Session::flash('error', 'License not reassignable.');
return redirect()->back()->withInput();
}

View File

@@ -32,8 +32,7 @@ class ModalController extends Controller
'statuslabel',
'supplier',
'upload-file',
'user',
'add-note',
'user',
];

View File

@@ -99,13 +99,9 @@ class ProfileController extends Controller
* User change email page.
*
*/
public function password() : View | RedirectResponse
public function password() : View
{
$user = auth()->user();
if ($user->ldap_import=='1') {
return redirect()->route('account')->with('error', trans('admin/users/message.error.password_ldap'));
}
return view('account/change-password', compact('user'));
}
@@ -120,7 +116,7 @@ class ProfileController extends Controller
$user = auth()->user();
if ($user->ldap_import == '1') {
return redirect()->route('account')->with('error', trans('admin/users/message.error.password_ldap'));
return redirect()->route('account.password.index')->with('error', trans('admin/users/message.error.password_ldap'));
}
$rules = [

View File

@@ -1,80 +0,0 @@
<?php
namespace App\Http\Controllers;
use App\Models\CustomField;
use App\Models\ReportTemplate;
use Illuminate\Http\RedirectResponse;
use Illuminate\Http\Request;
use Illuminate\Support\Arr;
class ReportTemplatesController extends Controller
{
public function store(Request $request): RedirectResponse
{
$this->authorize('reports.view');
// Ignore "options" rules since data does not come in under that key...
$validated = $request->validate(Arr::except((new ReportTemplate)->getRules(), 'options'));
$report = $request->user()->reportTemplates()->create([
'name' => $validated['name'],
'options' => $request->except(['_token', 'name']),
]);
session()->flash('success', trans('admin/reports/message.create.success'));
return redirect()->route('report-templates.show', $report->id);
}
public function show(ReportTemplate $reportTemplate)
{
$this->authorize('reports.view');
$customfields = CustomField::get();
$report_templates = ReportTemplate::orderBy('name')->get();
return view('reports/custom', [
'customfields' => $customfields,
'report_templates' => $report_templates,
'template' => $reportTemplate,
]);
}
public function edit(ReportTemplate $reportTemplate)
{
$this->authorize('reports.view');
return view('reports/custom', [
'customfields' => CustomField::get(),
'template' => $reportTemplate,
]);
}
public function update(Request $request, ReportTemplate $reportTemplate): RedirectResponse
{
$this->authorize('reports.view');
// Ignore "options" rules since data does not come in under that key...
$validated = $request->validate(Arr::except((new ReportTemplate)->getRules(), 'options'));
$reportTemplate->update([
'name' => $validated['name'],
'options' => $request->except(['_token', 'name']),
]);
session()->flash('success', trans('admin/reports/message.update.success'));
return redirect()->route('report-templates.show', $reportTemplate->id);
}
public function destroy(ReportTemplate $reportTemplate): RedirectResponse
{
$this->authorize('reports.view');
$reportTemplate->delete();
return redirect()->route('reports/custom')
->with('success', trans('admin/reports/message.delete.success'));
}
}

View File

@@ -11,15 +11,12 @@ use App\Models\AssetModel;
use App\Models\Category;
use App\Models\AssetMaintenance;
use App\Models\CheckoutAcceptance;
use App\Models\Company;
use App\Models\CustomField;
use App\Models\Depreciation;
use App\Models\License;
use App\Models\ReportTemplate;
use App\Models\Setting;
use App\Notifications\CheckoutAssetNotification;
use Carbon\Carbon;
use Illuminate\Database\Eloquent\Relations\MorphTo;
use Illuminate\Http\Request;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\Mail;
@@ -397,27 +394,12 @@ class ReportsController extends Controller
* @see ReportsController::postCustomReport() method that generates the CSV
* @since [v1.0]
*/
public function getCustomReport(Request $request) : View
public function getCustomReport() : View
{
$this->authorize('reports.view');
$customfields = CustomField::get();
$report_templates = ReportTemplate::orderBy('name')->get();
// The view needs a template to render correctly, even if it is empty...
$template = new ReportTemplate;
// Set the report's input values in the cases we were redirected back
// with validation errors so the report is populated as expected.
if ($request->old()) {
$template->name = $request->old('name');
$template->options = $request->old();
}
return view('reports/custom', [
'customfields' => $customfields,
'report_templates' => $report_templates,
'template' => $template,
]);
return view('reports/custom')->with('customfields', $customfields);
}
/**
@@ -1111,31 +1093,28 @@ class ReportsController extends Controller
$this->authorize('reports.view');
$showDeleted = $deleted == 'deleted';
$query = CheckoutAcceptance::pending()
->where('checkoutable_type', 'App\Models\Asset')
->with([
'checkoutable' => function (MorphTo $query) {
$query->morphWith([
AssetModel::class => ['model'],
Company::class => ['company'],
Asset::class => ['assignedTo'],
])->with('model.category');
},
'assignedTo' => function($query){
$query->withTrashed();
}
]);
if ($showDeleted) {
$query->withTrashed();
/**
* Get all assets with pending checkout acceptances
*/
if($showDeleted) {
$acceptances = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')->withTrashed()->with(['assignedTo' , 'checkoutable.assignedTo', 'checkoutable.model'])->get();
} else {
$acceptances = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')->with(['assignedTo' => function ($query) {
$query->withTrashed();
}, 'checkoutable.assignedTo', 'checkoutable.model'])->get();
}
$assetsForReport = $query->get()
->map(function ($acceptance) {
return [
'assetItem' => $acceptance->checkoutable,
'acceptance' => $acceptance,
];
$assetsForReport = $acceptances
->filter(function ($acceptance) {
$acceptance_checkoutable_flag = false;
if ($acceptance->checkoutable){
$acceptance_checkoutable_flag = $acceptance->checkoutable->checkedOutToUser();
}
return $acceptance->checkoutable_type == 'App\Models\Asset' && $acceptance_checkoutable_flag;
})
->map(function($acceptance) {
return ['assetItem' => $acceptance->checkoutable, 'acceptance' => $acceptance];
});
return view('reports/unaccepted_assets', compact('assetsForReport','showDeleted' ));
@@ -1177,10 +1156,10 @@ class ReportsController extends Controller
$locale = $assetItem->assignedTo?->locale;
// Only send notification if assigned
if ($locale && $email) {
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note))->locale($locale));
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $logItem->note, $acceptance))->locale($locale));
} elseif ($email) {
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note)));
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $logItem->note, $acceptance)));
}
if ($email == ''){

View File

@@ -192,7 +192,6 @@ class SettingsController extends Controller
$settings->next_auto_tag_base = 1;
$settings->auto_increment_assets = $request->input('auto_increment_assets', 0);
$settings->auto_increment_prefix = $request->input('auto_increment_prefix');
$settings->zerofill_count = $request->input('zerofill_count') ?: 0;
if ((! $user->isValid()) || (! $settings->isValid())) {
return redirect()->back()->withInput()->withErrors($user->getErrors())->withErrors($settings->getErrors());
@@ -696,6 +695,48 @@ class SettingsController extends Controller
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
*
* @since [v1.0]
*/
public function getBarcodes() : View
{
$setting = Setting::getSettings();
$is_gd_installed = extension_loaded('gd');
return view('settings.barcodes', compact('setting'))->with('is_gd_installed', $is_gd_installed);
}
/**
* Saves settings from form.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
*
* @since [v1.0]
*/
public function postBarcodes(Request $request) : RedirectResponse
{
if (is_null($setting = Setting::getSettings())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$setting->qr_code = $request->input('qr_code', '0');
$setting->alt_barcode = $request->input('alt_barcode');
$setting->alt_barcode_enabled = $request->input('alt_barcode_enabled', '0');
$setting->barcode_type = $request->input('barcode_type');
$setting->qr_text = $request->input('qr_text');
if ($setting->save()) {
return redirect()->route('settings.index')
->with('success', trans('admin/settings/message.update.success'));
}
return redirect()->back()->withInput()->withErrors($setting->getErrors());
}
/**
* Return a form to allow a super admin to update settings.
*
@@ -721,11 +762,8 @@ class SettingsController extends Controller
*/
public function getLabels() : View
{
$is_gd_installed = extension_loaded('gd');
return view('settings.labels')
->with('setting', Setting::getSettings())
->with('is_gd_installed', $is_gd_installed)
->with('customFields', CustomField::where('field_encrypted', '=', 0)->get());
}
@@ -761,13 +799,9 @@ class SettingsController extends Controller
$setting->labels_pagewidth = $request->input('labels_pagewidth');
$setting->labels_pageheight = $request->input('labels_pageheight');
$setting->labels_display_company_name = $request->input('labels_display_company_name', '0');
$setting->labels_display_company_name = $request->input('labels_display_company_name', '0');
//Barcodes
$setting->qr_code = $request->input('qr_code', '0');
//1D-Barcode
$setting->alt_barcode_enabled = $request->input('alt_barcode_enabled', '0');
//QR-Code
$setting->qr_text = $request->input('qr_text');
if ($request->filled('labels_display_name')) {
$setting->labels_display_name = 1;

View File

@@ -70,7 +70,7 @@ class BulkUsersController extends Controller
// bulk password reset, just do the thing
} elseif ($request->input('bulk_actions') == 'bulkpasswordreset') {
foreach ($users as $user) {
if (($user->activated == '1') && ($user->email != '') && ($user->ldap_import != '1')) {
if (($user->activated == '1') && ($user->email != '')) {
$credentials = ['email' => $user->email];
Password::sendResetLink($credentials/* , function (Message $message) {
$message->subject($this->getEmailSubject()); // TODO - I'm not sure if we still need this, but this second parameter is no longer accepted in later Laravel versions.

View File

@@ -56,7 +56,7 @@ class UserFilesController extends Controller
$logActions[] = $logAction;
}
// dd($logActions);
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.upload.success'));
return redirect()->back()->with('success', trans('admin/users/message.upload.success'));
}
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
@@ -87,7 +87,7 @@ class UserFilesController extends Controller
if (Storage::exists($rel_path.'/'.$filename)) {
Storage::delete($rel_path.'/'.$filename);
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.deletefile.success'));
return redirect()->back()->with('success', trans('admin/users/message.deletefile.success'));
}
}

View File

@@ -24,9 +24,9 @@ class AssetCheckoutRequest extends Request
$settings = \App\Models\Setting::getSettings();
$rules = [
'assigned_user' => 'numeric|nullable|required_without_all:assigned_asset,assigned_location',
'assigned_asset' => 'numeric|nullable|required_without_all:assigned_user,assigned_location',
'assigned_location' => 'numeric|nullable|required_without_all:assigned_user,assigned_asset',
'assigned_user' => 'required_without_all:assigned_asset,assigned_location',
'assigned_asset' => 'required_without_all:assigned_user,assigned_location',
'assigned_location' => 'required_without_all:assigned_user,assigned_asset',
'status_id' => 'exists:status_labels,id,deployable,1',
'checkout_to_type' => 'required|in:asset,location,user',
'checkout_at' => [

View File

@@ -7,6 +7,7 @@ use Illuminate\Contracts\Validation\Validator;
use Illuminate\Foundation\Http\FormRequest;
use Illuminate\Http\Exceptions\HttpResponseException;
use App\Rules\UserCannotSwitchCompaniesIfItemsAssigned;
use Illuminate\Support\Facades\Gate;
class SaveUserRequest extends FormRequest
{
@@ -17,7 +18,7 @@ class SaveUserRequest extends FormRequest
*/
public function authorize()
{
return true;
return (Gate::allows('users.create') || Gate::allows('users.edit'));
}
public function response(array $errors)
@@ -35,7 +36,8 @@ class SaveUserRequest extends FormRequest
$rules = [
'department_id' => 'nullable|exists:departments,id',
'manager_id' => 'nullable|exists:users,id',
'company_id' => ['nullable','exists:companies,id']
'company_id' => ['nullable','exists:companies,id'],
'groups' => ['nullable','exists:permission_groups,id']
];
switch ($this->method()) {

View File

@@ -46,6 +46,8 @@ class UploadFileRequest extends Request
$extension = $file->getClientOriginalExtension();
$file_name = $name_prefix.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$file->guessExtension();
Log::debug("Your filetype IS: ".$file->getMimeType());
// Check for SVG and sanitize it
if ($file->getMimeType() === 'image/svg+xml') {
Log::debug('This is an SVG');
@@ -64,6 +66,7 @@ class UploadFileRequest extends Request
} else {
$put_results = Storage::put($dirname.$file_name, file_get_contents($file));
Log::debug("Here are the '$put_results' (should be 0 or 1 or true or false or something?)");
}
return $file_name;
}

View File

@@ -69,7 +69,7 @@ class AccessoriesTransformer
return $array;
}
public function transformCheckedoutAccessory($accessory_checkouts, $total)
public function transformCheckedoutAccessory($accessory, $accessory_checkouts, $total)
{
$array = [];
@@ -77,13 +77,9 @@ class AccessoriesTransformer
$array[] = [
'id' => $checkout->id,
'assigned_to' => $this->transformAssignedTo($checkout),
'note' => $checkout->note ? e($checkout->note) : null,
'created_by' => $checkout->adminuser ? [
'id' => (int) $checkout->adminuser->id,
'name'=> e($checkout->adminuser->present()->fullName),
]: null,
'created_at' => Helper::getFormattedDateObject($checkout->created_at, 'datetime'),
'available_actions' => Gate::allows('checkout', Accessory::class) ? ['checkin' => true] : ['checkin' => false],
'checkout_notes' => e($checkout->note),
'last_checkout' => Helper::getFormattedDateObject($checkout->created_at, 'datetime'),
'available_actions' => ['checkin' => true],
];
}
@@ -93,11 +89,22 @@ class AccessoriesTransformer
public function transformAssignedTo($accessoryCheckout)
{
if ($accessoryCheckout->checkedOutToUser()) {
return (new UsersTransformer)->transformUserCompact($accessoryCheckout->assigned);
} elseif ($accessoryCheckout->checkedOutToLocation()) {
return (new LocationsTransformer())->transformLocationCompact($accessoryCheckout->assigned);
} elseif ($accessoryCheckout->checkedOutToAsset()) {
return (new AssetsTransformer())->transformAssetCompact($accessoryCheckout->assigned);
return [
'id' => (int) $accessoryCheckout->assigned->id,
'username' => e($accessoryCheckout->assigned->username),
'name' => e($accessoryCheckout->assigned->getFullNameAttribute()),
'first_name'=> e($accessoryCheckout->assigned->first_name),
'last_name'=> ($accessoryCheckout->assigned->last_name) ? e($accessoryCheckout->assigned->last_name) : null,
'email'=> ($accessoryCheckout->assigned->email) ? e($accessoryCheckout->assigned->email) : null,
'employee_number' => ($accessoryCheckout->assigned->employee_num) ? e($accessoryCheckout->assigned->employee_num) : null,
'type' => 'user',
];
}
return $accessoryCheckout->assigned ? [
'id' => $accessoryCheckout->assigned->id,
'name' => e($accessoryCheckout->assigned->display_name),
'type' => $accessoryCheckout->assignedType(),
] : null;
}
}

View File

@@ -29,15 +29,14 @@ class AssetMaintenancesTransformer
'name'=> ($assetmaintenance->asset->name) ? e($assetmaintenance->asset->name) : null,
'asset_tag'=> e($assetmaintenance->asset->asset_tag),
'serial'=> e($assetmaintenance->asset->serial),
'deleted_at'=> Helper::getFormattedDateObject($assetmaintenance->asset->deleted_at, 'datetime'),
'created_at' => Helper::getFormattedDateObject($assetmaintenance->asset->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($assetmaintenance->asset->updated_at, 'datetime'),
'deleted_at'=> e($assetmaintenance->asset->deleted_at),
'created_at'=> e($assetmaintenance->asset->created_at),
] : null,
'model' => (($assetmaintenance->asset) && ($assetmaintenance->asset->model)) ? [
'id' => (int) $assetmaintenance->asset->model->id,
'name'=> ($assetmaintenance->asset->model->name) ? e($assetmaintenance->asset->model->name).' '.e($assetmaintenance->asset->model->model_number) : null,
] : null,
'status_label' => (($assetmaintenance->asset) && ($assetmaintenance->asset->assetstatus)) ? [
'status_label' => ($assetmaintenance->asset->assetstatus) ? [
'id' => (int) $assetmaintenance->asset->assetstatus->id,
'name'=> e($assetmaintenance->asset->assetstatus->name),
'status_type'=> e($assetmaintenance->asset->assetstatus->getStatuslabelType()),
@@ -80,7 +79,7 @@ class AssetMaintenancesTransformer
];
$permissions_array['available_actions'] = [
'update' => (Gate::allows('update', Asset::class) && ((($assetmaintenance->asset) && $assetmaintenance->asset->deleted_at==''))) ? true : false,
'update' => (Gate::allows('update', Asset::class) && ($assetmaintenance->asset->deleted_at=='')) ? true : false,
'delete' => Gate::allows('delete', Asset::class),
];

View File

@@ -87,41 +87,6 @@ class AssetModelsTransformer
return $array;
}
public function transformAssetModelFiles($assetmodel, $total)
{
$array = [];
foreach ($assetmodel->uploads as $file) {
$array[] = self::transformAssetModelFile($file, $assetmodel);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformAssetModelFile($file, $assetmodel)
{
$array = [
'id' => (int) $file->id,
'filename' => e($file->filename),
'url' => route('show/modelfile', [$assetmodel->id, $file->id]),
'created_by' => ($file->adminuser) ? [
'id' => (int) $file->adminuser->id,
'name'=> e($file->adminuser->present()->fullName),
] : null,
'created_at' => Helper::getFormattedDateObject($file->created_at, 'datetime'),
'updated_at' => Helper::getFormattedDateObject($file->updated_at, 'datetime'),
'deleted_at' => Helper::getFormattedDateObject($file->deleted_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'delete' => (Gate::allows('update', AssetModel::class) && ($assetmodel->deleted_at == '')),
];
$array += $permissions_array;
return $array;
}
public function transformAssetModelsDatatable($assetmodels)
{
return (new DatatablesTransformer)->transformDatatables($assetmodels);

View File

@@ -3,14 +3,12 @@
namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Accessory;
use App\Models\AccessoryCheckout;
use App\Models\Asset;
use App\Models\Setting;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
use Carbon\Carbon;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Auth;
class AssetsTransformer
{
@@ -227,7 +225,7 @@ class AssetsTransformer
public function transformRequestedAsset(Asset $asset)
{
$array = [
'id' => (int)$asset->id,
'id' => (int) $asset->id,
'name' => e($asset->name),
'asset_tag' => e($asset->asset_tag),
'serial' => e($asset->serial),
@@ -236,7 +234,7 @@ class AssetsTransformer
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
'expected_checkin' => Helper::getFormattedDateObject($asset->expected_checkin, 'date'),
'location' => ($asset->location) ? e($asset->location->name) : null,
'status' => ($asset->assetstatus) ? $asset->present()->statusMeta : null,
'status'=> ($asset->assetstatus) ? $asset->present()->statusMeta : null,
'assigned_to_self' => ($asset->assigned_to == auth()->id()),
];
@@ -246,7 +244,7 @@ class AssetsTransformer
foreach ($asset->model->fieldset->fields as $field) {
// Only display this if it's allowed via the custom field setting
if (($field->field_encrypted == '0') && ($field->show_in_requestable_list == '1')) {
if (($field->field_encrypted=='0') && ($field->show_in_requestable_list=='1')) {
$value = $asset->{$field->db_column};
if (($field->format == 'DATE') && (!is_null($value)) && ($value != '')) {
@@ -270,61 +268,7 @@ class AssetsTransformer
$array += $permissions_array;
return $array;
}
public function transformAssetCompact(Asset $asset)
{
$array = [
'id' => (int) $asset->id,
'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null,
'type' => 'asset',
'name' => e($asset->present()->fullName()),
'model' => ($asset->model) ? e($asset->model->name) : null,
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
'asset_tag' => e($asset->asset_tag),
'serial' => e($asset->serial),
];
return $array;
}
public function transformCheckedoutAccessories($accessory_checkouts, $total)
{
$array = [];
foreach ($accessory_checkouts as $checkout) {
$array[] = self::transformCheckedoutAccessory($checkout);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformCheckedoutAccessory(AccessoryCheckout $accessory_checkout)
{
$array = [
'id' => $accessory_checkout->id,
'accessory' => [
'id' => $accessory_checkout->accessory->id,
'name' => $accessory_checkout->accessory->name,
],
'image' => ($accessory_checkout->accessory->image) ? Storage::disk('public')->url('accessories/'.e($accessory_checkout->accessory->image)) : null,
'note' => $accessory_checkout->note ? e($accessory_checkout->note) : null,
'created_by' => $accessory_checkout->adminuser ? [
'id' => (int) $accessory_checkout->adminuser->id,
'name'=> e($accessory_checkout->adminuser->present()->fullName),
]: null,
'created_at' => Helper::getFormattedDateObject($accessory_checkout->created_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'checkout' => false,
'checkin' => Gate::allows('checkin', Accessory::class),
];
$array += $permissions_array;
return $array;
}
}

View File

@@ -3,8 +3,6 @@
namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Accessory;
use App\Models\AccessoryCheckout;
use App\Models\Location;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
@@ -47,8 +45,6 @@ class LocationsTransformer
'zip' => ($location->zip) ? e($location->zip) : null,
'phone' => ($location->phone!='') ? e($location->phone): null,
'fax' => ($location->fax!='') ? e($location->fax): null,
'accessories_count' => (int) $location->accessories_count,
'assigned_accessories_count' => (int) $location->assigned_accessories_count,
'assigned_assets_count' => (int) $location->assigned_assets_count,
'assets_count' => (int) $location->assets_count,
'rtd_assets_count' => (int) $location->rtd_assets_count,
@@ -80,75 +76,4 @@ class LocationsTransformer
return $array;
}
}
public function transformCheckedoutAccessories($accessory_checkouts, $total)
{
$array = [];
foreach ($accessory_checkouts as $checkout) {
$array[] = self::transformCheckedoutAccessory($checkout);
}
return (new DatatablesTransformer)->transformDatatables($array, $total);
}
public function transformCheckedoutAccessory(AccessoryCheckout $accessory_checkout)
{
$array = [
'id' => $accessory_checkout->id,
'accessory' => [
'id' => $accessory_checkout->accessory->id,
'name' => $accessory_checkout->accessory->name,
],
'image' => ($accessory_checkout->accessory->image) ? Storage::disk('public')->url('accessories/'.e($accessory_checkout->accessory->image)) : null,
'note' => $accessory_checkout->note ? e($accessory_checkout->note) : null,
'created_by' => $accessory_checkout->adminuser ? [
'id' => (int) $accessory_checkout->adminuser->id,
'name'=> e($accessory_checkout->adminuser->present()->fullName),
]: null,
'created_at' => Helper::getFormattedDateObject($accessory_checkout->created_at, 'datetime'),
];
$permissions_array['available_actions'] = [
'checkout' => false,
'checkin' => Gate::allows('checkin', Accessory::class),
];
$array += $permissions_array;
return $array;
}
/**
* This gives a compact view of the location data without any additional relational queries,
* allowing us to 1) deliver a smaller payload and 2) avoid additional queries on relations that
* have not been easy/lazy loaded already
*
* @param Location $location
* @return array
* @throws \Exception
*/
public function transformLocationCompact(Location $location = null)
{
if ($location) {
$array = [
'id' => (int) $location->id,
'image' => ($location->image) ? Storage::disk('public')->url('locations/'.e($location->image)) : null,
'type' => "location",
'name' => e($location->name),
'created_by' => $location->adminuser ? [
'id' => (int) $location->adminuser->id,
'name'=> e($location->adminuser->present()->fullName),
]: null,
'created_at' => Helper::getFormattedDateObject($location->created_at, 'datetime'),
];
return $array;
}
}
}
}

View File

@@ -3,7 +3,6 @@
namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\PredefinedKit;
use App\Models\SnipeModel;
use Illuminate\Support\Facades\Gate;
@@ -43,7 +42,7 @@ class PredefinedKitsTransformer
$permissions_array['available_actions'] = [
'update' => Gate::allows('update', PredefinedKit::class),
'delete' => Gate::allows('delete', PredefinedKit::class),
'checkout' => Gate::allows('checkout', Asset::class),
'checkout' => Gate::allows('checkout', PredefinedKit::class),
// 'clone' => Gate::allows('create', PredefinedKit::class),
// 'restore' => Gate::allows('create', PredefinedKit::class),
];

View File

@@ -4,8 +4,8 @@ namespace App\Http\Transformers;
use App\Helpers\Helper;
use App\Models\User;
use Illuminate\Database\Eloquent\Collection;
use Illuminate\Support\Facades\Gate;
use Illuminate\Database\Eloquent\Collection;
class UsersTransformer
{
@@ -106,37 +106,6 @@ class UsersTransformer
return $array;
}
/**
* This gives a compact view of the user data without any additional relational queries,
* allowing us to 1) deliver a smaller payload and 2) avoid additional queries on relations that
* have not been easy/lazy loaded already
*
* @param User $user
* @return array
* @throws \Exception
*/
public function transformUserCompact(User $user) : array
{
$array = [
'id' => (int) $user->id,
'image' => e($user->present()->gravatar) ?? null,
'type' => 'user',
'name' => e($user->getFullNameAttribute()),
'first_name' => e($user->first_name),
'last_name' => e($user->last_name),
'username' => e($user->username),
'created_by' => $user->adminuser ? [
'id' => (int) $user->adminuser->id,
'name'=> e($user->adminuser->present()->fullName),
]: null,
'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'),
'deleted_at' => ($user->deleted_at) ? Helper::getFormattedDateObject($user->deleted_at, 'datetime') : null,
];
return $array;
}
public function transformUsersDatatable($users)
{
return (new DatatablesTransformer)->transformDatatables($users);

View File

@@ -39,7 +39,6 @@ abstract class Importer
* @var array
*/
private $defaultFieldMap = [
'id' => 'id',
'asset_tag' => 'asset tag',
'activated' => 'activated',
'category' => 'category',

View File

@@ -456,13 +456,14 @@ class ItemImporter extends Importer
{
if (empty($asset_location)) {
$this->log('No location given, so none created.');
return null;
}
$location = Location::where(['name' => $asset_location])->first();
if ($location) {
$this->log('Location '.$asset_location.' already exists');
return $location->id;
}
// No matching locations in the collection, create a new one.

View File

@@ -38,16 +38,8 @@ class LocationImporter extends ItemImporter
{
$editingLocation = false;
$location = Location::where('name', '=', $this->findCsvMatch($row, 'name'))->first();
if ($this->findCsvMatch($row, 'id')!='') {
// Override location if an ID was given
\Log::debug('Finding location by ID: '.$this->findCsvMatch($row, 'id'));
$location = Location::find($this->findCsvMatch($row, 'id'));
}
if ($location) {
if (! $this->updating) {
$this->log('A matching Location '.$this->item['name'].' already exists');
@@ -103,7 +95,6 @@ class LocationImporter extends ItemImporter
} else {
Log::debug($location->getErrors());
$this->logError($location, 'Location "'.$this->item['name'].'"');
return $location->errors;
}

View File

@@ -46,7 +46,7 @@ class CheckoutableListener
*/
public function onCheckedOut($event)
{
if ($this->shouldNotSendAnyNotifications($event->checkoutable)) {
if ($this->shouldNotSendAnyNotifications($event->checkoutable)){
return;
}
@@ -57,7 +57,7 @@ class CheckoutableListener
$acceptance = $this->getCheckoutAcceptance($event);
$adminCcEmailsArray = [];
if ($settings->admin_cc_email !== '') {
if($settings->admin_cc_email !== '') {
$adminCcEmail = $settings->admin_cc_email;
$adminCcEmailsArray = array_map('trim', explode(',', $adminCcEmail));
}
@@ -65,7 +65,7 @@ class CheckoutableListener
$mailable = $this->getCheckoutMailType($event, $acceptance);
$notifiable = $this->getNotifiables($event);
if ($event->checkedOutTo->locale) {
if (!$event->checkedOutTo->locale){
$mailable->locale($event->checkedOutTo->locale);
}
// Send email notifications
@@ -77,50 +77,41 @@ class CheckoutableListener
* 3. The item should send an email at check-in/check-out
*/
if ($event->checkoutable->requireAcceptance() || $event->checkoutable->getEula() ||
$this->checkoutableShouldSendEmail($event)) {
Log::info('Sending checkout email, Locale: ' . ($event->checkedOutTo->locale ?? 'default'));
if (!empty($notifiable)) {
Mail::to($notifiable)->cc($ccEmails)->send($mailable);
} elseif (!empty($ccEmails)) {
Mail::cc($ccEmails)->send($mailable);
if ($event->checkoutable->requireAcceptance() || $event->checkoutable->getEula() ||
$this->checkoutableShouldSendEmail($event)) {
Log::info('Sending checkout email, Locale: ' . ($event->checkedOutTo->locale ?? 'default'));
if (!empty($notifiable)) {
Mail::to($notifiable)->cc($ccEmails)->send($mailable);
} elseif (!empty($ccEmails)) {
Mail::cc($ccEmails)->send($mailable);
}
Log::info('Checkout Mail sent.');
}
Log::info('Checkout Mail sent.');
}
} catch (ClientException $e) {
Log::debug("Exception caught during checkout email: " . $e->getMessage());
} catch (Exception $e) {
Log::debug("Exception caught during checkout email: " . $e->getMessage());
}
// Send Webhook notification
try {
if ($this->shouldSendWebhookNotification()) {
if ($this->newMicrosoftTeamsWebhookEnabled()) {
$message = $this->getCheckoutNotification($event)->toMicrosoftTeams();
$notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
$notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
} else {
Notification::route($this->webhookSelected(), Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckoutNotification($event, $acceptance));
try{
if ($this->shouldSendWebhookNotification()) {
if ($this->newMicrosoftTeamsWebhookEnabled()) {
$message = $this->getCheckoutNotification($event)->toMicrosoftTeams();
$notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
$notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
} else {
Notification::route($this->webhookSelected(), Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckoutNotification($event, $acceptance));
}
}
}
} catch (ClientException $e) {
Log::error("ClientException caught during checkin notification: " . $e->getMessage());
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_fail') );
Log::debug("Exception caught during checkout notification: " . $e->getMessage());
} catch (Exception $e) {
Log::error(ucfirst(Setting::getSettings()->webhook_selected) . ' webhook notification failed:', [
'error' => $e->getMessage(),
'webhook_endpoint' => Setting::getSettings()->webhook_endpoint,
'event' => $event,
]);
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) . trans('admin/settings/message.webhook.webhook_fail'));
Log::debug("Exception caught during checkout notification: " . $e->getMessage());
}
}
/**
* Notify the user and post to webhook about the checked in checkoutable
*/
@@ -156,7 +147,7 @@ class CheckoutableListener
$ccEmails = array_filter($adminCcEmailsArray);
$mailable = $this->getCheckinMailType($event);
$notifiable = $this->getNotifiables($event);
if ($event->checkedOutTo->locale){
if (!$event->checkedOutTo->locale){
$mailable->locale($event->checkedOutTo->locale);
}
// Send email notifications
@@ -187,24 +178,18 @@ class CheckoutableListener
try {
if ($this->shouldSendWebhookNotification()) {
if ($this->newMicrosoftTeamsWebhookEnabled()) {
$message = $this->getCheckinNotification($event)->toMicrosoftTeams();
$notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
$notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
} else {
Notification::route($this->webhookSelected(), Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckinNotification($event));
$message = $this->getCheckinNotification($event)->toMicrosoftTeams();
$notification = new TeamsNotification(Setting::getSettings()->webhook_endpoint);
$notification->success()->sendMessage($message[0], $message[1]); // Send the message to Microsoft Teams
} else {
Notification::route($this->webhookSelected(), Setting::getSettings()->webhook_endpoint)
->notify($this->getCheckinNotification($event));
}
}
}
} catch (ClientException $e) {
Log::error("ClientException caught during checkin notification: " . $e->getMessage());
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_fail'));
Log::warning("Exception caught during checkin notification: " . $e->getMessage());
} catch (Exception $e) {
Log::error(ucfirst(Setting::getSettings()->webhook_selected) . ' webhook notification failed:', [
'error' => $e->getMessage(),
'webhook_endpoint' => Setting::getSettings()->webhook_endpoint,
'event' => $event,
]);
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_fail'));
Log::warning("Exception caught during checkin notification: " . $e->getMessage());
}
}
@@ -297,7 +282,7 @@ class CheckoutableListener
];
$mailable= $lookup[get_class($event->checkoutable)];
return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, $acceptance, $event->note);
return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedOutBy, $event->note, $acceptance);
}
private function getCheckinMailType($event){

View File

@@ -17,7 +17,6 @@ use App\Events\ItemAccepted;
use App\Events\ItemDeclined;
use App\Events\LicenseCheckedIn;
use App\Events\LicenseCheckedOut;
use App\Events\NoteAdded;
use App\Models\Actionlog;
use App\Models\User;
use App\Models\LicenseSeat;
@@ -129,23 +128,6 @@ class LogListener
}
/**
* Note is added to action log
*
*/
public function onNoteAdded(NoteAdded $event)
{
$logaction = new Actionlog();
$logaction->item_id = $event->itemNoteAddedOn->id;
$logaction->item_type = get_class($event->itemNoteAddedOn);
$logaction->note = $event->note; //this is the received alphanumeric text from the box
$logaction->created_by = $event->noteAddedBy->id;
$logaction->action_type = 'note_added';
$logaction->save();
}
/**
* Register the listeners for the subscriber.
*
@@ -159,7 +141,6 @@ class LogListener
'CheckoutAccepted',
'CheckoutDeclined',
'UserMerged',
'NoteAdded',
];
foreach ($list as $event) {

View File

@@ -329,7 +329,6 @@ class Importer extends Component
];
$this->locations_fields = [
'id' => trans('general.id'),
'name' => trans('general.item_name_var', ['item' => trans('general.location')]),
'address' => trans('general.address'),
'address2' => trans('general.importer.address2'),
@@ -401,6 +400,7 @@ class Importer extends Component
'requestable',
'Requestable',
],
'gravatar' =>
[
'gravatar',

View File

@@ -159,7 +159,7 @@ class SlackSettingsForm extends Component
]);
try {
$test = $webhook->post($this->webhook_endpoint, ['body' => $payload, ['headers' => ['Content-Type' => 'application/json']]]);
$test = $webhook->post($this->webhook_endpoint, ['body' => $payload]);
if(($test->getStatusCode() == 302)||($test->getStatusCode() == 301)){
return session()->flash('error' , trans('admin/settings/message.webhook.error_redirect', ['endpoint' => $this->webhook_endpoint]));
@@ -224,7 +224,7 @@ class SlackSettingsForm extends Component
try {
$response = Http::withHeaders([
'content-type' => 'application/json',
'content-type' => 'applications/json',
])->post($this->webhook_endpoint,
$payload)->throw();
@@ -259,7 +259,7 @@ class SlackSettingsForm extends Component
"text" => trans('general.webhook_test_msg', ['app' => $this->webhook_name]),
];
$response = Http::withHeaders([
'content-type' => 'application/json',
'content-type' => 'applications/json',
])->post($this->webhook_endpoint,
$payload)->throw();
}
@@ -269,7 +269,7 @@ class SlackSettingsForm extends Component
$notification->success()->sendMessage($message);
$response = Http::withHeaders([
'content-type' => 'application/json',
'content-type' => 'applications/json',
])->post($this->webhook_endpoint);
}

View File

@@ -21,7 +21,7 @@ class CheckoutAccessoryMail extends Mailable
/**
* Create a new message instance.
*/
public function __construct(Accessory $accessory, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
public function __construct(Accessory $accessory, $checkedOutTo, User $checkedOutBy,$note, $acceptance)
{
$this->item = $accessory;
$this->admin = $checkedOutBy;

View File

@@ -23,7 +23,7 @@ class CheckoutAssetMail extends Mailable
/**
* Create a new message instance.
*/
public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $note, $acceptance)
{
$this->item = $asset;
$this->admin = $checkedOutBy;

View File

@@ -27,6 +27,7 @@ class CheckoutLicenseMail extends Mailable
$this->note = $note;
$this->target = $checkedOutTo;
$this->acceptance = $acceptance;
$this->settings = Setting::getSettings();
}

View File

@@ -22,14 +22,7 @@ class AccessoryCheckout extends Model
{
use Searchable;
protected $fillable = [
'accessory_id',
'assigned_to',
'assigned_type',
'note'
];
protected $presenter = \App\Presenters\AccessoryPresenter::class;
protected $fillable = ['created_by', 'accessory_id', 'assigned_to', 'assigned_type', 'note'];
protected $table = 'accessories_checkout';
/**
@@ -41,13 +34,9 @@ class AccessoryCheckout extends Model
*/
public function accessory()
{
return $this->hasOne(Accessory::class, 'id', 'accessory_id');
return $this->hasOne(\App\Models\Accessory::class, 'accessory_id');
}
public function accessories()
{
return $this->hasMany(Accessory::class, 'id', 'accessory_id');
}
/**
* Establishes the accessory checkout -> user relationship
*
@@ -55,9 +44,9 @@ class AccessoryCheckout extends Model
* @since [v7.0.9]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function adminuser()
public function user()
{
return $this->hasOne(\App\Models\User::class, 'created_by');
return $this->hasOne(\App\Models\User::class, 'user_id');
}
/**
@@ -87,7 +76,7 @@ class AccessoryCheckout extends Model
/**
* Determines whether the accessory is checked out to a user
*
* Even though we allow for checkout to things beyond users
* Even though we allow allow for checkout to things beyond users
* this method is an easy way of seeing if we are checked out to a user.
*
* @author [A. Kroeger]
@@ -95,17 +84,7 @@ class AccessoryCheckout extends Model
*/
public function checkedOutToUser(): bool
{
return $this->assigned_type == User::class;
}
public function checkedOutToLocation(): bool
{
return $this->assigned_type == Location::class;
}
public function checkedOutToAsset(): bool
{
return $this->assigned_type == Asset::class;
return $this->assignedType() === Asset::USER;
}
public function scopeUserAssigned(Builder $query): void
@@ -113,16 +92,6 @@ class AccessoryCheckout extends Model
$query->where('assigned_type', '=', User::class);
}
public function scopeLocationAssigned(Builder $query): void
{
$query->where('assigned_type', '=', Location::class);
}
public function scopeAssetAssigned(Builder $query): void
{
$query->where('assigned_type', '=', Asset::class);
}
/**
* Run additional, advanced searches.
*

View File

@@ -69,7 +69,7 @@ class Actionlog extends SnipeModel
'company' => ['name'],
'adminuser' => ['first_name','last_name','username', 'email'],
'user' => ['first_name','last_name','username', 'email'],
'assets' => ['asset_tag','name', 'serial'],
'assets' => ['asset_tag','name'],
];
/**

View File

@@ -35,7 +35,7 @@ class CheckoutAcceptance extends Model
/**
* The resource that was is out
*
* @return \Illuminate\Database\Eloquent\Relations\MorphTo
* @return Illuminate\Database\Eloquent\Relations\MorphTo
*/
public function checkoutable()
{

View File

@@ -141,17 +141,4 @@ class Department extends SnipeModel
{
return $query->leftJoin('users as department_user', 'departments.manager_id', '=', 'department_user.id')->orderBy('department_user.first_name', $order)->orderBy('department_user.last_name', $order);
}
/**
* Query builder scope to order on company
*
* @param \Illuminate\Database\Query\Builder $query Query builder instance
* @param text $order Order
*
* @return \Illuminate\Database\Query\Builder Modified query builder
*/
public function scopeOrderCompany($query, $order)
{
return $query->leftJoin('companies as company_sort', 'departments.company_id', '=', 'company_sort.id')->orderBy('company_sort.name', $order);
}
}

View File

@@ -1,107 +0,0 @@
<?php
namespace App\Models\Labels\Tapes\Brother;
class TZe_24mm_D extends TZe_24mm
{
private const BARCODE_MARGIN = 1.40;
private const TAG_SIZE = 2.80;
private const TITLE_SIZE = 2.80;
private const TITLE_MARGIN = 0.50;
private const LABEL_SIZE = 2.50;
private const LABEL_MARGIN = - 0.35;
private const FIELD_SIZE = 2.50;
private const FIELD_MARGIN = 0.35;
private const BARCODE1D_SIZE = 3.00; // Size for the C128 barcode at bottom
public function getUnit() { return 'mm'; }
public function getWidth() { return 65.0; }
public function getSupportAssetTag() { return true; }
public function getSupport1DBarcode() { return true; }
public function getSupport2DBarcode() { return true; }
public function getSupportFields() { return 3; }
public function getSupportLogo() { return false; }
public function getSupportTitle() { return true; }
public function preparePDF($pdf) {}
public function write($pdf, $record) {
$pa = $this->getPrintableArea();
$currentX = $pa->x1;
$currentY = $pa->y1;
$usableWidth = $pa->w;
// Reserve space at bottom for 1D barcode
$usableHeight = $pa->h - self::BARCODE1D_SIZE;
$barcodeSize = $usableHeight - self::TAG_SIZE;
if ($record->has('barcode2d')) {
static::writeText(
$pdf, $record->get('tag'),
$pa->x1, $pa->y2 - self::TAG_SIZE - self::BARCODE1D_SIZE,
'freemono', 'b', self::TAG_SIZE, 'C',
$barcodeSize, self::TAG_SIZE, true, 0
);
static::write2DBarcode(
$pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type,
$currentX, $currentY,
$barcodeSize, $barcodeSize
);
$currentX += $barcodeSize + self::BARCODE_MARGIN;
$usableWidth -= $barcodeSize + self::BARCODE_MARGIN;
} else {
static::writeText(
$pdf, $record->get('tag'),
$pa->x1, $pa->y2 - self::TAG_SIZE - self::BARCODE1D_SIZE,
'freemono', 'b', self::TAG_SIZE, 'R',
$usableWidth, self::TAG_SIZE, true, 0
);
}
if ($record->has('title')) {
static::writeText(
$pdf, $record->get('title'),
$currentX, $currentY,
'freesans', '', self::TITLE_SIZE, 'L',
$usableWidth, self::TITLE_SIZE, true, 0
);
$currentY += self::TITLE_SIZE + self::TITLE_MARGIN;
}
foreach ($record->get('fields') as $field) {
// Write label and value on the same line
// Calculate label width with proportional character spacing
$labelWidth = $pdf->GetStringWidth($field['label'], 'freemono', '', self::LABEL_SIZE);
$charCount = strlen($field['label']);
$spacingPerChar = 0.5;
$totalSpacing = $charCount * $spacingPerChar;
$adjustedWidth = $labelWidth + $totalSpacing;
static::writeText(
$pdf, $field['label'],
$currentX, $currentY,
'freemono', 'B', self::LABEL_SIZE, 'L',
$adjustedWidth, self::LABEL_SIZE, true, 0, $spacingPerChar
);
static::writeText(
$pdf, $field['value'],
$currentX + $adjustedWidth + 2, $currentY,
'freemono', 'B', self::FIELD_SIZE, 'L',
$usableWidth - $adjustedWidth - 2, self::FIELD_SIZE, true, 0, 0.3
);
$currentY += max(self::LABEL_SIZE, self::FIELD_SIZE) + self::FIELD_MARGIN;
}
// Add C128 barcode at the bottom
if ($record->has('barcode1d')) {
static::write1DBarcode(
$pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type,
$pa->x1, $pa->y2 - self::BARCODE1D_SIZE,
$pa->w, self::BARCODE1D_SIZE
);
}
}
}

View File

@@ -253,18 +253,6 @@ class Location extends SnipeModel
return $this->morphMany(\App\Models\Asset::class, 'assigned', 'assigned_type', 'assigned_to')->withTrashed();
}
/**
* Establishes the accessory -> location assignment relationship
*
* @author A. Gianotto <snipe@snipe.net>
* @since [v3.0]
* @return \Illuminate\Database\Eloquent\Relations\Relation
*/
public function assignedAccessories()
{
return $this->morphMany(\App\Models\AccessoryCheckout::class, 'assigned', 'assigned_type', 'assigned_to');
}
public function setLdapOuAttribute($ldap_ou)
{
return $this->attributes['ldap_ou'] = empty($ldap_ou) ? null : $ldap_ou;

View File

@@ -1,241 +0,0 @@
<?php
namespace App\Models;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Model;
use Illuminate\Database\Eloquent\Relations\BelongsTo;
use Illuminate\Database\Eloquent\SoftDeletes;
use Watson\Validating\ValidatingTrait;
class ReportTemplate extends Model
{
use HasFactory;
use SoftDeletes;
use ValidatingTrait;
protected $casts = [
'options' => 'array',
];
protected $fillable = [
'created_by',
'name',
'options',
];
protected $rules = [
'name' => [
'required',
'string',
],
'options' => [
'required',
'array',
],
];
protected static function booted()
{
// Scope to current user
static::addGlobalScope('current_user', function (Builder $builder) {
if (auth()->check()) {
$builder->where('created_by', auth()->id());
}
});
static::created(function (ReportTemplate $reportTemplate) {
$logAction = new Actionlog([
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
'created_by' => auth()->id(),
]);
$logAction->logaction('create');
});
static::updated(function (ReportTemplate $reportTemplate) {
$changed = [];
foreach ($reportTemplate->getDirty() as $key => $value) {
$changed[$key] = [
'old' => $reportTemplate->getOriginal($key),
'new' => $reportTemplate->getAttribute($key),
];
}
$logAction = new Actionlog();
$logAction->item_type = ReportTemplate::class;
$logAction->item_id = $reportTemplate->id;
$logAction->created_by = auth()->id();
$logAction->log_meta = json_encode($changed);
$logAction->logaction('update');
});
static::deleted(function (ReportTemplate $reportTemplate) {
$logAction = new Actionlog([
'item_type' => ReportTemplate::class,
'item_id' => $reportTemplate->id,
'created_by' => auth()->id(),
]);
$logAction->logaction('delete');
});
}
/**
* Establishes the report template -> creator relationship.
*
*/
public function creator(): BelongsTo
{
return $this->belongsTo(User::class, 'created_by');
}
/**
* Get the value of a checkbox field for the given field name.
*
* @param string $fieldName
* @param string $fallbackValue The value to return if the report template is not saved yet.
*
*/
public function checkmarkValue(string $fieldName, string $fallbackValue = '1'): string
{
// Assuming we're using the null object pattern, and an empty model
// was passed to the view when showing the default report page,
// return the fallback value so that checkboxes are checked by default.
if (is_null($this->id)) {
return $fallbackValue;
}
// If the model does exist then return the value of the field
// or return 0 so the checkbox is unchecked.
// Falling back to 0 here is because checkboxes are not sent
// in the request when unchecked so they are not
// actually saved in the model's options.
return $this->options[$fieldName] ?? '0';
}
/**
* Get the value of a radio field for the given field name.
*
* @param string $fieldName
* @param string $value The value to check against.
* @param bool $isDefault Whether the radio input being checked is the default.
*
*/
public function radioValue(string $fieldName, string $value, bool $isDefault = false): bool
{
$fieldExists = array_has($this->options, $fieldName);
// If the field doesn't exist but the radio input
// being checked is the default then return true.
if (!$fieldExists && $isDefault) {
return true;
}
// If the field exists and matches what we're checking then return true.
if ($fieldExists && $this->options[$fieldName] === $value) {
return true;
}
// Otherwise return false.
return false;
}
/**
* Get the value of a select field for the given field name.
*
* @param string $fieldName
* @param string|null $model The Eloquent model to check against.
*
* @return mixed|null
*
*/
public function selectValue(string $fieldName, string $model = null)
{
// If the field does not exist then return null.
if (!isset($this->options[$fieldName])) {
return null;
}
$value = $this->options[$fieldName];
// If the value was stored as an array, most likely
// due to a previously being a multi-select,
// then return the first value.
if (is_array($value)) {
$value = $value[0];
}
// If a model is provided then we should ensure we only return
// the value if the model still exists.
// Note: It is possible $value is an id that no longer exists and this will return null.
if ($model) {
$foundModel = $model::find($value);
return $foundModel ? $foundModel->id : null;
}
return $value;
}
/**
* Get the values of a multi-select field for the given field name.
*
* @param string $fieldName
* @param string|null $model The Eloquent model to check against.
*
* @return iterable
*
*/
public function selectValues(string $fieldName, string $model = null): iterable
{
// If the field does not exist then return an empty array.
if (!isset($this->options[$fieldName])) {
return [];
}
// If a model is provided then we should ensure we only return
// the ids of models that exist and are not deleted.
if ($model) {
return $model::findMany($this->options[$fieldName])->pluck('id');
}
// Wrap the value in an array if needed. This is to ensure
// values previously stored as a single value,
// most likely from a single select, are returned as an array.
if (!is_array($this->options[$fieldName])) {
return [$this->options[$fieldName]];
}
return $this->options[$fieldName];
}
/**
* Get the value of a text field for the given field name.
*
* @param string $fieldName
* @param string|null $fallbackValue
*
* @return string
*/
public function textValue(string $fieldName, string|null $fallbackValue = ''): string
{
// Assuming we're using the null object pattern,
// return the default value if the object is not saved yet.
if (is_null($this->id)) {
return (string) $fallbackValue;
}
// Return the field's value if it exists
// and return the default value if not.
return $this->options[$fieldName] ?? '';
}
public function getDisplayNameAttribute()
{
return $this->name;
}
}

View File

@@ -13,7 +13,6 @@ use Illuminate\Contracts\Auth\CanResetPassword as CanResetPasswordContract;
use Illuminate\Contracts\Translation\HasLocalePreference;
use Illuminate\Database\Eloquent\Builder;
use Illuminate\Database\Eloquent\Factories\HasFactory;
use Illuminate\Database\Eloquent\Relations\HasMany;
use Illuminate\Database\Eloquent\SoftDeletes;
use Illuminate\Foundation\Auth\Access\Authorizable;
use Illuminate\Notifications\Notifiable;
@@ -334,7 +333,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
public function accessories()
{
return $this->belongsToMany(\App\Models\Accessory::class, 'accessories_checkout', 'assigned_to', 'accessory_id')
->where('assigned_type', '=', 'App\Models\User')
->withPivot('id', 'created_at', 'note')->withTrashed()->orderBy('accessory_id');
}
@@ -362,15 +360,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
return $this->belongsToMany(\App\Models\License::class, 'license_seats', 'assigned_to', 'license_id')->withPivot('id', 'created_at', 'updated_at');
}
/**
* Establishes the user -> reportTemplates relationship
*
*/
public function reportTemplates(): HasMany
{
return $this->hasMany(ReportTemplate::class, 'created_by');
}
/**
* Establishes a count of all items assigned
*

View File

@@ -80,7 +80,7 @@ class AssetObserver
{
if ($settings = Setting::getSettings()) {
$tag = $asset->asset_tag;
$prefix = (string)($settings->auto_increment_prefix ?? '');
$prefix = $settings->auto_increment_prefix;
$number = substr($tag, strlen($prefix));
// IF - auto_increment_assets is on, AND (there is no prefix OR the prefix matches the start of the tag)
// AND the rest of the string after the prefix is all digits, THEN...

View File

@@ -23,7 +23,7 @@ use Illuminate\Auth\Access\HandlesAuthorization;
abstract class SnipePermissionsPolicy
{
/**
* This should return the key of the model in the users json permission string.
* This should return the key of the model in the user's JSON permission string.
*
* @return bool
*/
@@ -37,11 +37,7 @@ abstract class SnipePermissionsPolicy
{
/**
* If an admin, they can do all item related tasks, but ARE constrained by FMCSA company access.
* That scoping happens on the model level (except for the Users model) via the Companyable trait.
*
* This does lead to some inconsistencies in the responses, since attempting to edit assets,
* accessories, etc (anything other than users) will result in a Forbidden error, whereas the users
* area will redirect with "That user doesn't exist" since the scoping is handled directly on those queries.
* That scoping happens on the model level via the Companyable trait.
*
* The *superuser* global permission gets handled in the AuthServiceProvider before() method.
*
@@ -53,7 +49,7 @@ abstract class SnipePermissionsPolicy
}
/**
* If we got here by $this→authorize('something', $actualModel) then we can continue on Il but if we got here
* If we got here by $this→authorize('something', $actualModel) then we can continue on, but if we got here
* via $this→authorize('something', Model::class) then calling Company:: isCurrentUserHasAccess($item) gets weird.
* Bail out here by returning "nothing" and allow the relevant method lower in this class to be called and handle authorization.
*/
@@ -85,7 +81,7 @@ abstract class SnipePermissionsPolicy
}
/**
* Determine whether the user can view the accessory.
* Determine whether the user can view the item.
*
* @param \App\Models\User $user
* @return mixed
@@ -112,7 +108,7 @@ abstract class SnipePermissionsPolicy
}
/**
* Determine whether the user can update the accessory.
* Determine whether the user can update the item.
*
* @param \App\Models\User $user
* @return mixed
@@ -124,7 +120,7 @@ abstract class SnipePermissionsPolicy
/**
* Determine whether the user can update the accessory.
* Determine whether the user can checkout the item.
*
* @param \App\Models\User $user
* @return mixed
@@ -135,7 +131,7 @@ abstract class SnipePermissionsPolicy
}
/**
* Determine whether the user can delete the accessory.
* Determine whether the user can delete the item.
*
* @param \App\Models\User $user
* @return mixed
@@ -151,7 +147,7 @@ abstract class SnipePermissionsPolicy
}
/**
* Determine whether the user can manage the accessory.
* Determine whether the user can manage the item.
*
* @param \App\Models\User $user
* @return mixed

View File

@@ -158,7 +158,7 @@ class AccessoryPresenter extends Presenter
'title' => trans('general.change'),
'formatter' => 'accessoriesInOutFormatter',
], [
'field' => 'available_actions',
'field' => 'actions',
'searchable' => false,
'sortable' => false,
'switchable' => false,
@@ -170,74 +170,6 @@ class AccessoryPresenter extends Presenter
return json_encode($layout);
}
public static function assignedDataTableLayout()
{
$layout = [
[
'field' => 'id',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('general.id'),
'visible' => false,
],
[
'field' => 'assigned_to.image',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('general.image'),
'visible' => true,
'formatter' => 'imageFormatter',
],
[
'field' => 'assigned_to',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('general.checked_out_to'),
'visible' => true,
'formatter' => 'polymorphicItemFormatter',
],
[
'field' => 'note',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('general.notes'),
'visible' => true,
],
[
'field' => 'created_at',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('admin/hardware/table.checkout_date'),
'visible' => true,
'formatter' => 'dateDisplayFormatter',
],
[
'field' => 'created_by',
'searchable' => false,
'sortable' => false,
'title' => trans('general.admin'),
'visible' => false,
'formatter' => 'usersLinkObjFormatter',
],
[
'field' => 'available_actions',
'searchable' => false,
'sortable' => false,
'switchable' => false,
'title' => trans('table.actions'),
'formatter' => 'accessoriesInOutFormatter',
],
];
return json_encode($layout);
}
/**
* Pregenerated link to this accessories view page.
* @return string

View File

@@ -46,7 +46,7 @@ class ActionlogPresenter extends Presenter
return 'fa-solid fa-mobile-screen';
}
if ($this->action_type == 'create') {
if ($this->action_type == 'create new') {
return 'fa-solid fa-user-plus';
}
@@ -70,7 +70,7 @@ class ActionlogPresenter extends Presenter
}
// Everything else
if ($this->action_type == 'create') {
if ($this->action_type == 'create new') {
return 'fa-solid fa-plus';
}
@@ -98,10 +98,6 @@ class ActionlogPresenter extends Presenter
return 'fa-solid fa-rotate-right';
}
if ($this->action_type == 'note_added') {
return 'fas fa-sticky-note';
}
return 'fa-solid fa-rotate-right';
}

View File

@@ -18,14 +18,16 @@ class LocationPresenter extends Presenter
'field' => 'bulk_selectable',
'checkbox' => true,
'formatter' => 'checkboxEnabledFormatter',
], [
],
[
'field' => 'id',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('general.id'),
'visible' => false,
], [
],
[
'field' => 'name',
'searchable' => true,
'sortable' => true,
@@ -33,7 +35,8 @@ class LocationPresenter extends Presenter
'title' => trans('admin/locations/table.name'),
'visible' => true,
'formatter' => 'locationsLinkFormatter',
], [
],
[
'field' => 'image',
'searchable' => false,
'sortable' => true,
@@ -41,7 +44,8 @@ class LocationPresenter extends Presenter
'title' => trans('general.image'),
'visible' => true,
'formatter' => 'imageFormatter',
], [
],
[
'field' => 'parent',
'searchable' => false,
'sortable' => true,
@@ -49,111 +53,100 @@ class LocationPresenter extends Presenter
'title' => trans('admin/locations/table.parent'),
'visible' => true,
'formatter' => 'locationsLinkObjFormatter',
], [
],
[
'field' => 'assets_count',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/message.current_location'),
'visible' => true,
], [
],
[
'field' => 'rtd_assets_count',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/hardware/form.default_location'),
'titleTooltip' => trans('admin/hardware/form.default_location'),
'tooltip' => 'true',
'visible' => false,
'class' => 'css-house-flag',
], [
],
[
'field' => 'assigned_assets_count',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/message.assigned_assets'),
'titleTooltip' => trans('admin/locations/message.assigned_assets'),
'visible' => true,
'class' => 'css-house-laptop',
], [
'field' => 'accessories_count',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('general.accessories'),
'titleTooltip' => trans('general.accessories'),
'visible' => true,
'class' => 'css-accessory',
], [
'field' => 'assigned_accessories_count',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('general.accessories_assigned'),
'titleTooltip' => trans('general.accessories_assigned'),
'visible' => true,
'class' => 'css-accessory-alt',
], [
],
[
'field' => 'users_count',
'searchable' => false,
'sortable' => true,
'switchable' => true,
'title' => trans('general.people'),
'titleTooltip' => trans('general.people'),
'visible' => true,
'class' => 'css-house-user',
// 'data-tooltip' => true, - not working, but I want to try to use regular tooltips here
], [
],
[
'field' => 'currency',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('general.currency'),
'visible' => true,
'class' => 'css-currency',
], [
],
[
'field' => 'address',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/table.address'),
'visible' => true,
], [
],
[
'field' => 'address2',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/table.address2'),
'visible' => false,
], [
],
[
'field' => 'city',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/table.city'),
'visible' => true,
], [
],
[
'field' => 'state',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/table.state'),
'visible' => true,
], [
],
[
'field' => 'zip',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/table.zip'),
'visible' => false,
], [
],
[
'field' => 'country',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/table.country'),
'visible' => false,
], [
],
[
'field' => 'phone',
'searchable' => true,
'sortable' => true,
@@ -161,7 +154,8 @@ class LocationPresenter extends Presenter
'title' => trans('admin/users/table.phone'),
'visible' => false,
'formatter' => 'phoneFormatter',
], [
],
[
'field' => 'fax',
'searchable' => true,
'sortable' => true,
@@ -169,14 +163,16 @@ class LocationPresenter extends Presenter
'title' => trans('admin/suppliers/table.fax'),
'visible' => false,
'formatter' => 'phoneFormatter',
], [
],
[
'field' => 'ldap_ou',
'searchable' => true,
'sortable' => true,
'switchable' => true,
'title' => trans('admin/locations/table.ldap_ou'),
'visible' => false,
], [
],
[
'field' => 'manager',
'searchable' => false,
'sortable' => true,
@@ -184,7 +180,9 @@ class LocationPresenter extends Presenter
'title' => trans('admin/users/table.manager'),
'visible' => false,
'formatter' => 'usersLinkObjFormatter',
], [
],
[
'field' => 'created_at',
'searchable' => true,
'sortable' => true,
@@ -192,7 +190,9 @@ class LocationPresenter extends Presenter
'title' => trans('general.created_at'),
'visible' => false,
'formatter' => 'dateDisplayFormatter',
], [
],
[
'field' => 'actions',
'searchable' => false,
'sortable' => false,
@@ -206,73 +206,6 @@ class LocationPresenter extends Presenter
return json_encode($layout);
}
public static function assignedAccessoriesDataTableLayout()
{
$layout = [
[
'field' => 'id',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('general.id'),
'visible' => false,
],
[
'field' => 'accessory',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('general.accessory'),
'visible' => true,
'formatter' => 'accessoriesLinkObjFormatter',
],
[
'field' => 'image',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('general.image'),
'visible' => true,
'formatter' => 'imageFormatter',
],
[
'field' => 'note',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('general.notes'),
'visible' => true,
],
[
'field' => 'created_at',
'searchable' => false,
'sortable' => false,
'switchable' => true,
'title' => trans('admin/hardware/table.checkout_date'),
'visible' => true,
'formatter' => 'dateDisplayFormatter',
],
[
'field' => 'created_by',
'searchable' => false,
'sortable' => false,
'title' => trans('general.admin'),
'visible' => false,
'formatter' => 'usersLinkObjFormatter',
],
[
'field' => 'available_actions',
'searchable' => false,
'sortable' => false,
'switchable' => false,
'title' => trans('table.actions'),
'formatter' => 'accessoriesInOutFormatter',
],
];
return json_encode($layout);
}
/**
* Link to this locations name
* @return string

View File

@@ -105,7 +105,7 @@ class Label implements View
}
}
if ($settings->alt_barcode_enabled) {
if ($template->getSupport1DBarcode()) {
$barcode1DType = $settings->label2_1d_type;
if ($barcode1DType != 'none') {
@@ -115,7 +115,8 @@ class Label implements View
]);
}
}
}
if ($template->getSupport2DBarcode()) {
$barcode2DType = $settings->label2_2d_type;
$barcode2DType = ($barcode2DType == 'default') ?
@@ -123,29 +124,16 @@ class Label implements View
$barcode2DType;
if (($barcode2DType != 'none') && (!is_null($barcode2DType))) {
switch ($settings->label2_2d_target) {
case 'ht_tag':
$barcode2DTarget = route('ht/assetTag', $asset->asset_tag);
break;
case 'plain_asset_id':
$barcode2DTarget = (string) $asset->id;
break;
case 'plain_asset_tag':
$barcode2DTarget = $asset->asset_tag;
break;
case 'plain_serial_number':
$barcode2DTarget = $asset->serial;
break;
case 'ht_tag': $barcode2DTarget = route('ht/assetTag', $asset->asset_tag); break;
case 'hardware_id':
default:
$barcode2DTarget = route('hardware.show', ['hardware' => $asset->id]);
break;
}
$assetData->put('barcode2d', (object)[
'type' => $barcode2DType,
'content' => $barcode2DTarget,
]);
default: $barcode2DTarget = route('hardware.show', ['hardware' => $asset->id]); break;
}
$assetData->put('barcode2d', (object)[
'type' => $barcode2DType,
'content' => $barcode2DTarget,
]);
}
}
$fields = $fieldDefinitions
->map(fn($field) => $field->toArray($asset))

View File

@@ -20,7 +20,6 @@
"php": "^8.1",
"ext-curl": "*",
"ext-fileinfo": "*",
"ext-iconv": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-pdo": "*",
@@ -56,7 +55,6 @@
"nunomaduro/collision": "^7.0",
"okvpn/clock-lts": "^1.0",
"onelogin/php-saml": "^3.4",
"onnov/detect-encoding": "^2.0",
"osa-eg/laravel-teams-notification": "^2.1",
"paragonie/constant_time_encoding": "^2.3",
"paragonie/sodium_compat": "^1.19",

101
composer.lock generated
View File

@@ -4,7 +4,7 @@
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
"This file is @generated automatically"
],
"content-hash": "2a6e7f5e039ee2f40605aefc5c5baf08",
"content-hash": "0750e3a427347b2a56a05a8b9b533d48",
"packages": [
{
"name": "alek13/slack",
@@ -3551,16 +3551,16 @@
},
{
"name": "league/commonmark",
"version": "2.6.0",
"version": "2.5.3",
"source": {
"type": "git",
"url": "https://github.com/thephpleague/commonmark.git",
"reference": "d150f911e0079e90ae3c106734c93137c184f932"
"reference": "b650144166dfa7703e62a22e493b853b58d874b0"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/d150f911e0079e90ae3c106734c93137c184f932",
"reference": "d150f911e0079e90ae3c106734c93137c184f932",
"url": "https://api.github.com/repos/thephpleague/commonmark/zipball/b650144166dfa7703e62a22e493b853b58d874b0",
"reference": "b650144166dfa7703e62a22e493b853b58d874b0",
"shasum": ""
},
"require": {
@@ -3585,9 +3585,8 @@
"phpstan/phpstan": "^1.8.2",
"phpunit/phpunit": "^9.5.21 || ^10.5.9 || ^11.0.0",
"scrutinizer/ocular": "^1.8.1",
"symfony/finder": "^5.3 | ^6.0 | ^7.0",
"symfony/process": "^5.4 | ^6.0 | ^7.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 | ^7.0",
"symfony/finder": "^5.3 | ^6.0 || ^7.0",
"symfony/yaml": "^2.3 | ^3.0 | ^4.0 | ^5.0 | ^6.0 || ^7.0",
"unleashedtech/php-coding-standard": "^3.1.1",
"vimeo/psalm": "^4.24.0 || ^5.0.0"
},
@@ -3597,7 +3596,7 @@
"type": "library",
"extra": {
"branch-alias": {
"dev-main": "2.7-dev"
"dev-main": "2.6-dev"
}
},
"autoload": {
@@ -3654,7 +3653,7 @@
"type": "tidelift"
}
],
"time": "2024-12-07T15:34:16+00:00"
"time": "2024-08-16T11:46:16+00:00"
},
{
"name": "league/config",
@@ -5574,70 +5573,6 @@
],
"time": "2024-05-30T15:14:26+00:00"
},
{
"name": "onnov/detect-encoding",
"version": "v2.0.0",
"source": {
"type": "git",
"url": "https://github.com/onnov/detect-encoding.git",
"reference": "6a8159ac3e6178ae043244b9d66a9b2701121e07"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/onnov/detect-encoding/zipball/6a8159ac3e6178ae043244b9d66a9b2701121e07",
"reference": "6a8159ac3e6178ae043244b9d66a9b2701121e07",
"shasum": ""
},
"require": {
"ext-iconv": "*",
"php": ">=7.3"
},
"require-dev": {
"infection/infection": "*",
"phpbench/phpbench": "*",
"phpcompatibility/php-compatibility": "*",
"phpmd/phpmd": "*",
"phpstan/phpstan": "*",
"phpstan/phpstan-strict-rules": "*",
"phpunit/phpunit": "*",
"roave/backward-compatibility-check": "*",
"squizlabs/php_codesniffer": "*"
},
"type": "library",
"autoload": {
"psr-4": {
"Onnov\\DetectEncoding\\": "src/"
}
},
"notification-url": "https://packagist.org/downloads/",
"license": [
"MIT"
],
"authors": [
{
"name": "onnov",
"email": "oblnn@yandex.ru"
}
],
"description": "Text encoding definition class instead of mb_detect_encoding. Defines: utf-8, windows-1251, koi8-r, iso-8859-5, ibm866, .....",
"homepage": "https://github.com/onnov/detect-encoding",
"keywords": [
"cyrillic",
"encoding",
"ibm866",
"iconv",
"iso-8859-5",
"koi8-r",
"mb_detect_encoding",
"utf-8",
"windows-1251"
],
"support": {
"issues": "https://github.com/onnov/detect-encoding/issues",
"source": "https://github.com/onnov/detect-encoding/tree/v2.0.0"
},
"time": "2021-01-04T14:29:34+00:00"
},
{
"name": "osa-eg/laravel-teams-notification",
"version": "v2.1.2",
@@ -11109,21 +11044,20 @@
},
{
"name": "tecnickcom/tcpdf",
"version": "6.8.0",
"version": "6.7.7",
"source": {
"type": "git",
"url": "https://github.com/tecnickcom/TCPDF.git",
"reference": "14ffa0e308f5634aa2489568b4b90b24073b6731"
"reference": "cfbc0028cc23f057f2baf9e73bdc238153c22086"
},
"dist": {
"type": "zip",
"url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/14ffa0e308f5634aa2489568b4b90b24073b6731",
"reference": "14ffa0e308f5634aa2489568b4b90b24073b6731",
"url": "https://api.github.com/repos/tecnickcom/TCPDF/zipball/cfbc0028cc23f057f2baf9e73bdc238153c22086",
"reference": "cfbc0028cc23f057f2baf9e73bdc238153c22086",
"shasum": ""
},
"require": {
"ext-curl": "*",
"php": ">=7.1.0"
"php": ">=5.5.0"
},
"type": "library",
"autoload": {
@@ -11170,7 +11104,7 @@
],
"support": {
"issues": "https://github.com/tecnickcom/TCPDF/issues",
"source": "https://github.com/tecnickcom/TCPDF/tree/6.8.0"
"source": "https://github.com/tecnickcom/TCPDF/tree/6.7.7"
},
"funding": [
{
@@ -11178,7 +11112,7 @@
"type": "custom"
}
],
"time": "2024-12-23T13:34:57+00:00"
"time": "2024-10-26T12:15:02+00:00"
},
{
"name": "tijsverkoyen/css-to-inline-styles",
@@ -16634,11 +16568,10 @@
"php": "^8.1",
"ext-curl": "*",
"ext-fileinfo": "*",
"ext-iconv": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-pdo": "*"
},
"platform-dev": {},
"platform-dev": [],
"plugin-api-version": "2.6.0"
}

View File

@@ -207,33 +207,33 @@ return [
/*
* The number of days for which backups must be kept.
*/
'keep_all_backups_for_days' => env('ALL_BACKUP_KEEP_DAYS', 7),
'keep_all_backups_for_days' => 7,
/*
* The number of days for which daily backups must be kept.
*/
'keep_daily_backups_for_days' => env('DAILY_BACKUP_KEEP_DAYS', 16),
'keep_daily_backups_for_days' => 16,
/*
* The number of weeks for which one weekly backup must be kept.
*/
'keep_weekly_backups_for_weeks' => env('WEEKLY_BACKUP_KEEP_WEEKS', 8),
'keep_weekly_backups_for_weeks' => 8,
/*
* The number of months for which one monthly backup must be kept.
*/
'keep_monthly_backups_for_months' => env('MONTHLY_BACKUP_KEEP_MONTHS', 4),
'keep_monthly_backups_for_months' => 4,
/*
* The number of years for which one yearly backup must be kept.
*/
'keep_yearly_backups_for_years' => env('YEARLY_BACKUP_KEEP_YEARS', 2),
'keep_yearly_backups_for_years' => 2,
/*
* After cleaning up the backups remove the oldest backup until
* this amount of megabytes has been reached.
*/
'delete_oldest_backups_when_using_more_megabytes_than' => env('BACKUP_PURGE_OLDEST_AT_MEGS', 5000),
'delete_oldest_backups_when_using_more_megabytes_than' => 5000,
],
],

View File

@@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v7.1.16',
'full_app_version' => 'v7.1.16 - build 16564-gfb857ccf5',
'build_version' => '16564',
'app_version' => 'v7.1.15',
'full_app_version' => 'v7.1.15 - build 16052-g25bfd3e84',
'build_version' => '16052',
'prerelease_version' => '',
'hash_version' => 'gfb857ccf5',
'full_hash' => 'v7.1.16-510-gfb857ccf5',
'hash_version' => 'g25bfd3e84',
'full_hash' => 'v7.1.15-105-g25bfd3e84',
'branch' => 'master',
);

View File

@@ -163,7 +163,7 @@ class AccessoryFactory extends Factory
$accessory->checkouts()->create([
'accessory_id' => $accessory->id,
'created_at' => Carbon::now(),
'created_by' => 1,
'user_id' => 1,
'assigned_to' => $user->id,
'assigned_type' => User::class,
]);

View File

@@ -4,7 +4,6 @@ namespace Database\Factories;
use App\Models\Accessory;
use App\Models\Asset;
use App\Models\CheckoutAcceptance;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
@@ -24,18 +23,6 @@ class CheckoutAcceptanceFactory extends Factory
];
}
public function configure(): static
{
return $this->afterCreating(function (CheckoutAcceptance $acceptance) {
if ($acceptance->checkoutable instanceof Asset && $acceptance->assignedTo instanceof User) {
$acceptance->checkoutable->update([
'assigned_to' => $acceptance->assigned_to_id,
'assigned_type' => get_class($acceptance->assignedTo),
]);
}
});
}
public function forAccessory()
{
return $this->state([

View File

@@ -23,7 +23,6 @@ class GroupFactory extends Factory
{
return [
'name' => $this->faker->name(),
'permissions' => json_encode([]),
];
}
}

View File

@@ -4,7 +4,6 @@ namespace Database\Factories;
use App\Models\Asset;
use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
@@ -34,18 +33,4 @@ class LicenseSeatFactory extends Factory
];
});
}
public function reassignable()
{
return $this->afterMaking(function (LicenseSeat $seat) {
$seat->license->update(['reassignable' => true]);
});
}
public function notReassignable()
{
return $this->afterMaking(function (LicenseSeat $seat) {
$seat->license->update(['reassignable' => false]);
});
}
}

View File

@@ -1,25 +0,0 @@
<?php
namespace Database\Factories;
use App\Models\User;
use Illuminate\Database\Eloquent\Factories\Factory;
class ReportTemplateFactory extends Factory
{
/**
* Define the model's default state.
*
* @return array
*/
public function definition()
{
return [
'name' => $this->faker->word(),
'options' => [
'id' => '1',
],
'created_by' => User::factory(),
];
}
}

View File

@@ -1,48 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class CreateReportTemplatesTable extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::create('report_templates', function (Blueprint $table) {
$table->id();
$table->integer('created_by')->nullable();
$table->string('name');
/*
* The "options" column was originally json but this causes issues
* with older versions of mariadb so it was changed text.
*
* A follow-up migration definitively changes it to a text column
* for the systems that had successfully run the migration:
* 2025_01_06_210534_change_report_templates_options_to_column_text_field.
*
* https://github.com/snipe/snipe-it/issues/16015
*/
$table->text('options');
$table->softDeletes();
$table->timestamps();
$table->index('created_by');
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::dropIfExists('report_templates');
}
}

View File

@@ -1,46 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
use Illuminate\Support\Facades\DB;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up()
{
// Copy values if target columns are blank
DB::table('settings')->whereNull('label2_2d_type')->orWhere('label2_2d_type', '')->update([
'label2_2d_type' => DB::raw('barcode_type')
]);
DB::table('settings')->whereNull('label2_1d_type')->orWhere('label2_1d_type', '')->update([
'label2_1d_type' => DB::raw('alt_barcode')
]);
Schema::table('settings', function (Blueprint $table) {
$table->dropColumn(['barcode_type', 'alt_barcode']);
});
}
public function down()
{
Schema::table('settings', function (Blueprint $table) {
// Re-add the columns that were dropped in case of rollback
$table->string('barcode_type')->nullable();
$table->string('alt_barcode')->nullable();
});
DB::table('settings')->whereNull('barcode_type')->orWhere('barcode_type', '')->update([
'barcode_type' => DB::raw('label2_2d_type')
]);
DB::table('settings')->whereNull('alt_barcode')->orWhere('alt_barcode', '')->update([
'alt_barcode' => DB::raw('label2_1d_type')
]);
}
};

View File

@@ -1,39 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration {
/**
* Run the migrations.
*/
public function up(): void
{
/*
* The "options" column was originally json but the migration was amended to change it to a text column
* since json columns cause issues with older versions of mariadb.
*
* This migration definitively changes it to a text column
* for the systems that had successfully run the migration.
*
* https://github.com/snipe/snipe-it/issues/16015
*/
if (Schema::hasTable('report_templates') && Schema::hasColumn('report_templates', 'options')) {
Schema::table('report_templates', function (Blueprint $table) {
$table->text('options')->change();
});
}
}
/**
* Reverse the migrations.
*/
public function down(): void
{
Schema::table('report_templates', function (Blueprint $table) {
// Instead of attempting to roll this back to json let's just
// keep it as text since that works for mysql, mariadb, and sqlite.
});
}
};

View File

@@ -1,43 +0,0 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
return new class extends Migration
{
/**
* Run the migrations.
*/
public function up(): void
{
DB::table('settings')->where('label2_2d_type', 'default')->update([
'label2_2d_type' => 'QRCODE',
]);
DB::table('settings')->where('label2_1d_type', 'default')->update([
'label2_1d_type' => 'C128',
]);
DB::table('settings')->whereNull('label2_2d_type')->orWhere('label2_2d_type', '')->update([
'label2_2d_type' => 'none',
]);
DB::table('settings')->whereNull('label2_1d_type')->orWhere('label2_1d_type', '')->update([
'label2_1d_type' => 'none',
]);
Schema::table('settings', function (Blueprint $table) {
$table->string('label2_2d_type')->default('QRCODE')->change();
$table->string('label2_1d_type')->default('C128')->change();
});
}
/**
* Reverse the migrations.
*/
public function down(): void
{
//
}
};

View File

@@ -8,7 +8,6 @@ use App\Models\LicenseSeat;
use App\Models\Supplier;
use App\Models\User;
use Illuminate\Database\Seeder;
use Illuminate\Support\Facades\Log;
class LicenseSeeder extends Seeder
{
@@ -21,20 +20,7 @@ class LicenseSeeder extends Seeder
$this->call(CategorySeeder::class);
}
$categories = Category::where('category_type', 'license')->get();
$graphicsSoftwareCategory = $categories->first(fn($category) => $category->name === 'Graphics Software');
$officeSoftwareCategory = $categories->first(fn($category) => $category->name === 'Office Software');
if (!$graphicsSoftwareCategory) {
Log::info('Graphics Software category not created. Using random category for seeding.');
$graphicsSoftwareCategory = Category::inRandomOrder()->first();
}
if (!$officeSoftwareCategory) {
Log::info('Office Software category not created. Using random category for seeding.');
$officeSoftwareCategory = Category::inRandomOrder()->first();
}
$categoryIds = Category::all()->pluck('id');
if (! Supplier::count()) {
$this->call(SupplierSeeder::class);
@@ -45,25 +31,25 @@ class LicenseSeeder extends Seeder
$admin = User::where('permissions->superuser', '1')->first() ?? User::factory()->firstAdmin()->create();
License::factory()->count(1)->photoshop()->create([
'category_id' => $graphicsSoftwareCategory->id,
'category_id' => $categoryIds->random(),
'supplier_id' => $supplierIds->random(),
'created_by' => $admin->id,
]);
License::factory()->count(1)->acrobat()->create([
'category_id' => $officeSoftwareCategory->id,
'category_id' => $categoryIds->random(),
'supplier_id' => $supplierIds->random(),
'created_by' => $admin->id,
]);
License::factory()->count(1)->indesign()->create([
'category_id' => $graphicsSoftwareCategory->id,
'category_id' => $categoryIds->random(),
'supplier_id' => $supplierIds->random(),
'created_by' => $admin->id,
]);
License::factory()->count(1)->office()->create([
'category_id' => $officeSoftwareCategory->id,
'category_id' => $categoryIds->random(),
'supplier_id' => $supplierIds->random(),
'created_by' => $admin->id,
]);

View File

@@ -19,12 +19,12 @@ class SettingsSeeder extends Seeder
$settings->logo = 'snipe-logo.png';
$settings->alert_email = 'service@snipe-it.io';
$settings->header_color = null;
$settings->label2_2d_type = 'QRCODE';
$settings->barcode_type = 'QRCODE';
$settings->default_currency = 'USD';
$settings->brand = 3;
$settings->ldap_enabled = 0;
$settings->full_multiple_companies_support = 0;
$settings->label2_1d_type = 'C128';
$settings->alt_barcode = 'C128';
$settings->skin = '';
$settings->email_domain = 'example.org';
$settings->email_format = 'filastname';

View File

@@ -6,7 +6,7 @@ volumes:
services:
app:
image: snipe/snipe-it:${APP_VERSION:-latest}
image: snipe/snipe-it:${APP_VERSION:-v7.0.11}
restart: unless-stopped
volumes:
- storage:/var/lib/snipeit

View File

@@ -103,7 +103,6 @@ php artisan migrate --force
php artisan config:clear
php artisan config:cache
touch /var/www/html/storage/logs/laravel.log
chown -R apache:root /var/www/html/storage/logs/laravel.log
export APACHE_LOG_DIR=/var/log/apache2

182
package-lock.json generated
View File

@@ -5,7 +5,7 @@
"packages": {
"": {
"dependencies": {
"@fortawesome/fontawesome-free": "^6.7.2",
"@fortawesome/fontawesome-free": "^6.6.0",
"acorn": "^8.12.0",
"acorn-import-assertions": "^1.9.0",
"admin-lte": "^2.4.18",
@@ -15,7 +15,7 @@
"bootstrap-colorpicker": "^2.5.3",
"bootstrap-datepicker": "^1.10.0",
"bootstrap-less": "^3.3.8",
"bootstrap-table": "1.24.0",
"bootstrap-table": "1.23.5",
"canvas-confetti": "^1.9.3",
"chart.js": "^2.9.4",
"clipboard": "^2.0.11",
@@ -27,7 +27,7 @@
"jquery-validation": "^1.21.0",
"jquery.iframe-transport": "^1.0.0",
"jspdf-autotable": "^3.8.4",
"less": "^4.2.1",
"less": "^4.2.0",
"less-loader": "^6.0",
"list.js": "^1.5.0",
"morris.js": "github:morrisjs/morris.js",
@@ -37,7 +37,7 @@
"signature_pad": "^4.2.0",
"tableexport.jquery.plugin": "1.30.0",
"tether": "^1.4.0",
"webpack": "^5.97.1"
"webpack": "^5.95.0"
},
"devDependencies": {
"all-contributors-cli": "^6.26.1",
@@ -1919,9 +1919,9 @@
}
},
"node_modules/@fortawesome/fontawesome-free": {
"version": "6.7.2",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.7.2.tgz",
"integrity": "sha512-JUOtgFW6k9u4Y+xeIaEiLr3+cjoUPiAuLXoyKOJSia6Duzb7pq+A76P9ZdPDoAoxHdHzq6gE9/jKBGXlZT8FbA==",
"version": "6.6.0",
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.6.0.tgz",
"integrity": "sha512-60G28ke/sXdtS9KZCpZSHHkCbdsOGEhIUGlwq6yhY74UpTiToIh8np7A8yphhM4BWsvNFtIvLpi4co+h9Mr9Ow==",
"engines": {
"node": ">=6"
}
@@ -2316,133 +2316,118 @@
}
},
"node_modules/@webassemblyjs/ast": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ast/-/ast-1.14.1.tgz",
"integrity": "sha512-nuBEDgQfm1ccRp/8bCQrx1frohyufl4JlbMMZ4P1wpeOfDhF6FQkxZJ1b/e+PLwr6X1Nhw6OLme5usuBWYBvuQ==",
"version": "1.12.1",
"license": "MIT",
"dependencies": {
"@webassemblyjs/helper-numbers": "1.13.2",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2"
"@webassemblyjs/helper-numbers": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6"
}
},
"node_modules/@webassemblyjs/floating-point-hex-parser": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/floating-point-hex-parser/-/floating-point-hex-parser-1.13.2.tgz",
"integrity": "sha512-6oXyTOzbKxGH4steLbLNOu71Oj+C8Lg34n6CqRvqfS2O71BxY6ByfMDRhBytzknj9yGUPVJ1qIKhRlAwO1AovA=="
"version": "1.11.6",
"license": "MIT"
},
"node_modules/@webassemblyjs/helper-api-error": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-api-error/-/helper-api-error-1.13.2.tgz",
"integrity": "sha512-U56GMYxy4ZQCbDZd6JuvvNV/WFildOjsaWD3Tzzvmw/mas3cXzRJPMjP83JqEsgSbyrmaGjBfDtV7KDXV9UzFQ=="
"version": "1.11.6",
"license": "MIT"
},
"node_modules/@webassemblyjs/helper-buffer": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-buffer/-/helper-buffer-1.14.1.tgz",
"integrity": "sha512-jyH7wtcHiKssDtFPRB+iQdxlDf96m0E39yb0k5uJVhFGleZFoNw1c4aeIcVUPPbXUVJ94wwnMOAqUHyzoEPVMA=="
"version": "1.12.1",
"license": "MIT"
},
"node_modules/@webassemblyjs/helper-numbers": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-numbers/-/helper-numbers-1.13.2.tgz",
"integrity": "sha512-FE8aCmS5Q6eQYcV3gI35O4J789wlQA+7JrqTTpJqn5emA4U2hvwJmvFRC0HODS+3Ye6WioDklgd6scJ3+PLnEA==",
"version": "1.11.6",
"license": "MIT",
"dependencies": {
"@webassemblyjs/floating-point-hex-parser": "1.13.2",
"@webassemblyjs/helper-api-error": "1.13.2",
"@webassemblyjs/floating-point-hex-parser": "1.11.6",
"@webassemblyjs/helper-api-error": "1.11.6",
"@xtuc/long": "4.2.2"
}
},
"node_modules/@webassemblyjs/helper-wasm-bytecode": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-bytecode/-/helper-wasm-bytecode-1.13.2.tgz",
"integrity": "sha512-3QbLKy93F0EAIXLh0ogEVR6rOubA9AoZ+WRYhNbFyuB70j3dRdwH9g+qXhLAO0kiYGlg3TxDV+I4rQTr/YNXkA=="
"version": "1.11.6",
"license": "MIT"
},
"node_modules/@webassemblyjs/helper-wasm-section": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/helper-wasm-section/-/helper-wasm-section-1.14.1.tgz",
"integrity": "sha512-ds5mXEqTJ6oxRoqjhWDU83OgzAYjwsCV8Lo/N+oRsNDmx/ZDpqalmrtgOMkHwxsG0iI//3BwWAErYRHtgn0dZw==",
"version": "1.12.1",
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-buffer": "1.14.1",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
"@webassemblyjs/wasm-gen": "1.14.1"
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/wasm-gen": "1.12.1"
}
},
"node_modules/@webassemblyjs/ieee754": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/ieee754/-/ieee754-1.13.2.tgz",
"integrity": "sha512-4LtOzh58S/5lX4ITKxnAK2USuNEvpdVV9AlgGQb8rJDHaLeHciwG4zlGr0j/SNWlr7x3vO1lDEsuePvtcDNCkw==",
"version": "1.11.6",
"license": "MIT",
"dependencies": {
"@xtuc/ieee754": "^1.2.0"
}
},
"node_modules/@webassemblyjs/leb128": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/leb128/-/leb128-1.13.2.tgz",
"integrity": "sha512-Lde1oNoIdzVzdkNEAWZ1dZ5orIbff80YPdHx20mrHwHrVNNTjNr8E3xz9BdpcGqRQbAEa+fkrCb+fRFTl/6sQw==",
"version": "1.11.6",
"license": "Apache-2.0",
"dependencies": {
"@xtuc/long": "4.2.2"
}
},
"node_modules/@webassemblyjs/utf8": {
"version": "1.13.2",
"resolved": "https://registry.npmjs.org/@webassemblyjs/utf8/-/utf8-1.13.2.tgz",
"integrity": "sha512-3NQWGjKTASY1xV5m7Hr0iPeXD9+RDobLll3T9d2AO+g3my8xy5peVyjSag4I50mR1bBSN/Ct12lo+R9tJk0NZQ=="
"version": "1.11.6",
"license": "MIT"
},
"node_modules/@webassemblyjs/wasm-edit": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-edit/-/wasm-edit-1.14.1.tgz",
"integrity": "sha512-RNJUIQH/J8iA/1NzlE4N7KtyZNHi3w7at7hDjvRNm5rcUXa00z1vRz3glZoULfJ5mpvYhLybmVcwcjGrC1pRrQ==",
"version": "1.12.1",
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-buffer": "1.14.1",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
"@webassemblyjs/helper-wasm-section": "1.14.1",
"@webassemblyjs/wasm-gen": "1.14.1",
"@webassemblyjs/wasm-opt": "1.14.1",
"@webassemblyjs/wasm-parser": "1.14.1",
"@webassemblyjs/wast-printer": "1.14.1"
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/helper-wasm-section": "1.12.1",
"@webassemblyjs/wasm-gen": "1.12.1",
"@webassemblyjs/wasm-opt": "1.12.1",
"@webassemblyjs/wasm-parser": "1.12.1",
"@webassemblyjs/wast-printer": "1.12.1"
}
},
"node_modules/@webassemblyjs/wasm-gen": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-gen/-/wasm-gen-1.14.1.tgz",
"integrity": "sha512-AmomSIjP8ZbfGQhumkNvgC33AY7qtMCXnN6bL2u2Js4gVCg8fp735aEiMSBbDR7UQIj90n4wKAFUSEd0QN2Ukg==",
"version": "1.12.1",
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
"@webassemblyjs/ieee754": "1.13.2",
"@webassemblyjs/leb128": "1.13.2",
"@webassemblyjs/utf8": "1.13.2"
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/ieee754": "1.11.6",
"@webassemblyjs/leb128": "1.11.6",
"@webassemblyjs/utf8": "1.11.6"
}
},
"node_modules/@webassemblyjs/wasm-opt": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-opt/-/wasm-opt-1.14.1.tgz",
"integrity": "sha512-PTcKLUNvBqnY2U6E5bdOQcSM+oVP/PmrDY9NzowJjislEjwP/C4an2303MCVS2Mg9d3AJpIGdUFIQQWbPds0Sw==",
"version": "1.12.1",
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-buffer": "1.14.1",
"@webassemblyjs/wasm-gen": "1.14.1",
"@webassemblyjs/wasm-parser": "1.14.1"
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-buffer": "1.12.1",
"@webassemblyjs/wasm-gen": "1.12.1",
"@webassemblyjs/wasm-parser": "1.12.1"
}
},
"node_modules/@webassemblyjs/wasm-parser": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wasm-parser/-/wasm-parser-1.14.1.tgz",
"integrity": "sha512-JLBl+KZ0R5qB7mCnud/yyX08jWFw5MsoalJ1pQ4EdFlgj9VdXKGuENGsiCIjegI1W7p91rUlcB/LB5yRJKNTcQ==",
"version": "1.12.1",
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/helper-api-error": "1.13.2",
"@webassemblyjs/helper-wasm-bytecode": "1.13.2",
"@webassemblyjs/ieee754": "1.13.2",
"@webassemblyjs/leb128": "1.13.2",
"@webassemblyjs/utf8": "1.13.2"
"@webassemblyjs/ast": "1.12.1",
"@webassemblyjs/helper-api-error": "1.11.6",
"@webassemblyjs/helper-wasm-bytecode": "1.11.6",
"@webassemblyjs/ieee754": "1.11.6",
"@webassemblyjs/leb128": "1.11.6",
"@webassemblyjs/utf8": "1.11.6"
}
},
"node_modules/@webassemblyjs/wast-printer": {
"version": "1.14.1",
"resolved": "https://registry.npmjs.org/@webassemblyjs/wast-printer/-/wast-printer-1.14.1.tgz",
"integrity": "sha512-kPSSXE6De1XOR820C90RIo2ogvZG+c3KiHzqUoO/F34Y2shGzesfqv7o57xrxovZJH/MetF5UjroJ/R/3isoiw==",
"version": "1.12.1",
"license": "MIT",
"dependencies": {
"@webassemblyjs/ast": "1.14.1",
"@webassemblyjs/ast": "1.12.1",
"@xtuc/long": "4.2.2"
}
},
@@ -2481,13 +2466,11 @@
},
"node_modules/@xtuc/ieee754": {
"version": "1.2.0",
"resolved": "https://registry.npmjs.org/@xtuc/ieee754/-/ieee754-1.2.0.tgz",
"integrity": "sha512-DX8nKgqcGwsc0eJSqYt5lwP4DH5FlHnmuWWBRy7X0NcaGR0ZtuyeESgMwTYVEtxmsNGY+qit4QYT/MIYTOTPeA=="
"license": "BSD-3-Clause"
},
"node_modules/@xtuc/long": {
"version": "4.2.2",
"resolved": "https://registry.npmjs.org/@xtuc/long/-/long-4.2.2.tgz",
"integrity": "sha512-NuHqBY1PB/D8xU6s/thBgOAiAP7HOYDQ32+BFZILJ8ivkUkAHQnWfn6WhL79Owj1qmUnoN/YPhktdIoucipkAQ=="
"license": "Apache-2.0"
},
"node_modules/accepts": {
"version": "1.3.8",
@@ -3705,9 +3688,9 @@
"license": "MIT"
},
"node_modules/bootstrap-table": {
"version": "1.24.0",
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.24.0.tgz",
"integrity": "sha512-dyRf5PQwTgFHj9yjuPXa+GIf4JpuQhsgD1CJrOqhw40qI2gTb3mJfRdoBc7iF2bqzOl+k0RnbAlhSPbGe4VS+w==",
"version": "1.23.5",
"resolved": "https://registry.npmjs.org/bootstrap-table/-/bootstrap-table-1.23.5.tgz",
"integrity": "sha512-9WByoSpJvA73gi2YYIlX6IWR74oZtBmSixul/Th8FTBtBd/kZRpbKESGTjhA3BA3AYTnfyY8Iy1KeRWPlV2GWQ==",
"peerDependencies": {
"jquery": "3"
}
@@ -7468,9 +7451,8 @@
}
},
"node_modules/less": {
"version": "4.2.1",
"resolved": "https://registry.npmjs.org/less/-/less-4.2.1.tgz",
"integrity": "sha512-CasaJidTIhWmjcqv0Uj5vccMI7pJgfD9lMkKtlnTHAdJdYK/7l8pM9tumLyJ0zhbD4KJLo/YvTj+xznQd5NBhg==",
"version": "4.2.0",
"license": "Apache-2.0",
"dependencies": {
"copy-anything": "^2.0.1",
"parse-node-version": "^1.0.1",
@@ -10901,15 +10883,15 @@
"license": "BSD-2-Clause"
},
"node_modules/webpack": {
"version": "5.97.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.97.1.tgz",
"integrity": "sha512-EksG6gFY3L1eFMROS/7Wzgrii5mBAFe4rIr3r2BTfo7bcc+DWwFZ4OJ/miOuHJO/A85HwyI4eQ0F6IKXesO7Fg==",
"version": "5.96.1",
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.96.1.tgz",
"integrity": "sha512-l2LlBSvVZGhL4ZrPwyr8+37AunkcYj5qh8o6u2/2rzoPc8gxFJkLj1WxNgooi9pnoc06jh0BjuXnamM4qlujZA==",
"dependencies": {
"@types/eslint-scope": "^3.7.7",
"@types/estree": "^1.0.6",
"@webassemblyjs/ast": "^1.14.1",
"@webassemblyjs/wasm-edit": "^1.14.1",
"@webassemblyjs/wasm-parser": "^1.14.1",
"@webassemblyjs/ast": "^1.12.1",
"@webassemblyjs/wasm-edit": "^1.12.1",
"@webassemblyjs/wasm-parser": "^1.12.1",
"acorn": "^8.14.0",
"browserslist": "^4.24.0",
"chrome-trace-event": "^1.0.2",

View File

@@ -25,7 +25,7 @@
"postcss": "^8.4.5"
},
"dependencies": {
"@fortawesome/fontawesome-free": "^6.7.2",
"@fortawesome/fontawesome-free": "^6.6.0",
"acorn": "^8.12.0",
"acorn-import-assertions": "^1.9.0",
"admin-lte": "^2.4.18",
@@ -35,7 +35,7 @@
"bootstrap-colorpicker": "^2.5.3",
"bootstrap-datepicker": "^1.10.0",
"bootstrap-less": "^3.3.8",
"bootstrap-table": "1.24.0",
"bootstrap-table": "1.23.5",
"canvas-confetti": "^1.9.3",
"chart.js": "^2.9.4",
"clipboard": "^2.0.11",
@@ -47,7 +47,7 @@
"jquery-validation": "^1.21.0",
"jquery.iframe-transport": "^1.0.0",
"jspdf-autotable": "^3.8.4",
"less": "^4.2.1",
"less": "^4.2.0",
"less-loader": "^6.0",
"list.js": "^1.5.0",
"morris.js": "github:morrisjs/morris.js",
@@ -57,6 +57,6 @@
"signature_pad": "^4.2.0",
"tableexport.jquery.plugin": "1.30.0",
"tether": "^1.4.0",
"webpack": "^5.97.1"
"webpack": "^5.95.0"
}
}

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

Some files were not shown because too many files have changed in this diff Show More