mirror of
https://github.com/snipe/snipe-it.git
synced 2025-03-05 20:52:15 -08:00
Merge branch 'develop' into bug/sc-24884
This commit is contained in:
commit
013463aafc
|
@ -86,6 +86,7 @@ COOKIE_DOMAIN=null
|
|||
SECURE_COOKIES=false
|
||||
API_TOKEN_EXPIRATION_YEARS=15
|
||||
BS_TABLE_STORAGE=cookieStorage
|
||||
BS_TABLE_DEEPLINK=true
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SECURITY HEADER SETTINGS
|
||||
|
|
|
@ -592,6 +592,11 @@ class AssetsController extends Controller
|
|||
}
|
||||
}
|
||||
}
|
||||
if ($field->element == 'checkbox') {
|
||||
if(is_array($field_val)) {
|
||||
$field_val = implode(',', $field_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$asset->{$field->db_column} = $field_val;
|
||||
|
@ -614,7 +619,7 @@ class AssetsController extends Controller
|
|||
$asset->image = $asset->getImageUrl();
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.create.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset), trans('admin/hardware/message.create.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
||||
|
@ -642,26 +647,35 @@ class AssetsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* this is here just legacy reasons. Api\AssetController
|
||||
* used image_source once to allow encoded image uploads.
|
||||
*/
|
||||
* this is here just legacy reasons. Api\AssetController
|
||||
* used image_source once to allow encoded image uploads.
|
||||
*/
|
||||
if ($request->has('image_source')) {
|
||||
$request->offsetSet('image', $request->offsetGet('image_source'));
|
||||
}
|
||||
}
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
$model = $asset->model;
|
||||
|
||||
|
||||
// Update custom fields
|
||||
if (($model) && (isset($model->fieldset))) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
$field_val = $request->input($field->db_column, null);
|
||||
|
||||
if ($request->has($field->db_column)) {
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('admin')) {
|
||||
$asset->{$field->db_column} = Crypt::encrypt($request->input($field->db_column));
|
||||
$asset->{$field->db_column} = Crypt::encrypt($field_val);
|
||||
}
|
||||
} else {
|
||||
$asset->{$field->db_column} = $request->input($field->db_column);
|
||||
}
|
||||
if ($field->element == 'checkbox') {
|
||||
if(is_array($field_val)) {
|
||||
$field_val = implode(',', $field_val);
|
||||
$asset->{$field->db_column} = $field_val;
|
||||
}
|
||||
}
|
||||
else {
|
||||
$asset->{$field->db_column} = $field_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -686,7 +700,7 @@ class AssetsController extends Controller
|
|||
if ($asset->image) {
|
||||
$asset->image = $asset->getImageUrl();
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($asset), trans('admin/hardware/message.update.success')));
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
||||
}
|
||||
|
|
|
@ -45,6 +45,10 @@ class ReportsController extends Controller
|
|||
$actionlogs = $actionlogs->where('action_type', '=', $request->input('action_type'))->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
if ($request->filled('user_id')) {
|
||||
$actionlogs = $actionlogs->where('user_id', '=', $request->input('user_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('action_source')) {
|
||||
$actionlogs = $actionlogs->where('action_source', '=', $request->input('action_source'))->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
|
|
@ -560,7 +560,26 @@ class UsersController extends Controller
|
|||
{
|
||||
$this->authorize('view', User::class);
|
||||
$this->authorize('view', Asset::class);
|
||||
$assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model')->get();
|
||||
$assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model');
|
||||
|
||||
|
||||
// Filter on category ID
|
||||
if ($request->filled('category_id')) {
|
||||
$assets = $assets->InCategory($request->input('category_id'));
|
||||
}
|
||||
|
||||
|
||||
// Filter on model ID
|
||||
if ($request->filled('model_id')) {
|
||||
|
||||
$model_ids = $request->input('model_id');
|
||||
if (!is_array($model_ids)) {
|
||||
$model_ids = array($model_ids);
|
||||
}
|
||||
$assets = $assets->InModelList($model_ids);
|
||||
}
|
||||
|
||||
$assets = $assets->get();
|
||||
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
|
||||
}
|
||||
|
@ -661,7 +680,17 @@ class UsersController extends Controller
|
|||
$user = User::find($request->get('id'));
|
||||
$user->two_factor_secret = null;
|
||||
$user->two_factor_enrolled = 0;
|
||||
$user->save();
|
||||
$user->saveQuietly();
|
||||
|
||||
// Log the reset
|
||||
$logaction = new Actionlog();
|
||||
$logaction->target_type = User::class;
|
||||
$logaction->target_id = $user->id;
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->item_id = $user->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->user_id = Auth::user()->id;
|
||||
$logaction->logaction('2FA reset');
|
||||
|
||||
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_success')], 200);
|
||||
} catch (\Exception $e) {
|
||||
|
|
|
@ -7,6 +7,7 @@ use App\Http\Requests\ImageUploadRequest;
|
|||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
@ -486,11 +487,11 @@ class AssetModelsController extends Controller
|
|||
* @param array $defaultValues
|
||||
* @return void
|
||||
*/
|
||||
private function assignCustomFieldsDefaultValues(AssetModel $model, array $defaultValues)
|
||||
private function assignCustomFieldsDefaultValues(AssetModel $model, array $defaultValues): bool
|
||||
{
|
||||
$data = array();
|
||||
foreach ($defaultValues as $customFieldId => $defaultValue) {
|
||||
$customField = \App\Models\CustomField::find($customFieldId);
|
||||
$customField = CustomField::find($customFieldId);
|
||||
|
||||
$data[$customField->db_column] = $defaultValue;
|
||||
}
|
||||
|
|
|
@ -102,6 +102,10 @@ class AssetsController extends Controller
|
|||
{
|
||||
$this->authorize(Asset::class);
|
||||
|
||||
// There are a lot more rules to add here but prevents
|
||||
// errors around `asset_tags` not being present below.
|
||||
$this->validate($request, ['asset_tags' => ['required', 'array']]);
|
||||
|
||||
// Handle asset tags - there could be one, or potentially many.
|
||||
// This is only necessary on create, not update, since bulk editing is handled
|
||||
// differently
|
||||
|
|
|
@ -260,7 +260,7 @@ class CustomFieldsController extends Controller
|
|||
|
||||
$field->name = trim(e($request->get("name")));
|
||||
$field->element = e($request->get("element"));
|
||||
$field->field_values = e($request->get("field_values"));
|
||||
$field->field_values = $request->get("field_values");
|
||||
$field->user_id = Auth::id();
|
||||
$field->help_text = $request->get("help_text");
|
||||
$field->show_in_email = $show_in_email;
|
||||
|
|
|
@ -20,6 +20,7 @@ use DB;
|
|||
use enshrined\svgSanitize\Sanitizer;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Image;
|
||||
use Input;
|
||||
use Redirect;
|
||||
|
@ -499,6 +500,19 @@ class SettingsController extends Controller
|
|||
*/
|
||||
public function postSecurity(Request $request)
|
||||
{
|
||||
$this->validate($request, [
|
||||
'pwd_secure_complexity' => 'array',
|
||||
'pwd_secure_complexity.*' => [
|
||||
Rule::in([
|
||||
'disallow_same_pwd_as_user_fields',
|
||||
'letters',
|
||||
'numbers',
|
||||
'symbols',
|
||||
'case_diff',
|
||||
])
|
||||
]
|
||||
]);
|
||||
|
||||
if (is_null($setting = Setting::getSettings())) {
|
||||
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
|
||||
}
|
||||
|
|
|
@ -4,6 +4,8 @@ namespace App\Http\Requests;
|
|||
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use Carbon\Carbon;
|
||||
use Carbon\Exceptions\InvalidFormatException;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
class StoreAssetRequest extends ImageUploadRequest
|
||||
|
@ -27,6 +29,8 @@ class StoreAssetRequest extends ImageUploadRequest
|
|||
? Company::getIdForCurrentUser($this->company_id)
|
||||
: $this->company_id;
|
||||
|
||||
$this->parseLastAuditDate();
|
||||
|
||||
$this->merge([
|
||||
'asset_tag' => $this->asset_tag ?? Asset::autoincrement_asset(),
|
||||
'company_id' => $idForCurrentUser,
|
||||
|
@ -48,4 +52,21 @@ class StoreAssetRequest extends ImageUploadRequest
|
|||
|
||||
return $rules;
|
||||
}
|
||||
|
||||
private function parseLastAuditDate(): void
|
||||
{
|
||||
if ($this->input('last_audit_date')) {
|
||||
try {
|
||||
$lastAuditDate = Carbon::parse($this->input('last_audit_date'));
|
||||
|
||||
$this->merge([
|
||||
'last_audit_date' => $lastAuditDate->startOfDay()->format('Y-m-d H:i:s'),
|
||||
]);
|
||||
} catch (InvalidFormatException $e) {
|
||||
// we don't need to do anything here...
|
||||
// we'll keep the provided date in an
|
||||
// invalid format so validation picks it up later
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -90,27 +90,29 @@ class Asset extends Depreciable
|
|||
];
|
||||
|
||||
protected $rules = [
|
||||
'model_id' => 'required|integer|exists:models,id,deleted_at,NULL|not_array',
|
||||
'status_id' => 'required|integer|exists:status_labels,id',
|
||||
'asset_tag' => 'required|min:1|max:255|unique_undeleted:assets,asset_tag|not_array',
|
||||
'name' => 'nullable|max:255',
|
||||
'company_id' => 'nullable|integer|exists:companies,id',
|
||||
'warranty_months' => 'nullable|numeric|digits_between:0,240',
|
||||
'last_checkout' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'model_id' => 'required|integer|exists:models,id,deleted_at,NULL|not_array',
|
||||
'status_id' => 'required|integer|exists:status_labels,id',
|
||||
'asset_tag' => 'required|min:1|max:255|unique_undeleted:assets,asset_tag|not_array',
|
||||
'name' => 'nullable|max:255',
|
||||
'company_id' => 'nullable|integer|exists:companies,id',
|
||||
'warranty_months' => 'nullable|numeric|digits_between:0,240',
|
||||
'last_checkout' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'expected_checkin' => 'nullable|date',
|
||||
'location_id' => 'nullable|exists:locations,id',
|
||||
'rtd_location_id' => 'nullable|exists:locations,id',
|
||||
'purchase_date' => 'nullable|date|date_format:Y-m-d',
|
||||
'serial' => 'nullable|unique_undeleted:assets,serial',
|
||||
'purchase_cost' => 'nullable|numeric|gte:0',
|
||||
'supplier_id' => 'nullable|exists:suppliers,id',
|
||||
'asset_eol_date' => 'nullable|date',
|
||||
'eol_explicit' => 'nullable|boolean',
|
||||
'byod' => 'nullable|boolean',
|
||||
'order_number' => 'nullable|string|max:191',
|
||||
'notes' => 'nullable|string|max:65535',
|
||||
'assigned_to' => 'nullable|integer',
|
||||
'requestable' => 'nullable|boolean',
|
||||
'last_audit_date' => 'nullable|date_format:Y-m-d H:i:s',
|
||||
'next_audit_date' => 'nullable|date|after:last_audit_date',
|
||||
'location_id' => 'nullable|exists:locations,id',
|
||||
'rtd_location_id' => 'nullable|exists:locations,id',
|
||||
'purchase_date' => 'nullable|date|date_format:Y-m-d',
|
||||
'serial' => 'nullable|unique_undeleted:assets,serial',
|
||||
'purchase_cost' => 'nullable|numeric|gte:0',
|
||||
'supplier_id' => 'nullable|exists:suppliers,id',
|
||||
'asset_eol_date' => 'nullable|date',
|
||||
'eol_explicit' => 'nullable|boolean',
|
||||
'byod' => 'nullable|boolean',
|
||||
'order_number' => 'nullable|string|max:191',
|
||||
'notes' => 'nullable|string|max:65535',
|
||||
'assigned_to' => 'nullable|integer',
|
||||
'requestable' => 'nullable|boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
|
|
|
@ -5,6 +5,8 @@ namespace App\Models;
|
|||
use Gate;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
class CustomFieldset extends Model
|
||||
|
@ -92,8 +94,19 @@ class CustomFieldset extends Model
|
|||
|
||||
array_push($rule, $field->attributes['format']);
|
||||
$rules[$field->db_column_name()] = $rule;
|
||||
//add not_array to rules for all fields
|
||||
$rules[$field->db_column_name()][] = 'not_array';
|
||||
|
||||
// add not_array to rules for all fields but checkboxes
|
||||
if ($field->element != 'checkbox') {
|
||||
$rules[$field->db_column_name()][] = 'not_array';
|
||||
}
|
||||
|
||||
if ($field->element == 'checkbox') {
|
||||
$rules[$field->db_column_name()][] = 'checkboxes';
|
||||
}
|
||||
|
||||
if ($field->element == 'radio') {
|
||||
$rules[$field->db_column_name()][] = 'radio_buttons';
|
||||
}
|
||||
}
|
||||
|
||||
return $rules;
|
||||
|
|
89
app/Models/Labels/Tapes/Dymo/LabelWriter_1933081.php
Normal file
89
app/Models/Labels/Tapes/Dymo/LabelWriter_1933081.php
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Labels\Tapes\Dymo;
|
||||
|
||||
|
||||
class LabelWriter_1933081 extends LabelWriter
|
||||
{
|
||||
private const BARCODE_MARGIN = 1.80;
|
||||
private const TAG_SIZE = 2.80;
|
||||
private const TITLE_SIZE = 2.80;
|
||||
private const TITLE_MARGIN = 0.50;
|
||||
private const LABEL_SIZE = 2.80;
|
||||
private const LABEL_MARGIN = - 0.35;
|
||||
private const FIELD_SIZE = 2.80;
|
||||
private const FIELD_MARGIN = 0.15;
|
||||
|
||||
public function getUnit() { return 'mm'; }
|
||||
public function getWidth() { return 89; }
|
||||
public function getHeight() { return 25; }
|
||||
public function getSupportAssetTag() { return true; }
|
||||
public function getSupport1DBarcode() { return true; }
|
||||
public function getSupport2DBarcode() { return true; }
|
||||
public function getSupportFields() { return 5; }
|
||||
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;
|
||||
|
||||
$barcodeSize = $pa->h - self::TAG_SIZE;
|
||||
|
||||
if ($record->has('barcode2d')) {
|
||||
static::writeText(
|
||||
$pdf, $record->get('tag'),
|
||||
$pa->x1, $pa->y2 - self::TAG_SIZE,
|
||||
'freesans', '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,
|
||||
'freesans', 'b', self::TAG_SIZE, 'R',
|
||||
$usableWidth, self::TAG_SIZE, true, 0
|
||||
);
|
||||
}
|
||||
|
||||
if ($record->has('title')) {
|
||||
static::writeText(
|
||||
$pdf, $record->get('title'),
|
||||
$currentX, $currentY,
|
||||
'freesans', 'b', self::TITLE_SIZE, 'L',
|
||||
$usableWidth, self::TITLE_SIZE, true, 0
|
||||
);
|
||||
$currentY += self::TITLE_SIZE + self::TITLE_MARGIN;
|
||||
}
|
||||
|
||||
foreach ($record->get('fields') as $field) {
|
||||
static::writeText(
|
||||
$pdf, (($field['label']) ? $field['label'].' ' : '') . $field['value'],
|
||||
$currentX, $currentY,
|
||||
'freesans', '', self::FIELD_SIZE, 'L',
|
||||
$usableWidth, self::FIELD_SIZE, true, 0, 0.3
|
||||
);
|
||||
$currentY += self::FIELD_SIZE + self::FIELD_MARGIN;
|
||||
}
|
||||
|
||||
if ($record->has('barcode1d')) {
|
||||
static::write1DBarcode(
|
||||
$pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type,
|
||||
$currentX, $barcodeSize + self::BARCODE_MARGIN, $usableWidth - self::TAG_SIZE, self::TAG_SIZE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
89
app/Models/Labels/Tapes/Dymo/LabelWriter_2112283.php
Normal file
89
app/Models/Labels/Tapes/Dymo/LabelWriter_2112283.php
Normal file
|
@ -0,0 +1,89 @@
|
|||
<?php
|
||||
|
||||
namespace App\Models\Labels\Tapes\Dymo;
|
||||
|
||||
|
||||
class LabelWriter_2112283 extends LabelWriter
|
||||
{
|
||||
private const BARCODE_MARGIN = 1.80;
|
||||
private const TAG_SIZE = 2.80;
|
||||
private const TITLE_SIZE = 2.80;
|
||||
private const TITLE_MARGIN = 0.50;
|
||||
private const LABEL_SIZE = 2.80;
|
||||
private const LABEL_MARGIN = - 0.35;
|
||||
private const FIELD_SIZE = 2.80;
|
||||
private const FIELD_MARGIN = 0.15;
|
||||
|
||||
public function getUnit() { return 'mm'; }
|
||||
public function getWidth() { return 54; }
|
||||
public function getHeight() { return 25; }
|
||||
public function getSupportAssetTag() { return true; }
|
||||
public function getSupport1DBarcode() { return true; }
|
||||
public function getSupport2DBarcode() { return true; }
|
||||
public function getSupportFields() { return 5; }
|
||||
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;
|
||||
|
||||
$barcodeSize = $pa->h - self::TAG_SIZE;
|
||||
|
||||
if ($record->has('barcode2d')) {
|
||||
static::writeText(
|
||||
$pdf, $record->get('tag'),
|
||||
$pa->x1, $pa->y2 - self::TAG_SIZE,
|
||||
'freesans', '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,
|
||||
'freesans', 'b', self::TAG_SIZE, 'R',
|
||||
$usableWidth, self::TAG_SIZE, true, 0
|
||||
);
|
||||
}
|
||||
|
||||
if ($record->has('title')) {
|
||||
static::writeText(
|
||||
$pdf, $record->get('title'),
|
||||
$currentX, $currentY,
|
||||
'freesans', 'b', self::TITLE_SIZE, 'L',
|
||||
$usableWidth, self::TITLE_SIZE, true, 0
|
||||
);
|
||||
$currentY += self::TITLE_SIZE + self::TITLE_MARGIN;
|
||||
}
|
||||
|
||||
foreach ($record->get('fields') as $field) {
|
||||
static::writeText(
|
||||
$pdf, (($field['label']) ? $field['label'].' ' : '') . $field['value'],
|
||||
$currentX, $currentY,
|
||||
'freesans', '', self::FIELD_SIZE, 'L',
|
||||
$usableWidth, self::FIELD_SIZE, true, 0, 0.3
|
||||
);
|
||||
$currentY += self::FIELD_SIZE + self::FIELD_MARGIN;
|
||||
}
|
||||
|
||||
if ($record->has('barcode1d')) {
|
||||
static::write1DBarcode(
|
||||
$pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type,
|
||||
$currentX, $barcodeSize + self::BARCODE_MARGIN, $usableWidth - self::TAG_SIZE, self::TAG_SIZE
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
|
@ -41,6 +41,7 @@ class AccessoryPresenter extends Presenter
|
|||
'field' => 'name',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.name'),
|
||||
'formatter' => 'accessoriesLinkFormatter',
|
||||
], [
|
||||
|
|
|
@ -38,10 +38,14 @@ class ActionlogPresenter extends Presenter
|
|||
|
||||
public function icon()
|
||||
{
|
||||
|
||||
|
||||
// User related icons
|
||||
if ($this->itemType() == 'user') {
|
||||
|
||||
if ($this->actionType()=='2fa reset') {
|
||||
return 'fa-solid fa-mobile-screen';
|
||||
}
|
||||
|
||||
if ($this->actionType()=='create new') {
|
||||
return 'fa-solid fa-user-plus';
|
||||
}
|
||||
|
@ -61,6 +65,7 @@ class ActionlogPresenter extends Presenter
|
|||
if ($this->actionType()=='update') {
|
||||
return 'fa-solid fa-user-pen';
|
||||
}
|
||||
|
||||
return 'fa-solid fa-user';
|
||||
}
|
||||
|
||||
|
|
|
@ -85,6 +85,7 @@ class AssetMaintenancesPresenter extends Presenter
|
|||
'field' => 'title',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('admin/asset_maintenances/form.title'),
|
||||
], [
|
||||
'field' => 'start_date',
|
||||
|
|
|
@ -35,6 +35,7 @@ class AssetModelPresenter extends Presenter
|
|||
'field' => 'name',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'visible' => true,
|
||||
'title' => trans('general.name'),
|
||||
'formatter' => 'modelsLinkFormatter',
|
||||
|
|
|
@ -55,6 +55,7 @@ class AssetPresenter extends Presenter
|
|||
'field' => 'asset_tag',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('admin/hardware/table.asset_tag'),
|
||||
'visible' => true,
|
||||
'formatter' => 'hardwareLinkFormatter',
|
||||
|
@ -316,7 +317,7 @@ class AssetPresenter extends Presenter
|
|||
'field' => 'checkincheckout',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.checkin').'/'.trans('general.checkout'),
|
||||
'visible' => true,
|
||||
'formatter' => 'hardwareInOutFormatter',
|
||||
|
|
|
@ -25,6 +25,7 @@ class CategoryPresenter extends Presenter
|
|||
'field' => 'name',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.name'),
|
||||
'visible' => true,
|
||||
'formatter' => 'categoriesLinkFormatter',
|
||||
|
|
|
@ -25,7 +25,7 @@ class CompanyPresenter extends Presenter
|
|||
'field' => 'name',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('admin/companies/table.name'),
|
||||
'visible' => true,
|
||||
'formatter' => 'companiesLinkFormatter',
|
||||
|
|
|
@ -126,7 +126,7 @@ class ComponentPresenter extends Presenter
|
|||
'field' => 'checkincheckout',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.checkin').'/'.trans('general.checkout'),
|
||||
'visible' => true,
|
||||
'formatter' => 'componentsInOutFormatter',
|
||||
|
|
|
@ -35,6 +35,7 @@ class ConsumablePresenter extends Presenter
|
|||
'field' => 'name',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.name'),
|
||||
'visible' => true,
|
||||
'formatter' => 'consumablesLinkFormatter',
|
||||
|
|
|
@ -25,6 +25,7 @@ class DepreciationPresenter extends Presenter
|
|||
'field' => 'name',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.name'),
|
||||
'visible' => true,
|
||||
'formatter' => 'depreciationsLinkFormatter',
|
||||
|
|
|
@ -34,6 +34,7 @@ class DepreciationReportPresenter extends Presenter
|
|||
"field" => "name",
|
||||
"searchable" => true,
|
||||
"sortable" => true,
|
||||
'switchable' => false,
|
||||
"title" => trans('admin/hardware/form.name'),
|
||||
"visible" => false,
|
||||
], [
|
||||
|
|
|
@ -33,6 +33,7 @@ class LicensePresenter extends Presenter
|
|||
'field' => 'name',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.name'),
|
||||
'formatter' => 'licensesLinkFormatter',
|
||||
], [
|
||||
|
@ -186,7 +187,7 @@ class LicensePresenter extends Presenter
|
|||
'field' => 'checkincheckout',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.checkin').'/'.trans('general.checkout'),
|
||||
'visible' => true,
|
||||
'formatter' => 'licensesInOutFormatter',
|
||||
|
@ -280,7 +281,7 @@ class LicensePresenter extends Presenter
|
|||
'field' => 'checkincheckout',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('general.checkin').'/'.trans('general.checkout'),
|
||||
'visible' => true,
|
||||
'formatter' => 'licenseSeatInOutFormatter',
|
||||
|
|
|
@ -31,6 +31,7 @@ class LocationPresenter extends Presenter
|
|||
'field' => 'name',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('admin/locations/table.name'),
|
||||
'visible' => true,
|
||||
'formatter' => 'locationsLinkFormatter',
|
||||
|
|
|
@ -27,6 +27,7 @@ class ManufacturerPresenter extends Presenter
|
|||
'field' => 'name',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('admin/manufacturers/table.name'),
|
||||
'visible' => true,
|
||||
'formatter' => 'manufacturersLinkFormatter',
|
||||
|
|
|
@ -38,7 +38,7 @@ class UserPresenter extends Presenter
|
|||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => 'Avatar',
|
||||
'title' => trans('general.importer.avatar'),
|
||||
'visible' => false,
|
||||
'formatter' => 'imageFormatter',
|
||||
],
|
||||
|
@ -175,7 +175,7 @@ class UserPresenter extends Presenter
|
|||
'field' => 'username',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('admin/users/table.username'),
|
||||
'visible' => true,
|
||||
'formatter' => 'usersLinkFormatter',
|
||||
|
|
|
@ -2,9 +2,12 @@
|
|||
|
||||
namespace App\Providers;
|
||||
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Department;
|
||||
use App\Models\Setting;
|
||||
use DB;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Validator;
|
||||
|
@ -293,6 +296,39 @@ class ValidationServiceProvider extends ServiceProvider
|
|||
Validator::extend('not_array', function ($attribute, $value, $parameters, $validator) {
|
||||
return !is_array($value);
|
||||
});
|
||||
|
||||
// This is only used in Models/CustomFieldset.php - it does automatic validation for checkboxes by making sure
|
||||
// that the submitted values actually exist in the options.
|
||||
Validator::extend('checkboxes', function ($attribute, $value, $parameters, $validator){
|
||||
$field = CustomField::where('db_column', $attribute)->first();
|
||||
$options = $field->formatFieldValuesAsArray();
|
||||
|
||||
if(is_array($value)) {
|
||||
$invalid = array_diff($value, $options);
|
||||
if(count($invalid) > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
// for legacy, allows users to submit a comma separated string of options
|
||||
elseif(!is_array($value)) {
|
||||
$exploded = array_map('trim', explode(',', $value));
|
||||
$invalid = array_diff($exploded, $options);
|
||||
if(count($invalid) > 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
});
|
||||
|
||||
// Validates that a radio button option exists
|
||||
Validator::extend('radio_buttons', function ($attribute, $value) {
|
||||
$field = CustomField::where('db_column', $attribute)->first();
|
||||
$options = $field->formatFieldValuesAsArray();
|
||||
|
||||
return in_array($value, $options);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
|
|
|
@ -174,4 +174,17 @@ return [
|
|||
|
||||
'bs_table_storage' => env('BS_TABLE_STORAGE', 'cookieStorage'),
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Bootstrap Table Enable Deeplinking
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Use deeplinks to directly link to search results, sorting, and pagination
|
||||
|
|
||||
| More info: https://github.com/generals-space/bootstrap-table-addrbar/blob/master/readme(EN).md
|
||||
*/
|
||||
|
||||
'bs_table_addrbar' => env('BS_TABLE_DEEPLINK', true),
|
||||
|
||||
];
|
||||
|
|
|
@ -1,10 +1,10 @@
|
|||
<?php
|
||||
return array (
|
||||
'app_version' => 'v6.3.3',
|
||||
'full_app_version' => 'v6.3.3 - build 12903-g0f63fa23e',
|
||||
'build_version' => '12903',
|
||||
'full_app_version' => 'v6.3.3 - build 13056-gb34156ca2',
|
||||
'build_version' => '13056',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => 'g0f63fa23e',
|
||||
'full_hash' => 'v6.3.3-67-g0f63fa23e',
|
||||
'hash_version' => 'gb34156ca2',
|
||||
'full_hash' => 'v6.3.3-151-gb34156ca2',
|
||||
'branch' => 'develop',
|
||||
);
|
6
package-lock.json
generated
6
package-lock.json
generated
|
@ -2379,9 +2379,9 @@
|
|||
}
|
||||
},
|
||||
"alpinejs": {
|
||||
"version": "3.13.5",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.5.tgz",
|
||||
"integrity": "sha512-1d2XeNGN+Zn7j4mUAKXtAgdc4/rLeadyTMWeJGXF5DzwawPBxwTiBhFFm6w/Ei8eJxUZeyNWWSD9zknfdz1kEw==",
|
||||
"version": "3.13.7",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.7.tgz",
|
||||
"integrity": "sha512-rcTyjTANbsePq1hb7eSekt3qjI94HLGeO6JaRjCssCVbIIc+qBrc7pO5S/+2JB6oojIibjM6FA+xRI3zhGPZIg==",
|
||||
"requires": {
|
||||
"@vue/reactivity": "~3.1.1"
|
||||
}
|
||||
|
|
|
@ -33,7 +33,7 @@
|
|||
"acorn-import-assertions": "^1.9.0",
|
||||
"admin-lte": "^2.4.18",
|
||||
"ajv": "^6.12.6",
|
||||
"alpinejs": "^3.13.5",
|
||||
"alpinejs": "^3.13.6",
|
||||
"blueimp-file-upload": "^9.34.0",
|
||||
"bootstrap": "^3.4.1",
|
||||
"bootstrap-colorpicker": "^2.5.3",
|
||||
|
|
BIN
public/js/dist/all-defer.js
vendored
BIN
public/js/dist/all-defer.js
vendored
Binary file not shown.
BIN
public/js/dist/bootstrap-table.js
vendored
BIN
public/js/dist/bootstrap-table.js
vendored
Binary file not shown.
|
@ -31,9 +31,9 @@
|
|||
"/css/webfonts/fa-v4compatibility.woff2": "/css/webfonts/fa-v4compatibility.woff2?id=e11465c0eff0549edd4e8ea6bbcf242f",
|
||||
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=99c395f0bab5966f32f63f4e55899e64",
|
||||
"/js/build/vendor.js": "/js/build/vendor.js?id=a2b971da417306a63385c8098acfe4af",
|
||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=d0eb38da8b772a21b827b7df208dc4fe",
|
||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=857da5daffd13e0553510e5ccd410c79",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=13bdb521e0c745d7f81dae3fb110b650",
|
||||
"/js/dist/all-defer.js": "/js/dist/all-defer.js?id=19ccc62a8f1ea103dede4808837384d4",
|
||||
"/js/dist/all-defer.js": "/js/dist/all-defer.js?id=18d36546bdad8285c229008df799b343",
|
||||
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
|
||||
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=d419cb63a12dc175d71645c876bfc2ab",
|
||||
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=76482123f6c70e866d6b971ba91de7bb",
|
||||
|
|
|
@ -261,7 +261,7 @@ return [
|
|||
'two_factor_enrollment' => 'Two-Factor Enrollment',
|
||||
'two_factor_enabled_text' => 'Enable Two Factor',
|
||||
'two_factor_reset' => 'Reset Two-Factor Secret',
|
||||
'two_factor_reset_help' => 'This will force the user to enroll their device with Google Authenticator again. This can be useful if their currently enrolled device is lost or stolen. ',
|
||||
'two_factor_reset_help' => 'This will force the user to enroll their device with their authenticator app again. This can be useful if their currently enrolled device is lost or stolen. ',
|
||||
'two_factor_reset_success' => 'Two factor device successfully reset',
|
||||
'two_factor_reset_error' => 'Two factor device reset failed',
|
||||
'two_factor_enabled_warning' => 'Enabling two-factor if it is not currently enabled will immediately force you to authenticate with a Google Auth enrolled device. You will have the ability to enroll your device if one is not currently enrolled.',
|
||||
|
|
|
@ -1,6 +1,7 @@
|
|||
<?php
|
||||
|
||||
return [
|
||||
'2FA_reset' => '2FA reset',
|
||||
'accessories' => 'Accessories',
|
||||
'activated' => 'Activated',
|
||||
'accepted_date' => 'Date Accepted',
|
||||
|
|
|
@ -105,6 +105,8 @@ return [
|
|||
'gte' => [
|
||||
'numeric' => 'Value cannot be negative'
|
||||
],
|
||||
'checkboxes' => ':attribute contains invalid options.',
|
||||
'radio_buttons' => ':attribute is invalid.',
|
||||
|
||||
|
||||
/*
|
||||
|
@ -151,4 +153,10 @@ return [
|
|||
|
||||
'attributes' => [],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Generic Validation Messages
|
||||
|--------------------------------------------------------------------------
|
||||
*/
|
||||
'invalid_value_in_field' => 'Invalid value included in this field',
|
||||
];
|
||||
|
|
|
@ -135,7 +135,7 @@
|
|||
|
||||
@if (!$field->id)
|
||||
<!-- Encrypted -->
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<div class="col-md-9 col-md-offset-3" id="encryption_section">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" value="1" name="field_encrypted" id="field_encrypted"{{ (Request::old('field_encrypted') || $field->field_encrypted) ? ' checked="checked"' : '' }}>
|
||||
{{ trans('admin/custom_fields/general.encrypt_field') }}
|
||||
|
@ -146,7 +146,6 @@
|
|||
<p><i class="fas fa-exclamation-triangle" aria-hidden="true"></i> {{ trans('admin/custom_fields/general.encrypt_field_help') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
|
||||
|
@ -298,11 +297,16 @@
|
|||
}).change();
|
||||
|
||||
// Only display the field element if the type is not text
|
||||
// and don't display encryption option for checkbox or radio
|
||||
$(".field_element").change(function(){
|
||||
$(this).find("option:selected").each(function(){
|
||||
if (($(this).attr("value")!="text") && ($(this).attr("value")!="textarea")){
|
||||
$("#field_values_text").show();
|
||||
if ($(this).attr("value") == "checkbox" || $(this).attr("value") == "radio") {
|
||||
$("#encryption_section").hide();
|
||||
}
|
||||
} else{
|
||||
$("#encryption_section").show();
|
||||
$("#field_values_text").hide();
|
||||
}
|
||||
});
|
||||
|
|
|
@ -904,27 +904,18 @@
|
|||
@endcan
|
||||
|
||||
@can('delete', $asset)
|
||||
@if ($asset->deleted_at=='')
|
||||
<div class="col-md-12" style="padding-top: 30px; padding-bottom: 30px;">
|
||||
<button class="btn btn-block btn-danger delete-asset" data-toggle="modal" data-title="{{ trans('general.delete') }}" data-content="{{ trans('general.sure_to_delete', ['item' => $asset->asset_tag]) }}" data-target="#dataConfirmModal">{{ trans('general.delete') }} </button>
|
||||
<div class="col-md-12" style="padding-top: 30px; padding-bottom: 30px;">
|
||||
@if ($asset->deleted_at=='')
|
||||
<button class="btn btn-sm btn-block btn-danger delete-asset" data-toggle="modal" data-title="{{ trans('general.delete') }}" data-content="{{ trans('general.sure_to_delete_var', ['item' => $asset->asset_tag]) }}" data-target="#dataConfirmModal">{{ trans('general.delete') }} </button>
|
||||
<span class="sr-only">{{ trans('general.delete') }}</span>
|
||||
</div>
|
||||
@endif
|
||||
@else
|
||||
<form method="POST" action="{{ route('restore/hardware', ['assetId' => $asset->id]) }}">
|
||||
@csrf
|
||||
<button class="btn btn-sm btn-warning col-md-12">{{ trans('general.restore') }}</button>
|
||||
</form>
|
||||
@endif
|
||||
@endcan
|
||||
|
||||
@if ($asset->deleted_at!='')
|
||||
<div class="text-center col-md-12" style="padding-top: 30px; padding-bottom: 30px;">
|
||||
<form method="POST" action="{{ route('restore/hardware', ['assetId' => $asset->id]) }}">
|
||||
@csrf
|
||||
<button class="btn btn-danger col-md-12">{{ trans('general.restore') }}</button>
|
||||
</form>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@if ($snipeSettings->qr_code=='1')
|
||||
<img src="{{ config('app.url') }}/hardware/{{ $asset->id }}/qr_code" class="img-thumbnail pull-right" style="height: 100px; width: 100px; margin-right: 10px;" alt="QR code for {{ $asset->getDisplayNameAttribute() }}">
|
||||
@endif
|
||||
|
||||
@if (($asset->assignedTo) && ($asset->deleted_at==''))
|
||||
<div style="text-align: left">
|
||||
<h2>{{ trans('admin/hardware/form.checkedout_to') }}</h2>
|
||||
|
@ -982,9 +973,17 @@
|
|||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
@if ($snipeSettings->qr_code=='1')
|
||||
<div class="col-md-12" style="padding-top: 15px;">
|
||||
<img src="{{ config('app.url') }}/hardware/{{ $asset->id }}/qr_code" class="img-thumbnail pull-right" style="height: 100px; width: 100px; margin-right: 10px;" alt="QR code for {{ $asset->getDisplayNameAttribute() }}">
|
||||
</div>
|
||||
@endif
|
||||
|
||||
</div> <!-- div.col-md-4 -->
|
||||
</div><!-- /row -->
|
||||
</div><!-- /.tab-pane asset details -->
|
||||
</div>
|
||||
|
||||
<div class="tab-pane fade" id="software">
|
||||
<div class="row">
|
||||
|
|
|
@ -174,23 +174,56 @@
|
|||
@endif
|
||||
|
||||
|
||||
@if ($license->supplier_id)
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<strong>
|
||||
{{ trans('general.supplier') }}
|
||||
</strong>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
@if ($license->supplier)
|
||||
<a href="{{ route('suppliers.show', $license->supplier_id) }}">
|
||||
@if ($license->supplier)
|
||||
<div class="row">
|
||||
<div class="col-md-3">
|
||||
<strong>{{ trans('general.supplier') }}</strong>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
@can('view', \App\Models\Supplier::class)
|
||||
<a href="{{ route('suppliers.show', $license->supplier->id) }}">
|
||||
{{ $license->supplier->name }}
|
||||
</a>
|
||||
@else
|
||||
{{ $license->supplier->name }}
|
||||
</a>
|
||||
@else
|
||||
{{ trans('general.deleted') }}
|
||||
@endif
|
||||
@endcan
|
||||
|
||||
@if ($license->supplier->url)
|
||||
<br><i class="fas fa-globe-americas" aria-hidden="true"></i> <a href="{{ $license->supplier->url }}" rel="noopener">{{ $license->supplier->url }}</a>
|
||||
@endif
|
||||
|
||||
@if ($license->supplier->phone)
|
||||
<br><i class="fas fa-phone" aria-hidden="true"></i>
|
||||
<a href="tel:{{ $license->supplier->phone }}">{{ $license->supplier->phone }}</a>
|
||||
@endif
|
||||
|
||||
@if ($license->supplier->email)
|
||||
<br><i class="far fa-envelope" aria-hidden="true"></i> <a href="mailto:{{ $license->supplier->email }}">{{ $license->supplier->email }}</a>
|
||||
@endif
|
||||
|
||||
@if ($license->supplier->address)
|
||||
<br>{{ $license->supplier->address }}
|
||||
@endif
|
||||
@if ($license->supplier->address2)
|
||||
<br>{{ $license->supplier->address2 }}
|
||||
@endif
|
||||
@if ($license->supplier->city)
|
||||
<br>{{ $license->supplier->city }},
|
||||
@endif
|
||||
@if ($license->supplier->state)
|
||||
{{ $license->supplier->state }}
|
||||
@endif
|
||||
@if ($license->supplier->country)
|
||||
{{ $license->supplier->country }}
|
||||
@endif
|
||||
@if ($license->supplier->zip)
|
||||
{{ $license->supplier->zip }}
|
||||
@endif
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
@else
|
||||
{{ trans('general.deleted') }}
|
||||
@endif
|
||||
|
||||
|
||||
|
|
|
@ -9,7 +9,7 @@
|
|||
<!-- Listbox -->
|
||||
@if ($field->element=='listbox')
|
||||
{{ Form::select($field->db_column_name(), $field->formatFieldValuesAsArray(),
|
||||
Request::old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, htmlspecialchars($item->{$field->db_column_name()}, ENT_QUOTES)) : $field->defaultValue($model->id))), ['class'=>'format select2 form-control']) }}
|
||||
Request::old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id))), ['class'=>'format select2 form-control']) }}
|
||||
|
||||
@elseif ($field->element=='textarea')
|
||||
<textarea class="col-md-6 form-control" id="{{ $field->db_column_name() }}" name="{{ $field->db_column_name() }}">{{ Request::old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id))) }}</textarea>
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<!-- Listbox -->
|
||||
@if ($field->element=='listbox')
|
||||
{{ Form::select($field->db_column_name(), $field->formatFieldValuesAsArray(),
|
||||
Request::old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, htmlspecialchars($item->{$field->db_column_name()}, ENT_QUOTES)) : $field->defaultValue($model->id))), ['class'=>'format select2 form-control']) }}
|
||||
Request::old($field->db_column_name(),(isset($item) ? Helper::gracefulDecrypt($field, $item->{$field->db_column_name()}) : $field->defaultValue($model->id))), ['class'=>'format select2 form-control']) }}
|
||||
|
||||
@elseif ($field->element=='textarea')
|
||||
@if($field->is_unique)
|
||||
|
|
|
@ -236,6 +236,12 @@
|
|||
</li>
|
||||
@endif
|
||||
|
||||
@if ($model->created_at)
|
||||
<li>{{ trans('general.created_at') }}:
|
||||
{{ Helper::getFormattedDateObject($model->created_at, 'datetime', false) }}
|
||||
</li>
|
||||
@endif
|
||||
|
||||
@if ($model->min_amt)
|
||||
<li>{{ trans('general.min_amt') }}:
|
||||
{{$model->min_amt }}
|
||||
|
@ -313,11 +319,6 @@
|
|||
</li>
|
||||
@endif
|
||||
|
||||
|
||||
|
||||
@if ($model->deleted_at!='')
|
||||
<li><br /><a href="{{ route('models.restore.store', $model->id) }}" class="btn-flat large info ">{{ trans('admin/models/general.restore') }}</a></li>
|
||||
@endif
|
||||
</ul>
|
||||
|
||||
@if ($model->note)
|
||||
|
@ -337,22 +338,32 @@
|
|||
|
||||
@can('create', \App\Models\AssetModel::class)
|
||||
<div class="col-md-12" style="padding-bottom: 5px;">
|
||||
<a href="{{ route('models.clone.create', $model->id) }}" style="width: 100%;" class="btn btn-sm btn-warning hidden-print">{{ trans('admin/models/table.clone') }}</a>
|
||||
<a href="{{ route('models.clone.create', $model->id) }}" style="width: 100%;" class="btn btn-sm btn-primary hidden-print">{{ trans('admin/models/table.clone') }}</a>
|
||||
</div>
|
||||
@endcan
|
||||
|
||||
@can('delete', \App\Models\AssetModel::class)
|
||||
@if ($model->assets_count > 0)
|
||||
|
||||
<div class="col-md-12" style="padding-bottom: 5px;">
|
||||
<button class="btn btn-block btn-sm btn-danger hidden-print disabled" data-tooltip="true" data-placement="top" data-title="{{ trans('general.cannot_be_deleted') }}">{{ trans('general.delete') }}</button>
|
||||
<button class="btn btn-block btn-sm btn-primary hidden-print disabled" data-tooltip="true" data-placement="top" data-title="{{ trans('general.cannot_be_deleted') }}">{{ trans('general.delete') }}</button>
|
||||
</div>
|
||||
@else
|
||||
<div class="col-md-12" style="padding-bottom: 10px;">
|
||||
<button class="btn btn-block btn-danger delete-asset" data-toggle="modal" title="{{ trans('general.delete_what', ['item'=> trans('general.asset_model')]) }}" data-content="{{ trans('general.sure_to_delete_var', ['item' => $model->name]) }}" data-target="#dataConfirmModal" data-tooltip="true" data-placement="top" data-title="{{ trans('general.delete_what', ['item'=> trans('general.asset_model')]) }}">{{ trans('general.delete') }} </button>
|
||||
<span class="sr-only">{{ trans('general.delete') }}</span>
|
||||
</div>
|
||||
|
||||
@endif
|
||||
|
||||
|
||||
<div class="text-center col-md-12" style="padding-top: 30px; padding-bottom: 30px;">
|
||||
@if ($model->deleted_at!='')
|
||||
<form method="POST" action="{{ route('models.restore.store', $model->id) }}">
|
||||
@csrf
|
||||
<button style="width: 100%;" class="btn btn-sm btn-warning hidden-print">{{ trans('button.restore') }}</button>
|
||||
</form>
|
||||
@else
|
||||
<button class="btn btn-block btn-sm btn-danger delete-asset" data-toggle="modal" title="{{ trans('general.delete_what', ['item'=> trans('general.asset_model')]) }}" data-content="{{ trans('general.sure_to_delete_var', ['item' => $model->name]) }}" data-target="#dataConfirmModal" data-tooltip="true" data-placement="top" data-title="{{ trans('general.delete_what', ['item'=> trans('general.asset_model')]) }}">{{ trans('general.delete') }} </button>
|
||||
<span class="sr-only">{{ trans('general.delete') }}</span>
|
||||
@endif
|
||||
</div>
|
||||
|
||||
@endcan
|
||||
</div>
|
||||
</div> <!-- /.row -->
|
||||
|
|
|
@ -46,16 +46,19 @@
|
|||
stickyHeader: true,
|
||||
stickyHeaderOffsetLeft: parseInt($('body').css('padding-left'), 10),
|
||||
stickyHeaderOffsetRight: parseInt($('body').css('padding-right'), 10),
|
||||
locale: locale,
|
||||
locale: '{{ app()->getLocale() }}',
|
||||
undefinedText: '',
|
||||
iconsPrefix: 'fa',
|
||||
cookieStorage: '{{ config('session.bs_table_storage') }}',
|
||||
cookie: true,
|
||||
cookieExpire: '2y',
|
||||
showColumnsToggleAll: true,
|
||||
minimumCountColumns: 2,
|
||||
mobileResponsive: true,
|
||||
maintainSelected: true,
|
||||
trimOnSearch: false,
|
||||
showSearchClearButton: true,
|
||||
addrbar: {{ (config('session.bs_table_addrbar') == 'true') ? 'true' : 'false'}}, // deeplink search phrases, sorting, etc
|
||||
paginationFirstText: "{{ trans('general.first') }}",
|
||||
paginationLastText: "{{ trans('general.last') }}",
|
||||
paginationPreText: "{{ trans('general.previous') }}",
|
||||
|
@ -85,7 +88,7 @@
|
|||
export: 'fa-download',
|
||||
clearSearch: 'fa-times'
|
||||
},
|
||||
exportOptions: export_options,
|
||||
exportOptions: export_options,
|
||||
exportTypes: ['xlsx', 'excel', 'csv', 'pdf','json', 'xml', 'txt', 'sql', 'doc' ],
|
||||
onLoadSuccess: function () {
|
||||
$('[data-tooltip="true"]').tooltip(); // Needed to attach tooltips after ajax call
|
||||
|
|
|
@ -74,12 +74,11 @@
|
|||
|
||||
|
||||
<!-- Common Passwords -->
|
||||
<div class="form-group">
|
||||
<div class="form-group {{ $errors->has('pwd_secure_complexity.*') ? 'error' : '' }}">
|
||||
<div class="col-md-3">
|
||||
{{ Form::label('pwd_secure_complexity', trans('admin/settings/general.pwd_secure_complexity')) }}
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
|
||||
<label class="form-control">
|
||||
<span class="sr-only">{{ trans('admin/settings/general.pwd_secure_uncommon') }}</span>
|
||||
{{ Form::checkbox('pwd_secure_uncommon', '1', old('pwd_secure_uncommon', $setting->pwd_secure_uncommon),array( 'aria-label'=>'pwd_secure_uncommon')) }}
|
||||
|
@ -106,6 +105,9 @@
|
|||
{{ trans('admin/settings/general.pwd_secure_complexity_case_diff') }}
|
||||
</label>
|
||||
|
||||
@if ($errors->has('pwd_secure_complexity.*'))
|
||||
<span class="alert-msg">{{ trans('validation.invalid_value_in_field') }}</span>
|
||||
@endif
|
||||
<p class="help-block">
|
||||
{{ trans('admin/settings/general.pwd_secure_complexity_help') }}
|
||||
</p>
|
||||
|
|
|
@ -499,18 +499,21 @@
|
|||
</div>
|
||||
@endif
|
||||
|
||||
<!-- Reset Two Factor -->
|
||||
<div class="form-group">
|
||||
<div class="col-md-8 col-md-offset-3 two_factor_resetrow">
|
||||
<a class="btn btn-default btn-sm pull-left" id="two_factor_reset" style="margin-right: 10px;"> {{ trans('admin/settings/general.two_factor_reset') }}</a>
|
||||
<span id="two_factor_reseticon"></span>
|
||||
<span id="two_factor_resetresult"></span>
|
||||
<span id="two_factor_resetstatus"></span>
|
||||
@if ((Auth::user()->isSuperUser()) && ($user->two_factor_active_and_enrolled()) && ($snipeSettings->two_factor_enabled!='0') && ($snipeSettings->two_factor_enabled!=''))
|
||||
<!-- Reset Two Factor -->
|
||||
<div class="form-group">
|
||||
<div class="col-md-8 col-md-offset-3 two_factor_resetrow">
|
||||
<a class="btn btn-default btn-sm pull-left" id="two_factor_reset" style="margin-right: 10px;"> {{ trans('admin/settings/general.two_factor_reset') }}</a>
|
||||
<span id="two_factor_reseticon"></span>
|
||||
<span id="two_factor_resetresult"></span>
|
||||
<span id="two_factor_resetstatus"></span>
|
||||
</div>
|
||||
<div class="col-md-8 col-md-offset-3 two_factor_resetrow">
|
||||
<p class="help-block">{{ trans('admin/settings/general.two_factor_reset_help') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
<div class="col-md-8 col-md-offset-3 two_factor_resetrow">
|
||||
<p class="help-block">{{ trans('admin/settings/general.two_factor_reset_help') }}</p>
|
||||
</div>
|
||||
</div>
|
||||
@endif
|
||||
|
||||
@endif
|
||||
|
||||
<!-- Groups -->
|
||||
|
@ -702,7 +705,7 @@ $(document).ready(function() {
|
|||
$("#two_factor_resetrow").removeClass('success');
|
||||
$("#two_factor_resetrow").removeClass('danger');
|
||||
$("#two_factor_resetstatus").html('');
|
||||
$("#two_factor_reseticon").html('<i class="fas fa-spinner spin"></i>');
|
||||
$("#two_factor_reseticon").html('<i class="fas fa-spinner spin"></i> ');
|
||||
$.ajax({
|
||||
url: '{{ route('api.users.two_factor_reset', ['id'=> $user->id]) }}',
|
||||
type: 'POST',
|
||||
|
@ -715,13 +718,12 @@ $(document).ready(function() {
|
|||
|
||||
success: function (data) {
|
||||
$("#two_factor_reseticon").html('');
|
||||
$("#two_factor_resetstatus").html('<i class="fas fa-check text-success"></i>' + data.message);
|
||||
$("#two_factor_resetstatus").html('<span class="text-success"><i class="fas fa-check"></i> ' + data.message + '</span>');
|
||||
},
|
||||
|
||||
error: function (data) {
|
||||
$("#two_factor_reseticon").html('');
|
||||
$("#two_factor_reseticon").html('<i class="fas fa-exclamation-triangle text-danger"></i>');
|
||||
$('#two_factor_resetstatus').text(data.message);
|
||||
$("#two_factor_resetstatus").html('<span class="text-danger"><i class="fas fa-exclamation-triangle text-danger"></i> ' + data.message + '</span>');
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -110,6 +110,7 @@
|
|||
<th data-field="asset_name" data-sortable="true" data-visible="true">{{ trans('general.name') }}</th>
|
||||
<th data-field="asset_category" data-sortable="true" data-visible="true">{{ trans('general.category') }}</th>
|
||||
<th data-field="asset_model" data-sortable="true" data-visible="true">{{ trans('admin/hardware/form.model') }}</th>
|
||||
<th data-field="rtd_location" data-sortable="true" data-visible="true">{{ trans('admin/hardware/form.default_location') }}</th>
|
||||
<th data-field="asset_location" data-sortable="true" data-visible="false">{{ trans('general.location') }}</th>
|
||||
<th data-field="asset_serial" data-sortable="true" data-visible="true">{{ trans('admin/hardware/form.serial') }}</th>
|
||||
<th data-field="asset_checkout_date" data-sortable="true" data-visible="true">{{ trans('admin/hardware/table.checkout_date') }}</th>
|
||||
|
@ -129,6 +130,7 @@
|
|||
<td>{{ $asset->name }}</td>
|
||||
<td>{{ (($asset->model) && ($asset->model->category)) ? $asset->model->category->name : trans('general.invalid_category') }}</td>
|
||||
<td>{{ ($asset->model) ? $asset->model->name : trans('general.invalid_model') }}</td>
|
||||
<td>{{ ($asset->defaultLoc) ? $asset->defaultLoc->name : '' }}</td>
|
||||
<td>{{ ($asset->location) ? $asset->location->name : '' }}</td>
|
||||
<td>{{ $asset->serial }}</td>
|
||||
<td>
|
||||
|
@ -155,6 +157,7 @@
|
|||
<td>{{ $asset->asset_tag }}</td>
|
||||
<td>{{ $asset->name }}</td>
|
||||
<td>{{ $asset->model->category->name }}</td>
|
||||
<td>{{ ($asset->defaultLoc) ? $asset->defaultLoc->name : '' }}</td>
|
||||
<td>{{ ($asset->location) ? $asset->location->name : '' }}</td>
|
||||
<td>{{ $asset->model->name }}</td>
|
||||
<td>{{ $asset->serial }}</td>
|
||||
|
|
|
@ -597,7 +597,7 @@
|
|||
</div>
|
||||
</div>
|
||||
|
||||
@if ((Auth::user()->isSuperUser()) && ($snipeSettings->two_factor_enabled!='0') && ($snipeSettings->two_factor_enabled!=''))
|
||||
@if ((Auth::user()->isSuperUser()) && ($user->two_factor_active_and_enrolled()) && ($snipeSettings->two_factor_enabled!='0') && ($snipeSettings->two_factor_enabled!=''))
|
||||
|
||||
<!-- 2FA reset -->
|
||||
<div class="row">
|
||||
|
|
|
@ -7,13 +7,10 @@ use App\Models\Actionlog;
|
|||
use App\Models\User;
|
||||
use App\Notifications\CheckoutAccessoryNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccessoryCheckoutTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingOutAccessoryRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
|
|
|
@ -11,13 +11,10 @@ use App\Models\Statuslabel;
|
|||
use App\Models\User;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetCheckinTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingInAssetRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
|
|
|
@ -6,13 +6,10 @@ use App\Models\Asset;
|
|||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetIndexTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testAssetIndexReturnsExpectedAssets()
|
||||
{
|
||||
Asset::factory()->count(3)->create();
|
||||
|
|
|
@ -9,15 +9,11 @@ use App\Models\Location;
|
|||
use App\Models\Statuslabel;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetStoreTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testRequiresPermissionToCreateAsset()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
|
@ -69,8 +65,7 @@ class AssetStoreTest extends TestCase
|
|||
$this->assertEquals('random_string', $asset->asset_tag);
|
||||
$this->assertEquals($userAssigned->id, $asset->assigned_to);
|
||||
$this->assertTrue($asset->company->is($company));
|
||||
// I don't see this on the GUI side either, but it's in the docs so I'm guessing that's a mistake? It wasn't in the controller.
|
||||
// $this->assertEquals('2023-09-03', $asset->last_audit_date);
|
||||
$this->assertEquals('2023-09-03 00:00:00', $asset->last_audit_date->format('Y-m-d H:i:s'));
|
||||
$this->assertTrue($asset->location->is($location));
|
||||
$this->assertTrue($asset->model->is($model));
|
||||
$this->assertEquals('A New Asset', $asset->name);
|
||||
|
@ -86,6 +81,52 @@ class AssetStoreTest extends TestCase
|
|||
$this->assertEquals(10, $asset->warranty_months);
|
||||
}
|
||||
|
||||
public function testSetsLastAuditDateToMidnightOfProvidedDate()
|
||||
{
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'last_audit_date' => '2023-09-03 12:23:45',
|
||||
'asset_tag' => '1234',
|
||||
'model_id' => AssetModel::factory()->create()->id,
|
||||
'status_id' => Statuslabel::factory()->create()->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success');
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
$this->assertEquals('00:00:00', $asset->last_audit_date->format('H:i:s'));
|
||||
}
|
||||
|
||||
public function testLastAuditDateCanBeNull()
|
||||
{
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
// 'last_audit_date' => '2023-09-03 12:23:45',
|
||||
'asset_tag' => '1234',
|
||||
'model_id' => AssetModel::factory()->create()->id,
|
||||
'status_id' => Statuslabel::factory()->create()->id,
|
||||
])
|
||||
->assertOk()
|
||||
->assertStatusMessageIs('success');
|
||||
|
||||
$asset = Asset::find($response['payload']['id']);
|
||||
$this->assertNull($asset->last_audit_date);
|
||||
}
|
||||
|
||||
public function testNonDateUsedForLastAuditDateReturnsValidationError()
|
||||
{
|
||||
$response = $this->actingAsForApi(User::factory()->superuser()->create())
|
||||
->postJson(route('api.assets.store'), [
|
||||
'last_audit_date' => 'this-is-not-valid',
|
||||
'asset_tag' => '1234',
|
||||
'model_id' => AssetModel::factory()->create()->id,
|
||||
'status_id' => Statuslabel::factory()->create()->id,
|
||||
])
|
||||
->assertStatusMessageIs('error');
|
||||
|
||||
$this->assertNotNull($response->json('messages.last_audit_date'));
|
||||
}
|
||||
|
||||
public function testArchivedDepreciateAndPhysicalCanBeNull()
|
||||
{
|
||||
$model = AssetModel::factory()->ipadModel()->create();
|
||||
|
|
|
@ -5,13 +5,10 @@ namespace Tests\Feature\Api\Assets;
|
|||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetsForSelectListTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testAssetsCanBeSearchedForByAssetTag()
|
||||
{
|
||||
Asset::factory()->create(['asset_tag' => '0001']);
|
||||
|
|
|
@ -5,13 +5,10 @@ namespace Tests\Feature\Api\Assets;
|
|||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class RequestableAssetsTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testViewingRequestableAssetsRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
|
|
|
@ -5,13 +5,10 @@ namespace Tests\Feature\Api\Components;
|
|||
use App\Models\Company;
|
||||
use App\Models\Component;
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ComponentIndexTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testComponentIndexAdheresToCompanyScoping()
|
||||
{
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
|
|
@ -7,13 +7,10 @@ use App\Models\Consumable;
|
|||
use App\Models\User;
|
||||
use App\Notifications\CheckoutConsumableNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ConsumableCheckoutTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingOutConsumableRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
|
|
|
@ -5,13 +5,10 @@ namespace Tests\Feature\Api\Consumables;
|
|||
use App\Models\Company;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ConsumablesIndexTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testConsumableIndexAdheresToCompanyScoping()
|
||||
{
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
|
|
@ -5,15 +5,11 @@ namespace Tests\Feature\Api\Departments;
|
|||
use App\Models\Company;
|
||||
use App\Models\Department;
|
||||
use App\Models\User;
|
||||
use Illuminate\Routing\Route;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class DepartmentIndexTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testViewingDepartmentIndexRequiresAuthentication()
|
||||
{
|
||||
$this->getJson(route('api.departments.index'))->assertRedirect();
|
||||
|
|
|
@ -4,13 +4,10 @@ namespace Tests\Feature\Api\Groups;
|
|||
|
||||
use App\Models\Group;
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class GroupStoreTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testStoringGroupRequiresSuperAdminPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
|
|
|
@ -5,13 +5,10 @@ namespace Tests\Feature\Api\Licenses;
|
|||
use App\Models\Company;
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LicensesIndexTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testLicensesIndexAdheresToCompanyScoping()
|
||||
{
|
||||
[$companyA, $companyB] = Company::factory()->count(2)->create();
|
||||
|
|
|
@ -5,13 +5,10 @@ namespace Tests\Feature\Api\Locations;
|
|||
use App\Models\Location;
|
||||
use App\Models\User;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LocationsForSelectListTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testGettingLocationListRequiresProperPermission()
|
||||
{
|
||||
$this->actingAsForApi(User::factory()->create())
|
||||
|
|
|
@ -3,13 +3,10 @@
|
|||
namespace Tests\Feature\Api\Users;
|
||||
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UpdateUserApiTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testApiUsersCanBeActivatedWithNumber()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
|
|
|
@ -6,13 +6,10 @@ use App\Models\Company;
|
|||
use App\Models\User;
|
||||
use Illuminate\Testing\Fluent\AssertableJson;
|
||||
use Laravel\Passport\Passport;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UsersForSelectListTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testUsersAreReturned()
|
||||
{
|
||||
$users = User::factory()->superuser()->count(3)->create();
|
||||
|
|
|
@ -5,13 +5,10 @@ namespace Tests\Feature\Api\Users;
|
|||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Laravel\Passport\Passport;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UsersSearchTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCanSearchByUserFirstAndLastName()
|
||||
{
|
||||
User::factory()->create(['first_name' => 'Luke', 'last_name' => 'Skywalker']);
|
||||
|
|
|
@ -8,13 +8,10 @@ use App\Models\Group;
|
|||
use App\Models\Location;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UsersUpdateTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCanUpdateUserViaPatch()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
|
|
|
@ -8,13 +8,10 @@ use App\Models\User;
|
|||
use App\Notifications\CheckinAccessoryNotification;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccessoryCheckinTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingInAccessoryRequiresCorrectPermission()
|
||||
{
|
||||
$accessory = Accessory::factory()->checkedOutToUser()->create();
|
||||
|
|
|
@ -11,13 +11,10 @@ use App\Models\Statuslabel;
|
|||
use App\Models\User;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Event;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetCheckinTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingInAssetRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAs(User::factory()->create())
|
||||
|
|
|
@ -7,13 +7,10 @@ use App\Models\CheckoutAcceptance;
|
|||
use App\Notifications\AcceptanceAssetAcceptedNotification;
|
||||
use App\Notifications\AcceptanceAssetDeclinedNotification;
|
||||
use Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccessoryAcceptanceTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
/**
|
||||
* This can be absorbed into a bigger test
|
||||
*/
|
||||
|
|
|
@ -7,13 +7,10 @@ use App\Models\Actionlog;
|
|||
use App\Models\User;
|
||||
use App\Notifications\CheckoutAccessoryNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AccessoryCheckoutTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingOutAccessoryRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAs(User::factory()->create())
|
||||
|
|
|
@ -7,13 +7,10 @@ use App\Models\Consumable;
|
|||
use App\Models\User;
|
||||
use App\Notifications\CheckoutConsumableNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ConsumableCheckoutTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testCheckingOutConsumableRequiresCorrectPermission()
|
||||
{
|
||||
$this->actingAs(User::factory()->create())
|
||||
|
|
|
@ -6,13 +6,10 @@ use App\Models\Asset;
|
|||
use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class LicenseCheckoutTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testNotesAreStoredInActionLogOnCheckoutToAsset()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
|
|
|
@ -3,13 +3,10 @@
|
|||
namespace Tests\Feature;
|
||||
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class DashboardTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testUsersWithoutAdminAccessAreRedirected()
|
||||
{
|
||||
$this->actingAs(User::factory()->create())
|
||||
|
|
|
@ -7,7 +7,6 @@ use App\Models\Asset;
|
|||
use App\Models\User;
|
||||
use App\Notifications\CheckinAssetNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
|
@ -15,8 +14,6 @@ use Tests\TestCase;
|
|||
*/
|
||||
class EmailNotificationsUponCheckinTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
|
|
@ -14,7 +14,6 @@ use App\Notifications\CheckinAssetNotification;
|
|||
use App\Notifications\CheckinLicenseSeatNotification;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
|
@ -22,8 +21,6 @@ use Tests\TestCase;
|
|||
*/
|
||||
class SlackNotificationsUponCheckinTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
|
|
@ -16,7 +16,6 @@ use App\Notifications\CheckoutConsumableNotification;
|
|||
use App\Notifications\CheckoutLicenseSeatNotification;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
|
@ -24,8 +23,6 @@ use Tests\TestCase;
|
|||
*/
|
||||
class SlackNotificationsUponCheckoutTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
|
|
@ -8,14 +8,10 @@ use App\Models\User;
|
|||
use Illuminate\Testing\TestResponse;
|
||||
use League\Csv\Reader;
|
||||
use PHPUnit\Framework\Assert;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
|
||||
class CustomReportTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
|
|
@ -3,13 +3,10 @@
|
|||
namespace Tests\Feature\Users;
|
||||
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class UpdateUserTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testUsersCanBeActivatedWithNumber()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
|
|
|
@ -4,7 +4,7 @@ namespace Tests\Support;
|
|||
|
||||
use App\Models\Setting;
|
||||
|
||||
trait InteractsWithSettings
|
||||
trait InitializesSettings
|
||||
{
|
||||
protected Settings $settings;
|
||||
|
|
@ -9,7 +9,7 @@ use RuntimeException;
|
|||
use Tests\Support\AssertsAgainstSlackNotifications;
|
||||
use Tests\Support\CustomTestMacros;
|
||||
use Tests\Support\InteractsWithAuthentication;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\Support\InitializesSettings;
|
||||
|
||||
abstract class TestCase extends BaseTestCase
|
||||
{
|
||||
|
@ -17,6 +17,7 @@ abstract class TestCase extends BaseTestCase
|
|||
use CreatesApplication;
|
||||
use CustomTestMacros;
|
||||
use InteractsWithAuthentication;
|
||||
use InitializesSettings;
|
||||
use LazilyRefreshDatabase;
|
||||
|
||||
private array $globallyDisabledMiddleware = [
|
||||
|
@ -25,20 +26,23 @@ abstract class TestCase extends BaseTestCase
|
|||
|
||||
protected function setUp(): void
|
||||
{
|
||||
if (!file_exists(realpath(__DIR__ . '/../') . '/.env.testing')) {
|
||||
throw new RuntimeException(
|
||||
'.env.testing file does not exist. Aborting to avoid wiping your local database'
|
||||
);
|
||||
}
|
||||
$this->guardAgainstMissingEnv();
|
||||
|
||||
parent::setUp();
|
||||
|
||||
$this->registerCustomMacros();
|
||||
|
||||
$this->withoutMiddleware($this->globallyDisabledMiddleware);
|
||||
|
||||
if (collect(class_uses_recursive($this))->contains(InteractsWithSettings::class)) {
|
||||
$this->initializeSettings();
|
||||
}
|
||||
$this->initializeSettings();
|
||||
}
|
||||
|
||||
$this->registerCustomMacros();
|
||||
private function guardAgainstMissingEnv(): void
|
||||
{
|
||||
if (!file_exists(realpath(__DIR__ . '/../') . '/.env.testing')) {
|
||||
throw new RuntimeException(
|
||||
'.env.testing file does not exist. Aborting to avoid wiping your local database.'
|
||||
);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,14 +2,10 @@
|
|||
namespace Tests\Unit;
|
||||
|
||||
use App\Models\AssetMaintenance;
|
||||
use Carbon\Carbon;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetMaintenanceTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testZerosOutWarrantyIfBlank()
|
||||
{
|
||||
$c = new AssetMaintenance;
|
||||
|
|
|
@ -4,13 +4,10 @@ namespace Tests\Unit;
|
|||
use App\Models\Asset;
|
||||
use App\Models\Category;
|
||||
use App\Models\AssetModel;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetModelTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testAnAssetModelContainsAssets()
|
||||
{
|
||||
$category = Category::factory()->create([
|
||||
|
|
|
@ -5,13 +5,10 @@ use App\Models\Asset;
|
|||
use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
use Carbon\Carbon;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testAutoIncrement()
|
||||
{
|
||||
$this->settings->enableAutoIncrement();
|
||||
|
|
|
@ -4,13 +4,10 @@ namespace Tests\Unit;
|
|||
use App\Models\Category;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Asset;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class CategoryTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testFailsEmptyValidation()
|
||||
{
|
||||
// An Asset requires a name, a qty, and a category_id.
|
||||
|
|
|
@ -12,13 +12,10 @@ use App\Models\License;
|
|||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class CompanyScopingTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function models(): array
|
||||
{
|
||||
return [
|
||||
|
|
|
@ -5,13 +5,10 @@ use App\Models\Category;
|
|||
use App\Models\Company;
|
||||
use App\Models\Component;
|
||||
use App\Models\Location;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class ComponentTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testAComponentBelongsToACompany()
|
||||
{
|
||||
$component = Component::factory()
|
||||
|
|
|
@ -5,13 +5,10 @@ use App\Models\Depreciation;
|
|||
use App\Models\Category;
|
||||
use App\Models\License;
|
||||
use App\Models\AssetModel;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class DepreciationTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testADepreciationHasModels()
|
||||
{
|
||||
$depreciation = Depreciation::factory()->create();
|
||||
|
|
|
@ -3,8 +3,6 @@
|
|||
namespace Tests\Unit;
|
||||
|
||||
use App\Models\Ldap;
|
||||
use Exception;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
/**
|
||||
|
@ -12,7 +10,6 @@ use Tests\TestCase;
|
|||
*/
|
||||
class LdapTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
use \phpmock\phpunit\PHPMock;
|
||||
|
||||
public function testConnect()
|
||||
|
|
|
@ -4,13 +4,10 @@ namespace Tests\Unit\Models\Company;
|
|||
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class GetIdForCurrentUserTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testReturnsProvidedValueWhenFullCompanySupportDisabled()
|
||||
{
|
||||
$this->settings->disableMultipleFullCompanySupport();
|
||||
|
|
|
@ -8,13 +8,10 @@ use App\Models\Category;
|
|||
use Carbon\Carbon;
|
||||
use App\Notifications\CheckoutAssetNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class NotificationTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testAUserIsEmailedIfTheyCheckoutAnAssetWithEULA()
|
||||
{
|
||||
$admin = User::factory()->superuser()->create();
|
||||
|
|
|
@ -2,13 +2,10 @@
|
|||
namespace Tests\Unit;
|
||||
|
||||
use App\Models\SnipeModel;
|
||||
use Tests\Support\InteractsWithSettings;
|
||||
use Tests\TestCase;
|
||||
|
||||
class SnipeModelTest extends TestCase
|
||||
{
|
||||
use InteractsWithSettings;
|
||||
|
||||
public function testSetsPurchaseDatesAppropriately()
|
||||
{
|
||||
$c = new SnipeModel;
|
||||
|
|
|
@ -183,11 +183,11 @@ mix
|
|||
[
|
||||
"./resources/assets/js/dragtable.js",
|
||||
'./node_modules/bootstrap-table/dist/bootstrap-table.js',
|
||||
"./resources/assets/js/bootstrap-table-reorder-columns.js",
|
||||
'./node_modules/bootstrap-table/dist/extensions/mobile/bootstrap-table-mobile.js',
|
||||
'./node_modules/bootstrap-table/dist/extensions/export/bootstrap-table-export.js',
|
||||
'./node_modules/bootstrap-table/dist/extensions/cookie/bootstrap-table-cookie.js',
|
||||
'./node_modules/bootstrap-table/dist/extensions/sticky-header/bootstrap-table-sticky-header.js',
|
||||
'./node_modules/bootstrap-table/dist/extensions/addrbar/bootstrap-table-addrbar.js',
|
||||
'./resources/assets/js/extensions/jquery.base64.js',
|
||||
'./node_modules/tableexport.jquery.plugin/tableExport.min.js',
|
||||
'./node_modules/tableexport.jquery.plugin/libs/jsPDF/jspdf.umd.min.js',
|
||||
|
|
Loading…
Reference in a new issue