diff --git a/app/Console/Commands/RestoreFromBackup.php b/app/Console/Commands/RestoreFromBackup.php index c5e3a4c790..b1f1753564 100644 --- a/app/Console/Commands/RestoreFromBackup.php +++ b/app/Console/Commands/RestoreFromBackup.php @@ -149,7 +149,7 @@ class RestoreFromBackup extends Command $boring_files[] = $raw_path; continue; } - if (@pathinfo($raw_path)['extension'] == 'sql') { + if (@pathinfo($raw_path, PATHINFO_EXTENSION) == 'sql') { \Log::debug("Found a sql file!"); $sqlfiles[] = $raw_path; $sqlfile_indices[] = $i; diff --git a/app/Http/Controllers/Account/AcceptanceController.php b/app/Http/Controllers/Account/AcceptanceController.php index 59c8f88430..726e164ba8 100644 --- a/app/Http/Controllers/Account/AcceptanceController.php +++ b/app/Http/Controllers/Account/AcceptanceController.php @@ -222,8 +222,8 @@ class AcceptanceController extends Controller 'item_model' => $display_model, 'item_serial' => $item->serial, 'eula' => $item->getEula(), - 'check_out_date' => Carbon::parse($acceptance->created_at)->format($branding_settings->date_display_format), - 'accepted_date' => Carbon::parse($acceptance->accepted_at)->format($branding_settings->date_display_format), + 'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d'), + 'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d'), 'assigned_to' => $assigned_to, 'company_name' => $branding_settings->site_name, 'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null, @@ -273,7 +273,7 @@ class AcceptanceController extends Controller 'item_tag' => $item->asset_tag, 'item_model' => $display_model, 'item_serial' => $item->serial, - 'declined_date' => Carbon::parse($acceptance->accepted_at)->format($branding_settings->date_display_format), + 'declined_date' => Carbon::parse($acceptance->declined_at)->format('Y-m-d'), 'assigned_to' => $assigned_to, 'company_name' => $branding_settings->site_name, 'date_settings' => $branding_settings->date_display_format, diff --git a/app/Http/Controllers/Api/ImportController.php b/app/Http/Controllers/Api/ImportController.php index e5f0c6ab1f..9742cc1644 100644 --- a/app/Http/Controllers/Api/ImportController.php +++ b/app/Http/Controllers/Api/ImportController.php @@ -127,7 +127,7 @@ class ImportController extends Controller $this->authorize('import'); // Run a backup immediately before processing - if ($request->has('run-backup')) { + if ($request->get('run-backup')) { \Log::debug('Backup manually requested via importer'); Artisan::call('backup:run'); } else { diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php index cca829c23f..9a9135a380 100644 --- a/app/Http/Controllers/Api/UsersController.php +++ b/app/Http/Controllers/Api/UsersController.php @@ -542,9 +542,10 @@ class UsersController extends Controller if (empty($user->email)) { return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error'))); } + + $user->notify((new CurrentInventory($user))); - return response()->Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success')); - + return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success'))); } /** diff --git a/app/Http/Controllers/ProfileController.php b/app/Http/Controllers/ProfileController.php index 739376e3ab..cf5f49feb0 100755 --- a/app/Http/Controllers/ProfileController.php +++ b/app/Http/Controllers/ProfileController.php @@ -67,37 +67,9 @@ class ProfileController extends Controller $user->location_id = $request->input('location_id'); } + // Handle the avatar upload and/or delete if necessary + app('\App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'avatar', 'avatars', 'avatar'); - if ($request->input('avatar_delete') == 1) { - $user->avatar = null; - } - - - if ($request->hasFile('avatar')) { - $path = 'avatars'; - - if (! Storage::disk('public')->exists($path)) { - Storage::disk('public')->makeDirectory($path, 775); - } - - $upload = $image = $request->file('avatar'); - $ext = $image->getClientOriginalExtension(); - $file_name = 'avatar-'.str_random(18).'.'.$ext; - - if ($image->getClientOriginalExtension() != 'svg') { - $upload = Image::make($image->getRealPath())->resize(84, 84); - } - - // This requires a string instead of an object, so we use ($string) - Storage::disk('public')->put($path.'/'.$file_name, (string) $upload->encode()); - - // Remove Current image if exists - if (($user->avatar) && (Storage::disk('public')->exists($path.'/'.$user->avatar))) { - Storage::disk('public')->delete($path.'/'.$user->avatar); - } - - $user->avatar = $file_name; - } if ($user->save()) { return redirect()->route('profile')->with('success', 'Account successfully updated'); diff --git a/app/Http/Controllers/Users/UsersController.php b/app/Http/Controllers/Users/UsersController.php index 52d423036f..2a34992552 100755 --- a/app/Http/Controllers/Users/UsersController.php +++ b/app/Http/Controllers/Users/UsersController.php @@ -131,7 +131,7 @@ class UsersController extends Controller $user->permissions = json_encode($permissions_array); // we have to invoke the - app(\App\Http\Requests\ImageUploadRequest::class)->handleImages($user, 600, 'image', 'avatars', 'avatar'); + app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar'); if ($user->save()) { if ($request->filled('groups')) { @@ -296,7 +296,7 @@ class UsersController extends Controller $user->permissions = json_encode($permissions_array); // Handle uploaded avatar - app(\App\Http\Requests\ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar'); + app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar'); //\Log::debug(print_r($user, true)); diff --git a/app/Http/Requests/ImageUploadRequest.php b/app/Http/Requests/ImageUploadRequest.php index 1b0b051366..6fb6ead210 100644 --- a/app/Http/Requests/ImageUploadRequest.php +++ b/app/Http/Requests/ImageUploadRequest.php @@ -63,11 +63,13 @@ class ImageUploadRequest extends Request * @param string $path location for uploaded images, defaults to uploads/plural of item type. * @return SnipeModel Target asset is being checked out to. */ - public function handleImages($item, $w = 600, $form_fieldname = null, $path = null, $db_fieldname = 'image') + public function handleImages($item, $w = 600, $form_fieldname = 'image', $path = null, $db_fieldname = 'image') { + $type = strtolower(class_basename(get_class($item))); if (is_null($path)) { + $path = str_plural($type); if ($type == 'assetmodel') { @@ -79,42 +81,31 @@ class ImageUploadRequest extends Request } } - if (is_null($form_fieldname)) { - $form_fieldname = 'image'; - } - - // This is dumb, but we need it for overriding field names for exceptions like avatars and logo uploads - if (is_null($db_fieldname)) { - $use_db_field = $form_fieldname; - } else { - $use_db_field = $db_fieldname; - } - - - // ConvertBase64ToFiles just changes object type, - // as it cannot currently insert files to $this->files if ($this->offsetGet($form_fieldname) instanceof UploadedFile) { - $image=$this->offsetGet($form_fieldname); + $image = $this->offsetGet($form_fieldname); + \Log::debug('Image is an instance of UploadedFile'); + } elseif ($this->hasFile($form_fieldname)) { + $image = $this->file($form_fieldname); + \Log::debug('Just use regular upload for '.$form_fieldname); } else { - if ($this->hasFile($form_fieldname)) { - $image = $this->file($form_fieldname); - } + \Log::debug('No image found for form fieldname: '.$form_fieldname); } if (isset($image)) { - \Log::debug($image); if (!config('app.lock_passwords')) { $ext = $image->getClientOriginalExtension(); - $file_name = $type.'-'.$form_fieldname.'-'.str_random(10).'.'.$ext; + $file_name = $type.'-'.$form_fieldname.'-'.$item->id.'-'.str_random(10).'.'.$ext; \Log::info('File name will be: '.$file_name); \Log::debug('File extension is: '.$ext); if (($image->getClientOriginalExtension() !== 'webp') && ($image->getClientOriginalExtension() !== 'svg')) { + \Log::debug('Not an SVG or webp - resize'); \Log::debug('Trying to upload to: '.$path.'/'.$file_name); + $upload = Image::make($image->getRealPath())->resize(null, $w, function ($constraint) { $constraint->aspectRatio(); $constraint->upsize(); @@ -122,6 +113,7 @@ class ImageUploadRequest extends Request // This requires a string instead of an object, so we use ($string) Storage::disk('public')->put($path.'/'.$file_name, (string) $upload->encode()); + } else { // If the file is a webp, we need to just move it since webp support // needs to be compiled into gd for resizing to be available @@ -146,30 +138,30 @@ class ImageUploadRequest extends Request } // Remove Current image if exists - if (($item->{$use_db_field}!='') && (Storage::disk('public')->exists($path.'/'.$item->{$use_db_field}))) { + if (($item->{$form_fieldname}!='') && (Storage::disk('public')->exists($path.'/'.$item->{$db_fieldname}))) { \Log::debug('A file already exists that we are replacing - we should delete the old one.'); try { - Storage::disk('public')->delete($path.'/'.$item->{$use_db_field}); + Storage::disk('public')->delete($path.'/'.$item->{$form_fieldname}); \Log::debug('Old file '.$path.'/'.$file_name.' has been deleted.'); } catch (\Exception $e) { \Log::debug('Could not delete old file. '.$path.'/'.$file_name.' does not exist?'); } } - $item->{$use_db_field} = $file_name; + $item->{$db_fieldname} = $file_name; } + // If the user isn't uploading anything new but wants to delete their old image, do so - } else { - if ($this->input('image_delete') == '1') { - \Log::debug('Deleting image'); - try { - Storage::disk('public')->delete($path.'/'.$item->{$use_db_field}); - $item->{$use_db_field} = null; - } catch (\Exception $e) { - \Log::debug($e); - } + } elseif ($this->input('image_delete') == '1') { + \Log::debug('Deleting image'); + try { + Storage::disk('public')->delete($path.'/'.$item->{$db_fieldname}); + $item->{$db_fieldname} = null; + } catch (\Exception $e) { + \Log::debug($e); } + } return $item; diff --git a/app/Models/SnipeSCIMConfig.php b/app/Models/SnipeSCIMConfig.php index 36a9ac855c..77cbf01c1a 100644 --- a/app/Models/SnipeSCIMConfig.php +++ b/app/Models/SnipeSCIMConfig.php @@ -12,94 +12,9 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig { public function getUserConfig() { - $config = parent::getUserConfig(); - // Much of this is copied verbatim from the library, then adjusted for our needs - $config['class'] = SCIMUser::class; - unset($config['mapping']['example:name:space']); - - $config['map_unmapped'] = false; // anything we don't explicitly map will _not_ show up. - - $core_namespace = 'urn:ietf:params:scim:schemas:core:2.0:User'; - $core = $core_namespace.':'; - $mappings =& $config['mapping'][$core_namespace]; //grab this entire key, we don't want to be repeating ourselves - - //username - *REQUIRED* - $config['validations'][$core.'userName'] = 'required'; - $mappings['userName'] = AttributeMapping::eloquent('username'); - - //human name - *FIRST NAME REQUIRED* - $config['validations'][$core.'name.givenName'] = 'required'; - $config['validations'][$core.'name.familyName'] = 'string'; //not required - - $mappings['name']['familyName'] = AttributeMapping::eloquent("last_name"); - $mappings['name']['givenName'] = AttributeMapping::eloquent("first_name"); - $mappings['name']['formatted'] = (new AttributeMapping())->ignoreWrite()->setRead( - function (&$object) { - return $object->getFullNameAttribute(); - } - ); - - // externalId support - $config['validations'][$core.'externalId'] = 'string|nullable'; // not required, but supported mostly just for Okta - // note that the mapping is *not* namespaced like the other $mappings - $config['mapping']['externalId'] = AttributeMapping::eloquent('scim_externalid'); - - $config['validations'][$core.'emails'] = 'nullable|array'; // emails are not required in Snipe-IT... - $config['validations'][$core.'emails.*.value'] = 'email'; // ...(had to remove the recommended 'required' here) - - $mappings['emails'] = [[ - "value" => AttributeMapping::eloquent("email"), - "display" => null, - "type" => AttributeMapping::constant("work")->ignoreWrite(), - "primary" => AttributeMapping::constant(true)->ignoreWrite() - ]]; - - //active - $config['validations'][$core.'active'] = 'boolean'; - - $mappings['active'] = AttributeMapping::eloquent('activated'); - - //phone - $config['validations'][$core.'phoneNumbers'] = 'nullable|array'; - $config['validations'][$core.'phoneNumbers.*.value'] = 'string'; // another one where want to say 'we don't _need_ a phone number, but if you have one it better have a value. - - $mappings['phoneNumbers'] = [[ - "value" => AttributeMapping::eloquent("phone"), - "display" => null, - "type" => AttributeMapping::constant("work")->ignoreWrite(), - "primary" => AttributeMapping::constant(true)->ignoreWrite() - ]]; - - //address - $config['validations'][$core.'addresses'] = 'nullable|array'; - $config['validations'][$core.'addresses.*.streetAddress'] = 'string'; - $config['validations'][$core.'addresses.*.locality'] = 'string'; - $config['validations'][$core.'addresses.*.region'] = 'nullable|string'; - $config['validations'][$core.'addresses.*.postalCode'] = 'nullable|string'; - $config['validations'][$core.'addresses.*.country'] = 'string'; - - $mappings['addresses'] = [[ - 'type' => AttributeMapping::constant("work")->ignoreWrite(), - 'formatted' => AttributeMapping::constant("n/a")->ignoreWrite(), // TODO - is this right? This doesn't look right. - 'streetAddress' => AttributeMapping::eloquent("address"), - 'locality' => AttributeMapping::eloquent("city"), - 'region' => AttributeMapping::eloquent("state"), - 'postalCode' => AttributeMapping::eloquent("zip"), - 'country' => AttributeMapping::eloquent("country"), - 'primary' => AttributeMapping::constant(true)->ignoreWrite() //this isn't in the example? - ]]; - - //title - $config['validations'][$core.'title'] = 'string'; - $mappings['title'] = AttributeMapping::eloquent('jobtitle'); - - //Preferred Language - $config['validations'][$core.'preferredLanguage'] = 'string'; - $mappings['preferredLanguage'] = AttributeMapping::eloquent('locale'); - - /* + /* more snipe-it attributes I'd like to check out (to map to 'enterprise' maybe?): - website - notes? @@ -108,66 +23,213 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig - company_id to "organization?" */ - $enterprise_namespace = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User'; - $ent = $enterprise_namespace.':'; - // we remove the 'example' namespace and add the Enterprise one - $config['mapping']['schemas'] = AttributeMapping::constant( [$core_namespace, $enterprise_namespace] )->ignoreWrite(); + $user_prefix = 'urn:ietf:params:scim:schemas:core:2.0:User:'; + $enterprise_prefix = 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User:'; - $config['validations'][$ent.'employeeNumber'] = 'string'; - $config['validations'][$ent.'department'] = 'string'; - $config['validations'][$ent.'manager'] = 'nullable'; - $config['validations'][$ent.'manager.value'] = 'string'; + return [ - $config['mapping'][$enterprise_namespace] = [ - 'employeeNumber' => AttributeMapping::eloquent('employee_num'), - 'department' =>(new AttributeMapping())->setAdd( // FIXME parent? - function ($value, &$object) { - $department = Department::where("name", $value)->first(); - if ($department) { - $object->department_id = $department->id; - } - } - )->setReplace( - function ($value, &$object) { - $department = Department::where("name", $value)->first(); - if ($department) { - $object->department_id = $department->id; + // Set to 'null' to make use of auth.providers.users.model (App\User::class) + 'class' => SCIMUser::class, + + 'validations' => [ + $user_prefix . 'userName' => 'required', + $user_prefix . 'name.givenName' => 'required', + $user_prefix . 'name.familyName' => 'nullable|string', + $user_prefix . 'externalId' => 'nullable|string', + $user_prefix . 'emails' => 'nullable|array', + $user_prefix . 'emails.*.value' => 'nullable|email', + $user_prefix . 'active' => 'boolean', + $user_prefix . 'phoneNumbers' => 'nullable|array', + $user_prefix . 'phoneNumbers.*.value' => 'nullable|string', + $user_prefix . 'addresses' => 'nullable|array', + $user_prefix . 'addresses.*.streetAddress' => 'nullable|string', + $user_prefix . 'addresses.*.locality' => 'nullable|string', + $user_prefix . 'addresses.*.region' => 'nullable|string', + $user_prefix . 'addresses.*.postalCode' => 'nullable|string', + $user_prefix . 'addresses.*.country' => 'nullable|string', + $user_prefix . 'title' => 'nullable|string', + $user_prefix . 'preferredLanguage' => 'nullable|string', + + // Enterprise validations: + $enterprise_prefix . 'employeeNumber' => 'nullable|string', + $enterprise_prefix . 'department' => 'nullable|string', + $enterprise_prefix . 'manager' => 'nullable', + $enterprise_prefix . 'manager.value' => 'nullable|string' + ], + + 'singular' => 'User', + 'schema' => [Schema::SCHEMA_USER], + + //eager loading + 'withRelations' => [], + 'map_unmapped' => false, +// 'unmapped_namespace' => 'urn:ietf:params:scim:schemas:laravel:unmapped', + 'description' => 'User Account', + + // Map a SCIM attribute to an attribute of the object. + 'mapping' => [ + + 'id' => AttributeMapping::eloquent("id")->disableWrite(), + + 'externalId' => AttributeMapping::eloquent('scim_externalid'), // FIXME - I have a PR that changes a lot of this. + + 'meta' => [ + 'created' => AttributeMapping::eloquent("created_at")->disableWrite(), + 'lastModified' => AttributeMapping::eloquent("updated_at")->disableWrite(), + + 'location' => (new AttributeMapping())->setRead( + function ($object) { + return route( + 'scim.resource', + [ + 'resourceType' => 'Users', + 'resourceObject' => $object->id + ] + ); } - } - )->setRead( - function (&$object) { - return $object->department ? $object->department->name : null; - } - ), - 'manager' => [ - // FIXME - manager writes are disabled. This kinda works but it leaks errors all over the place. Not cool. - // '$ref' => (new AttributeMapping())->ignoreWrite()->ignoreRead(), - // 'displayName' => (new AttributeMapping())->ignoreWrite()->ignoreRead(), - // NOTE: you could probably do a 'plain' Eloquent mapping here, but we don't for future-proofing - 'value' => (new AttributeMapping())->setAdd( - function ($value, &$object) { - $manager = User::find($value); - if ($manager) { - $object->manager_id = $manager->id; + )->disableWrite(), + + 'resourceType' => AttributeMapping::constant("User") + ], + + 'schemas' => AttributeMapping::constant( + [ + 'urn:ietf:params:scim:schemas:core:2.0:User', + 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' + ] + )->ignoreWrite(), + + 'urn:ietf:params:scim:schemas:core:2.0:User' => [ + + 'userName' => AttributeMapping::eloquent("username"), + + 'name' => [ + 'formatted' => (new AttributeMapping())->ignoreWrite()->setRead( + function (&$object) { + return $object->getFullNameAttribute(); + } + ), + 'familyName' => AttributeMapping::eloquent("last_name"), + 'givenName' => AttributeMapping::eloquent("first_name"), + 'middleName' => null, + 'honorificPrefix' => null, + 'honorificSuffix' => null + ], + + 'displayName' => null, + 'nickName' => null, + 'profileUrl' => null, + 'title' => AttributeMapping::eloquent('jobtitle'), + 'userType' => null, + 'preferredLanguage' => AttributeMapping::eloquent('locale'), // Section 5.3.5 of [RFC7231] + 'locale' => null, // see RFC5646 + 'timezone' => null, // see RFC6557 + 'active' => AttributeMapping::eloquent('activated'), + + 'password' => AttributeMapping::eloquent('password')->disableRead(), + + // Multi-Valued Attributes + 'emails' => [[ + "value" => AttributeMapping::eloquent("email"), + "display" => null, + "type" => AttributeMapping::constant("work")->ignoreWrite(), + "primary" => AttributeMapping::constant(true)->ignoreWrite() + ]], + + 'phoneNumbers' => [[ + "value" => AttributeMapping::eloquent("phone"), + "display" => null, + "type" => AttributeMapping::constant("work")->ignoreWrite(), + "primary" => AttributeMapping::constant(true)->ignoreWrite() + ]], + + 'ims' => [[ + "value" => null, + "display" => null, + "type" => null, + "primary" => null + ]], // Instant messaging addresses for the User + + 'photos' => [[ + "value" => null, + "display" => null, + "type" => null, + "primary" => null + ]], + + 'addresses' => [[ + 'type' => AttributeMapping::constant("work")->ignoreWrite(), + 'formatted' => AttributeMapping::constant("n/a")->ignoreWrite(), // TODO - is this right? This doesn't look right. + 'streetAddress' => AttributeMapping::eloquent("address"), + 'locality' => AttributeMapping::eloquent("city"), + 'region' => AttributeMapping::eloquent("state"), + 'postalCode' => AttributeMapping::eloquent("zip"), + 'country' => AttributeMapping::eloquent("country"), + 'primary' => AttributeMapping::constant(true)->ignoreWrite() //this isn't in the example? + ]], + + 'groups' => [[ + 'value' => null, + '$ref' => null, + 'display' => null, + 'type' => null, + 'type' => null + ]], + + 'entitlements' => null, + 'roles' => null, + 'x509Certificates' => null + ], + + 'urn:ietf:params:scim:schemas:extension:enterprise:2.0:User' => [ + 'employeeNumber' => AttributeMapping::eloquent('employee_num'), + 'department' => (new AttributeMapping())->setAdd( // FIXME parent? + function ($value, &$object) { + $department = Department::where("name", $value)->first(); + if ($department) { + $object->department_id = $department->id; + } } - } )->setReplace( function ($value, &$object) { - $manager = User::find($value); - if ($manager) { - $object->manager_id = $manager->id; + $department = Department::where("name", $value)->first(); + if ($department) { + $object->department_id = $department->id; } } )->setRead( function (&$object) { - return $object->manager_id; - } + return $object->department ? $object->department->name : null; + } ), + 'manager' => [ + // FIXME - manager writes are disabled. This kinda works but it leaks errors all over the place. Not cool. + // '$ref' => (new AttributeMapping())->ignoreWrite()->ignoreRead(), + // 'displayName' => (new AttributeMapping())->ignoreWrite()->ignoreRead(), + // NOTE: you could probably do a 'plain' Eloquent mapping here, but we don't for future-proofing + 'value' => (new AttributeMapping())->setAdd( + function ($value, &$object) { + $manager = User::find($value); + if ($manager) { + $object->manager_id = $manager->id; + } + } + )->setReplace( + function ($value, &$object) { + $manager = User::find($value); + if ($manager) { + $object->manager_id = $manager->id; + } + } + )->setRead( + function (&$object) { + return $object->manager_id; + } + ), + ] + ] ] ]; - - return $config; } - } diff --git a/app/Models/User.php b/app/Models/User.php index 399008430b..34c0af6b2e 100755 --- a/app/Models/User.php +++ b/app/Models/User.php @@ -61,7 +61,9 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo 'remote', 'start_date', 'end_date', - 'scim_externalid' + 'scim_externalid', + 'avatar', + 'gravatar', ]; protected $casts = [ diff --git a/composer.lock b/composer.lock index bf8cb1f758..d6067c5e27 100644 --- a/composer.lock +++ b/composer.lock @@ -78,12 +78,12 @@ "source": { "type": "git", "url": "https://github.com/grokability/laravel-scim-server.git", - "reference": "2c7ecc450eee59234e059ec2e7724b2d8f3a8369" + "reference": "9e8dd2d3958d3c3c05d0a99fe6475361ad9e9419" }, "dist": { "type": "zip", - "url": "https://api.github.com/repos/grokability/laravel-scim-server/zipball/2c7ecc450eee59234e059ec2e7724b2d8f3a8369", - "reference": "2c7ecc450eee59234e059ec2e7724b2d8f3a8369", + "url": "https://api.github.com/repos/grokability/laravel-scim-server/zipball/9e8dd2d3958d3c3c05d0a99fe6475361ad9e9419", + "reference": "9e8dd2d3958d3c3c05d0a99fe6475361ad9e9419", "shasum": "" }, "require": { @@ -133,7 +133,7 @@ "support": { "source": "https://github.com/grokability/laravel-scim-server/tree/master" }, - "time": "2022-11-22T20:26:54+00:00" + "time": "2023-01-12T00:32:07+00:00" }, { "name": "asm89/stack-cors", diff --git a/config/database.php b/config/database.php index 9d94454db2..36440b2127 100755 --- a/config/database.php +++ b/config/database.php @@ -102,6 +102,7 @@ return [ 'pgsql' => [ 'driver' => 'pgsql', 'host' => env('DB_HOST', 'localhost'), + 'port' => env('DB_PORT', '5432'), 'database' => env('DB_DATABASE', 'forge'), 'username' => env('DB_USERNAME', 'forge'), 'password' => env('DB_PASSWORD', ''), diff --git a/config/scim.php b/config/scim.php index d7d578efc2..4e343cd3a6 100644 --- a/config/scim.php +++ b/config/scim.php @@ -3,6 +3,6 @@ return [ "trace" => env("SCIM_TRACE",false), // below, if we ever get 'sure' that we can change this default to 'true' we should - "omit_main_schema_in_return" => env('SCIM_STANDARDS_COMPLIANCE', false), + "omit_main_schema_in_return" => env('SCIM_STANDARDS_COMPLIANCE', true), "publish_routes" => false, ]; diff --git a/public/css/dist/skins/skin-contrast.css b/public/css/dist/skins/skin-contrast.css index b5d7fc4e9b..50dfc577e2 100644 --- a/public/css/dist/skins/skin-contrast.css +++ b/public/css/dist/skins/skin-contrast.css @@ -149,6 +149,13 @@ background-color: #000000; color: #fff; } +a.btn.btn-link.text-left { + color: #001F3F; + border: 1px solid #000; +} +a.btn.btn-link.text-left:hover { + color: #001F3F; +} a { color: #001F3F; } @@ -163,9 +170,6 @@ a.btn:hover { color: #fff; text-decoration: underline; } -a.btn:visited { - color: #fff; -} .text-primary { color: #000000; } diff --git a/public/css/dist/skins/skin-contrast.min.css b/public/css/dist/skins/skin-contrast.min.css index b5d7fc4e9b..50dfc577e2 100644 --- a/public/css/dist/skins/skin-contrast.min.css +++ b/public/css/dist/skins/skin-contrast.min.css @@ -149,6 +149,13 @@ background-color: #000000; color: #fff; } +a.btn.btn-link.text-left { + color: #001F3F; + border: 1px solid #000; +} +a.btn.btn-link.text-left:hover { + color: #001F3F; +} a { color: #001F3F; } @@ -163,9 +170,6 @@ a.btn:hover { color: #fff; text-decoration: underline; } -a.btn:visited { - color: #fff; -} .text-primary { color: #000000; } diff --git a/public/img/snipe-logo-bug.png b/public/img/snipe-logo-bug.png new file mode 100644 index 0000000000..423a5b7490 Binary files /dev/null and b/public/img/snipe-logo-bug.png differ diff --git a/public/mix-manifest.json b/public/mix-manifest.json index 719da79a95..b200128c7d 100644 --- a/public/mix-manifest.json +++ b/public/mix-manifest.json @@ -16,7 +16,7 @@ "/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=76482123f6c70e866d6b971ba91de7bb", "/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=c0d21166315b7c2cdd4819fa4a5e4d1e", "/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=0a82a6ae6bb4e58fe62d162c4fb50397", - "/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=8e538625ebd4b8096e150d1aa483547b", + "/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=da6c7997d9de2f8329142399f0ce50da", "/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=44bf834f2110504a793dadec132a5898", "/css/dist/all.css": "/css/dist/all.css?id=ef030b613d45620b907cf0184a14e868", "/css/blue.png": "/css/blue.png?id=e83a6c29e04fe851f2122815b2e4b150", @@ -49,5 +49,5 @@ "/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=713b1205aa2d7c9db282f8cd5754c0e4", "/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=6f0563e726c2fe4fab4026daaa5bfdf2", "/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=f343f659ca1d45534d2c2c3cc30fb619", - "/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=8e538625ebd4b8096e150d1aa483547b" + "/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=da6c7997d9de2f8329142399f0ce50da" } diff --git a/resources/assets/less/skins/skin-contrast.less b/resources/assets/less/skins/skin-contrast.less index f66e76676b..eba7001b0b 100644 --- a/resources/assets/less/skins/skin-contrast.less +++ b/resources/assets/less/skins/skin-contrast.less @@ -84,7 +84,13 @@ color: #fff; } } - +a.btn.btn-link.text-left{ + color:@navy; + border: 1px solid #000; +} +a.btn.btn-link.text-left:hover{ + color:@navy; +} a { color: @navy; @@ -102,10 +108,6 @@ a.btn { &:hover { color: #fff; text-decoration: underline; - - } - &:visited { - color: #fff; } } diff --git a/resources/lang/en/general.php b/resources/lang/en/general.php index acc00501ed..43d8b3d9e1 100644 --- a/resources/lang/en/general.php +++ b/resources/lang/en/general.php @@ -3,6 +3,7 @@ return [ 'accessories' => 'Accessories', 'activated' => 'Activated', + 'accepted_date' => 'Date Accepted', 'accessory' => 'Accessory', 'accessory_report' => 'Accessory Report', 'action' => 'Action', @@ -27,7 +28,9 @@ return [ 'audit' => 'Audit', 'audit_report' => 'Audit Log', 'assets' => 'Assets', + 'assigned_date' => 'Date Assigned', 'assigned_to' => 'Assigned to :name', + 'assignee' => 'Assigned to', 'avatar_delete' => 'Delete Avatar', 'avatar_upload' => 'Upload Avatar', 'back' => 'Back', diff --git a/resources/views/accessories/edit.blade.php b/resources/views/accessories/edit.blade.php old mode 100755 new mode 100644 index c16e57cb22..532336182b --- a/resources/views/accessories/edit.blade.php +++ b/resources/views/accessories/edit.blade.php @@ -24,17 +24,20 @@ @include ('partials.forms.edit.notes') -@if ($item->image) -
- -
-