Compare commits
70 Commits
v8.0.2
...
fix_s3_bac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93014d7f34 | ||
|
|
759e3794df | ||
|
|
c50b14763f | ||
|
|
369a68fe57 | ||
|
|
83855d44d0 | ||
|
|
6f847294ed | ||
|
|
d556d1c6e7 | ||
|
|
3bb94e98f0 | ||
|
|
8f5f6f3502 | ||
|
|
b3792bfa00 | ||
|
|
40f7257723 | ||
|
|
8486256142 | ||
|
|
7f36750e33 | ||
|
|
de046db106 | ||
|
|
eb1d27a5bc | ||
|
|
cc0b9f404a | ||
|
|
70332696c6 | ||
|
|
7a9b5d61b0 | ||
|
|
5876259893 | ||
|
|
8755c54edc | ||
|
|
014f3b7652 | ||
|
|
3a2579b205 | ||
|
|
149474bfe3 | ||
|
|
b2b768dede | ||
|
|
a9ed9e2a7f | ||
|
|
ce8523b00a | ||
|
|
7076a68d35 | ||
|
|
112112d258 | ||
|
|
3928c8afe9 | ||
|
|
23ce54e80c | ||
|
|
646e3e8df5 | ||
|
|
30c4e9dbf7 | ||
|
|
27fc30a881 | ||
|
|
8ac7cda4ee | ||
|
|
6f04d314a8 | ||
|
|
1051b1d16d | ||
|
|
115bb94704 | ||
|
|
25807cc62f | ||
|
|
cd1d1b2d3e | ||
|
|
6dcd3bfd30 | ||
|
|
a0dc056da8 | ||
|
|
27aeb518ff | ||
|
|
245a16c377 | ||
|
|
de3c1d159f | ||
|
|
e88bba51bb | ||
|
|
f97211f6cd | ||
|
|
027c2b3627 | ||
|
|
4c43a06eee | ||
|
|
25c8449e86 | ||
|
|
13e1f4a127 | ||
|
|
ed96fd766c | ||
|
|
7cbb3f7e07 | ||
|
|
7e9c564d0b | ||
|
|
fc88b2487f | ||
|
|
e94ee48f74 | ||
|
|
6a4a5d1380 | ||
|
|
ab9e9b66d2 | ||
|
|
c15c338ffd | ||
|
|
d1197d015c | ||
|
|
ce31ce477e | ||
|
|
78f9292555 | ||
|
|
4e7c6bd2cf | ||
|
|
70aed45bfe | ||
|
|
e2805f4033 | ||
|
|
d254a40e0a | ||
|
|
fdcb891cbb | ||
|
|
16d322d70e | ||
|
|
2163312997 | ||
|
|
0dfb71cfe5 | ||
|
|
bdb0e6c2a3 |
@@ -3289,6 +3289,15 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "azmcnutt",
|
||||
"name": "James M",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/31522486?v=4",
|
||||
"profile": "https://github.com/azmcnutt",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
| [<img src="https://avatars.githubusercontent.com/u/55590532?v=4" width="110px;"/><br /><sub>squintfox</sub>](https://github.com/squintfox)<br />[💻](https://github.com/snipe/snipe-it/commits?author=squintfox "Code") | [<img src="https://avatars.githubusercontent.com/u/1380084?v=4" width="110px;"/><br /><sub>Jeff Clay</sub>](https://github.com/jeffclay)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jeffclay "Code") | [<img src="https://avatars.githubusercontent.com/u/52716446?v=4" width="110px;"/><br /><sub>Phil J R</sub>](https://github.com/PP-JN-RL)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PP-JN-RL "Code") | [<img src="https://avatars.githubusercontent.com/u/1496725?v=4" width="110px;"/><br /><sub>i_virus</sub>](https://www.corelight.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chandanchowdhury "Code") | [<img src="https://avatars.githubusercontent.com/u/1020541?v=4" width="110px;"/><br /><sub>Paul Grime</sub>](https://github.com/gitgrimbo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gitgrimbo "Code") | [<img src="https://avatars.githubusercontent.com/u/922815?v=4" width="110px;"/><br /><sub>Lee Porte</sub>](https://leeporte.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=LeePorte "Code") | [<img src="https://avatars.githubusercontent.com/u/23613427?v=4" width="110px;"/><br /><sub>BRYAN </sub>](https://github.com/bryanlopezinc)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Code") [⚠️](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Tests") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/64061710?v=4" width="110px;"/><br /><sub>U-H-T</sub>](https://github.com/U-H-T)<br />[💻](https://github.com/snipe/snipe-it/commits?author=U-H-T "Code") | [<img src="https://avatars.githubusercontent.com/u/5395363?v=4" width="110px;"/><br /><sub>Matt Tyree</sub>](https://github.com/Tyree)<br />[📖](https://github.com/snipe/snipe-it/commits?author=Tyree "Documentation") | [<img src="https://avatars.githubusercontent.com/u/292081?v=4" width="110px;"/><br /><sub>Florent Bervas</sub>](http://spoontux.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FlorentDotMe "Code") | [<img src="https://avatars.githubusercontent.com/u/4498077?v=4" width="110px;"/><br /><sub>Daniel Albertsen</sub>](https://ditscheri.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dbakan "Code") | [<img src="https://avatars.githubusercontent.com/u/100710244?v=4" width="110px;"/><br /><sub>r-xyz</sub>](https://github.com/r-xyz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=r-xyz "Code") | [<img src="https://avatars.githubusercontent.com/u/47491036?v=4" width="110px;"/><br /><sub>Steven Mainor</sub>](https://github.com/DrekiDegga)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DrekiDegga "Code") | [<img src="https://avatars.githubusercontent.com/u/65785975?v=4" width="110px;"/><br /><sub>arne-kroeger</sub>](https://github.com/arne-kroeger)<br />[💻](https://github.com/snipe/snipe-it/commits?author=arne-kroeger "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/167117705?v=4" width="110px;"/><br /><sub>Glukose1</sub>](https://github.com/Glukose1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Glukose1 "Code") | [<img src="https://avatars.githubusercontent.com/u/1197791?v=4" width="110px;"/><br /><sub>Scarzy</sub>](https://github.com/Scarzy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Scarzy "Code") | [<img src="https://avatars.githubusercontent.com/u/37372069?v=4" width="110px;"/><br /><sub>setpill</sub>](https://github.com/setpill)<br />[💻](https://github.com/snipe/snipe-it/commits?author=setpill "Code") | [<img src="https://avatars.githubusercontent.com/u/3755203?v=4" width="110px;"/><br /><sub>swift2512</sub>](https://github.com/swift2512)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aswift2512 "Bug reports") | [<img src="https://avatars.githubusercontent.com/u/6136439?v=4" width="110px;"/><br /><sub>Darren Rainey</sub>](https://darrenraineys.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DarrenRainey "Code") | [<img src="https://avatars.githubusercontent.com/u/133033121?v=4" width="110px;"/><br /><sub>maciej-poleszczyk</sub>](https://github.com/maciej-poleszczyk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=maciej-poleszczyk "Code") | [<img src="https://avatars.githubusercontent.com/u/143394709?v=4" width="110px;"/><br /><sub>Sebastian Groß</sub>](https://github.com/sgross-emlix)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sgross-emlix "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/41107778?v=4" width="110px;"/><br /><sub>Anouar Touati</sub>](https://github.com/AnouarTouati)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AnouarTouati "Code") | [<img src="https://avatars.githubusercontent.com/u/25596663?v=4" width="110px;"/><br /><sub>aHVzY2g</sub>](https://github.com/aHVzY2g)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aHVzY2g "Code") | [<img src="https://avatars.githubusercontent.com/u/13408130?v=4" width="110px;"/><br /><sub>林博仁 Buo-ren Lin</sub>](https://brlin.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=brlin-tw "Code") | [<img src="https://avatars.githubusercontent.com/u/18550946?v=4" width="110px;"/><br /><sub>Adugna Gizaw</sub>](https://orbalia.pythonanywhere.com/)<br />[🌍](#translation-addex12 "Translation") | [<img src="https://avatars.githubusercontent.com/u/760989?v=4" width="110px;"/><br /><sub>Jesse Ostrander</sub>](https://github.com/jostrander)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jostrander "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/41107778?v=4" width="110px;"/><br /><sub>Anouar Touati</sub>](https://github.com/AnouarTouati)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AnouarTouati "Code") | [<img src="https://avatars.githubusercontent.com/u/25596663?v=4" width="110px;"/><br /><sub>aHVzY2g</sub>](https://github.com/aHVzY2g)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aHVzY2g "Code") | [<img src="https://avatars.githubusercontent.com/u/13408130?v=4" width="110px;"/><br /><sub>林博仁 Buo-ren Lin</sub>](https://brlin.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=brlin-tw "Code") | [<img src="https://avatars.githubusercontent.com/u/18550946?v=4" width="110px;"/><br /><sub>Adugna Gizaw</sub>](https://orbalia.pythonanywhere.com/)<br />[🌍](#translation-addex12 "Translation") | [<img src="https://avatars.githubusercontent.com/u/760989?v=4" width="110px;"/><br /><sub>Jesse Ostrander</sub>](https://github.com/jostrander)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jostrander "Code") | [<img src="https://avatars.githubusercontent.com/u/31522486?v=4" width="110px;"/><br /><sub>James M</sub>](https://github.com/azmcnutt)<br />[💻](https://github.com/snipe/snipe-it/commits?author=azmcnutt "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
@@ -361,9 +361,15 @@ class LdapSync extends Command
|
||||
// (Specifically, we don't handle a value of '0.0' correctly)
|
||||
$raw_value = @$results[$i][$ldap_map["active_flag"]][0];
|
||||
$filter_var = filter_var($raw_value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
||||
|
||||
$boolean_cast = (bool) $raw_value;
|
||||
|
||||
$user->activated = $filter_var ?? $boolean_cast; // if filter_var() was true or false, use that. If it's null, use the $boolean_cast
|
||||
|
||||
if (Setting::getSettings()->ldap_invert_active_flag === 1) {
|
||||
// Because ldap_active_flag is set, if filter_var is true or boolean_cast is true, then user is suspended
|
||||
$user->activated = !($filter_var ?? $boolean_cast);
|
||||
}else{
|
||||
$user->activated = $filter_var ?? $boolean_cast; // if filter_var() was true or false, use that. If it's null, use the $boolean_cast
|
||||
}
|
||||
|
||||
} elseif (array_key_exists('useraccountcontrol', $results[$i])) {
|
||||
// ....otherwise, (ie if no 'active' LDAP flag is defined), IF the UAC setting exists,
|
||||
@@ -428,8 +434,12 @@ class LdapSync extends Command
|
||||
$item['note'] = $item['createorupdate'];
|
||||
$item['status'] = 'success';
|
||||
if ($item['createorupdate'] === 'created' && $ldap_default_group) {
|
||||
$user->groups()->attach($ldap_default_group);
|
||||
// Check if the relationship already exists
|
||||
if (!$user->groups()->where('group_id', $ldap_default_group)->exists()) {
|
||||
$user->groups()->attach($ldap_default_group);
|
||||
}
|
||||
}
|
||||
|
||||
//updates assets location based on user's location
|
||||
if ($user->wasChanged('location_id')) {
|
||||
foreach ($user->assets as $asset) {
|
||||
|
||||
@@ -70,23 +70,26 @@ class SendAcceptanceReminder extends Command
|
||||
// The [0] is weird, but it allows for the item_count to work and grabs the appropriate info for each user.
|
||||
// Collapsing and flattening the collection doesn't work above.
|
||||
$acceptance = $unacceptedAssetGroup[0]['acceptance'];
|
||||
|
||||
$locale = $acceptance->assignedTo?->locale;
|
||||
$email = $acceptance->assignedTo?->email;
|
||||
|
||||
if(!$email){
|
||||
$no_email_list[] = [
|
||||
'id' => $acceptance->assignedTo->id,
|
||||
'name' => $acceptance->assignedTo->present()->fullName(),
|
||||
'id' => $acceptance->assignedTo?->id,
|
||||
'name' => $acceptance->assignedTo?->present()->fullName(),
|
||||
];
|
||||
} else {
|
||||
$count++;
|
||||
}
|
||||
$item_count = $unacceptedAssetGroup->count();
|
||||
|
||||
if ($locale && $email) {
|
||||
Mail::to($email)->send((new UnacceptedAssetReminderMail($acceptance, $item_count))->locale($locale));
|
||||
|
||||
} elseif ($email) {
|
||||
Mail::to($email)->send((new UnacceptedAssetReminderMail($acceptance, $item_count)));
|
||||
}
|
||||
$count++;
|
||||
|
||||
}
|
||||
|
||||
$this->info($count.' users notified.');
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Mail\SendUpcomingAuditMail;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Recipients\AlertRecipient;
|
||||
use App\Models\Setting;
|
||||
use App\Notifications\SendUpcomingAuditNotification;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class SendUpcomingAuditReport extends Command
|
||||
{
|
||||
@@ -48,19 +47,19 @@ class SendUpcomingAuditReport extends Command
|
||||
$today = Carbon::now();
|
||||
$interval_date = $today->copy()->addDays($interval);
|
||||
|
||||
$assets = Asset::whereNull('deleted_at')->DueOrOverdueForAudit($settings)->orderBy('assets.next_audit_date', 'desc')->get();
|
||||
$this->info($assets->count().' assets must be audited in on or before '.$interval_date.' is deadline');
|
||||
$assets = Asset::whereNull('deleted_at')->dueOrOverdueForAudit($settings)->orderBy('assets.next_audit_date', 'desc')->get();
|
||||
$this->info($assets->count() . ' assets must be audited in on or before ' . $interval_date . ' is deadline');
|
||||
|
||||
|
||||
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
||||
if ((count($assets) !== 0) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
||||
// Send a rollup to the admin, if settings dictate
|
||||
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item) {
|
||||
return new AlertRecipient($item);
|
||||
});
|
||||
$recipients = collect(explode(',', $settings->alert_email))
|
||||
->map(fn($item) => trim($item))
|
||||
->all();
|
||||
|
||||
$this->info('Sending Admin SendUpcomingAuditNotification to: '.$settings->alert_email);
|
||||
\Notification::send($recipients, new SendUpcomingAuditNotification($assets, $settings->audit_warning_days));
|
||||
|
||||
$this->info('Sending Admin SendUpcomingAuditNotification to: ' . $settings->alert_email);
|
||||
Mail::to($recipients)->send(new SendUpcomingAuditMail($assets, $settings->audit_warning_days));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Console;
|
||||
use App\Console\Commands\ImportLocations;
|
||||
use App\Console\Commands\ReEncodeCustomFieldNames;
|
||||
use App\Console\Commands\RestoreDeletedUsers;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
@@ -18,12 +19,14 @@ class Kernel extends ConsoleKernel
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
$schedule->command('snipeit:inventory-alerts')->daily();
|
||||
$schedule->command('snipeit:expiring-alerts')->daily();
|
||||
$schedule->command('snipeit:expected-checkin')->daily();
|
||||
if(Setting::getSettings()->alerts_enabled === 1) {
|
||||
$schedule->command('snipeit:inventory-alerts')->daily();
|
||||
$schedule->command('snipeit:expiring-alerts')->daily();
|
||||
$schedule->command('snipeit:expected-checkin')->daily();
|
||||
$schedule->command('snipeit:upcoming-audits')->daily();
|
||||
}
|
||||
$schedule->command('snipeit:backup')->weekly();
|
||||
$schedule->command('backup:clean')->daily();
|
||||
$schedule->command('snipeit:upcoming-audits')->daily();
|
||||
$schedule->command('auth:clear-resets')->everyFifteenMinutes();
|
||||
$schedule->command('saml:clear_expired_nonces')->weekly();
|
||||
}
|
||||
|
||||
@@ -66,25 +66,41 @@ class ImportController extends Controller
|
||||
if (! ini_get('auto_detect_line_endings')) {
|
||||
ini_set('auto_detect_line_endings', '1');
|
||||
}
|
||||
$file_contents = $file->getContent(); //TODO - this *does* load the whole file in RAM, but we need that to be able to 'iconv' it?
|
||||
$encoding = $detector->getEncoding($file_contents);
|
||||
$reader = null;
|
||||
if (strcasecmp($encoding, 'UTF-8') != 0) {
|
||||
$transliterated = iconv($encoding, 'UTF-8', $file_contents);
|
||||
if ($transliterated !== false) {
|
||||
$tmpname = tempnam(sys_get_temp_dir(), '');
|
||||
$tmpresults = file_put_contents($tmpname, $transliterated);
|
||||
if ($tmpresults !== false) {
|
||||
if (function_exists('iconv')) {
|
||||
$file_contents = $file->getContent(); //TODO - this *does* load the whole file in RAM, but we need that to be able to 'iconv' it?
|
||||
$encoding = $detector->getEncoding($file_contents);
|
||||
\Log::warning("Discovered encoding: $encoding in uploaded CSV");
|
||||
$reader = null;
|
||||
if (strcasecmp($encoding, 'UTF-8') != 0) {
|
||||
$transliterated = false;
|
||||
try {
|
||||
$transliterated = iconv(strtoupper($encoding), 'UTF-8', $file_contents);
|
||||
} catch (\Exception $e) {
|
||||
$transliterated = false; //blank out the partially-decoded string
|
||||
return response()->json(
|
||||
Helper::formatStandardApiResponse(
|
||||
'error',
|
||||
null,
|
||||
trans('admin/hardware/message.import.transliterate_failure', ["encoding" => $encoding])
|
||||
),
|
||||
422
|
||||
);
|
||||
}
|
||||
if ($transliterated !== false) {
|
||||
$tmpname = tempnam(sys_get_temp_dir(), '');
|
||||
$tmpresults = file_put_contents($tmpname, $transliterated);
|
||||
$transliterated = null; //save on memory?
|
||||
$newfile = new UploadedFile($tmpname, $file->getClientOriginalName(), null, null, true); //WARNING: this is enabling 'test mode' - which is gross, but otherwise the file won't be treated as 'uploaded'
|
||||
if ($newfile->isValid()) {
|
||||
$file = $newfile;
|
||||
if ($tmpresults !== false) {
|
||||
$newfile = new UploadedFile($tmpname, $file->getClientOriginalName(), null, null, true); //WARNING: this is enabling 'test mode' - which is gross, but otherwise the file won't be treated as 'uploaded'
|
||||
if ($newfile->isValid()) {
|
||||
$file = $newfile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$file_contents = null; //try to save on memory, I guess?
|
||||
}
|
||||
$reader = Reader::createFromFileObject($file->openFile('r')); //file pointer leak?
|
||||
$file_contents = null; //try to save on memory, I guess?
|
||||
|
||||
try {
|
||||
$import->header_row = $reader->fetchOne(0);
|
||||
|
||||
@@ -206,6 +206,7 @@ class LoginController extends Controller
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
$user->last_login = \Carbon::now();
|
||||
$user->email = $ldap_attr['email'];
|
||||
$user->first_name = $ldap_attr['firstname'];
|
||||
$user->last_name = $ldap_attr['lastname']; //FIXME (or TODO?) - do we need to map additional fields that we now support? E.g. country, phone, etc.
|
||||
@@ -432,6 +433,7 @@ class LoginController extends Controller
|
||||
|
||||
if (Google2FA::verifyKey($user->two_factor_secret, $secret)) {
|
||||
$user->two_factor_enrolled = 1;
|
||||
$user->last_login = \Carbon::now();
|
||||
$user->saveQuietly();
|
||||
$request->session()->put('2fa_authed', $user->id);
|
||||
|
||||
|
||||
@@ -1175,18 +1175,13 @@ class ReportsController extends Controller
|
||||
}
|
||||
$email = $assetItem->assignedTo?->email;
|
||||
$locale = $assetItem->assignedTo?->locale;
|
||||
// Only send notification if assigned
|
||||
if ($locale && $email) {
|
||||
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note))->locale($locale));
|
||||
|
||||
} elseif ($email) {
|
||||
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note)));
|
||||
}
|
||||
|
||||
if ($email == ''){
|
||||
if (is_null($email) || $email === '') {
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.no_email'));
|
||||
}
|
||||
|
||||
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note, firstTimeSending: false))->locale($locale));
|
||||
|
||||
return redirect()->route('reports/unaccepted_assets')->with('success', trans('admin/reports/general.reminder_sent'));
|
||||
}
|
||||
|
||||
|
||||
1
app/Http/Controllers/SettingsController.php
Executable file → Normal file
1
app/Http/Controllers/SettingsController.php
Executable file → Normal file
@@ -851,6 +851,7 @@ class SettingsController extends Controller
|
||||
$setting->ldap_auth_filter_query = $request->input('ldap_auth_filter_query');
|
||||
$setting->ldap_version = $request->input('ldap_version', 3);
|
||||
$setting->ldap_active_flag = $request->input('ldap_active_flag');
|
||||
$setting->ldap_invert_active_flag = $request->input('ldap_invert_active_flag');
|
||||
$setting->ldap_emp_num = $request->input('ldap_emp_num');
|
||||
$setting->ldap_email = $request->input('ldap_email');
|
||||
$setting->ldap_manager = $request->input('ldap_manager');
|
||||
|
||||
@@ -12,11 +12,11 @@ class CategoryEditForm extends Component
|
||||
|
||||
public $originalSendCheckInEmailValue;
|
||||
|
||||
public $requireAcceptance;
|
||||
public bool $requireAcceptance;
|
||||
|
||||
public $sendCheckInEmail;
|
||||
public bool $sendCheckInEmail;
|
||||
|
||||
public $useDefaultEula;
|
||||
public bool $useDefaultEula;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
|
||||
@@ -20,10 +20,12 @@ class CheckoutAssetMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
private bool $firstTimeSending;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
|
||||
public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $acceptance, $note, bool $firstTimeSending = true)
|
||||
{
|
||||
$this->item = $asset;
|
||||
$this->admin = $checkedOutBy;
|
||||
@@ -36,6 +38,8 @@ class CheckoutAssetMail extends Mailable
|
||||
$this->last_checkout = '';
|
||||
$this->expected_checkin = '';
|
||||
|
||||
$this->firstTimeSending = $firstTimeSending;
|
||||
|
||||
if ($this->item->last_checkout) {
|
||||
$this->last_checkout = Helper::getFormattedDateObject($this->item->last_checkout, 'date',
|
||||
false);
|
||||
@@ -56,7 +60,7 @@ class CheckoutAssetMail extends Mailable
|
||||
|
||||
return new Envelope(
|
||||
from: $from,
|
||||
subject: trans('mail.Asset_Checkout_Notification'),
|
||||
subject: $this->getSubject(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -107,4 +111,13 @@ class CheckoutAssetMail extends Mailable
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
private function getSubject(): string
|
||||
{
|
||||
if ($this->firstTimeSending) {
|
||||
return trans('mail.Asset_Checkout_Notification');
|
||||
}
|
||||
|
||||
return trans('mail.unaccepted_asset_reminder');
|
||||
}
|
||||
}
|
||||
|
||||
65
app/Mail/SendUpcomingAuditMail.php
Normal file
65
app/Mail/SendUpcomingAuditMail.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SendUpcomingAuditMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct($params, $threshold)
|
||||
{
|
||||
$this->assets = $params;
|
||||
$this->threshold = $threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
$from = new Address(config('mail.from.address'), config('mail.from.name'));
|
||||
|
||||
return new Envelope(
|
||||
from: $from,
|
||||
subject: trans_choice('mail.upcoming-audits', $this->assets->count(), ['count' => $this->assets->count(), 'threshold' => $this->threshold]),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
|
||||
|
||||
return new Content(
|
||||
|
||||
markdown: 'notifications.markdown.upcoming-audits',
|
||||
with: [
|
||||
'assets' => $this->assets,
|
||||
'threshold' => $this->threshold,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -19,9 +19,10 @@ class UnacceptedAssetReminderMail extends Mailable
|
||||
*/
|
||||
public function __construct($checkout_info, $count)
|
||||
{
|
||||
|
||||
$this->count = $count;
|
||||
$this->target = $checkout_info['acceptance']?->assignedTo;
|
||||
$this->acceptance = $checkout_info['acceptance'];
|
||||
$this->target = $checkout_info?->assignedTo;
|
||||
$this->acceptance = $checkout_info;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -90,12 +90,6 @@ class AssetMaintenancesPresenter extends Presenter
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/asset_maintenances/form.asset_maintenance_type'),
|
||||
], [
|
||||
'field' => 'title',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('admin/asset_maintenances/form.title'),
|
||||
], [
|
||||
'field' => 'start_date',
|
||||
'searchable' => true,
|
||||
|
||||
@@ -105,4 +105,17 @@ $config = [
|
||||
// (by default, the PUBLIC_FILESYSTEM DISK is 'local_public', in the public/uploads directory)
|
||||
$config['disks']['public'] = $config['disks'][env('PUBLIC_FILESYSTEM_DISK','local_public')];
|
||||
|
||||
// Handle the 'backup' disk for S3 consideration
|
||||
if (env('PRIVATE_FILESYSTEM_DISK') == 's3_private') {
|
||||
$config['disks']['backup']['driver'] = 's3';
|
||||
$config['disks']['backup']['key'] = $config['disks']['s3_private']['key'];
|
||||
$config['disks']['backup']['secret'] = $config['disks']['s3_private']['secret'];
|
||||
$config['disks']['backup']['region'] = $config['disks']['s3_private']['region'];
|
||||
$config['disks']['backup']['bucket'] = $config['disks']['s3_private']['bucket'];
|
||||
$config['disks']['backup']['url'] = $config['disks']['s3_private']['url'];
|
||||
$config['disks']['backup']['root'] = $config['disks']['s3_private']['root'];
|
||||
$config['disks']['backup']['visibility'] = 'private';
|
||||
}
|
||||
|
||||
|
||||
return $config;
|
||||
@@ -27,6 +27,10 @@ class CheckoutAcceptanceFactory extends Factory
|
||||
public function configure(): static
|
||||
{
|
||||
return $this->afterCreating(function (CheckoutAcceptance $acceptance) {
|
||||
if ($acceptance->checkoutable instanceof Asset) {
|
||||
$this->createdAssociatedActionLogEntry($acceptance);
|
||||
}
|
||||
|
||||
if ($acceptance->checkoutable instanceof Asset && $acceptance->assignedTo instanceof User) {
|
||||
$acceptance->checkoutable->update([
|
||||
'assigned_to' => $acceptance->assigned_to_id,
|
||||
@@ -51,4 +55,23 @@ class CheckoutAcceptanceFactory extends Factory
|
||||
'declined_at' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function accepted()
|
||||
{
|
||||
return $this->state([
|
||||
'accepted_at' => now()->subDay(),
|
||||
'declined_at' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
private function createdAssociatedActionLogEntry(CheckoutAcceptance $acceptance): void
|
||||
{
|
||||
$acceptance->checkoutable->assetlog()->create([
|
||||
'action_type' => 'checkout',
|
||||
'target_id' => $acceptance->assigned_to_id,
|
||||
'target_type' => get_class($acceptance->assignedTo),
|
||||
'item_id' => $acceptance->checkoutable_id,
|
||||
'item_type' => $acceptance->checkoutable_type,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->boolean('ldap_invert_active_flag')->default(false);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->dropColumn('ldap_invert_active_flag');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -13,4 +13,8 @@ return [
|
||||
'no_depreciations_warning' => '<strong>Warning: </strong>
|
||||
You do not currently have any depreciations set up.
|
||||
Please set up at least one depreciation to view the depreciation report.',
|
||||
'depreciation_method' => 'Depreciation Method',
|
||||
'linear_depreciation' => 'Linear (Default)',
|
||||
'half_1' => 'Half-year convention, always applied',
|
||||
'half_2' => 'Half-year convention, applied with condition',
|
||||
];
|
||||
|
||||
@@ -66,6 +66,7 @@ return [
|
||||
'file_already_deleted' => 'The file selected was already deleted',
|
||||
'header_row_has_malformed_characters' => 'One or more attributes in the header row contain malformed UTF-8 characters',
|
||||
'content_row_has_malformed_characters' => 'One or more attributes in the first row of content contain malformed UTF-8 characters',
|
||||
'transliterate_failure' => 'Transliteration from :encoding to UTF-8 failed due to invalid characters in input'
|
||||
],
|
||||
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ return [
|
||||
'info' => 'Select the options you want for your asset report.',
|
||||
'deleted_user' => 'Deleted user',
|
||||
'send_reminder' => 'Send reminder',
|
||||
'cannot_send_reminder' => 'User has been deleted or does not have an email address so cannot receive a reminder',
|
||||
'reminder_sent' => 'Reminder sent',
|
||||
'acceptance_deleted' => 'Acceptance request deleted',
|
||||
'acceptance_request' => 'Acceptance request',
|
||||
|
||||
@@ -42,6 +42,7 @@ return [
|
||||
'confirm_purge' => 'Confirm Purge',
|
||||
'confirm_purge_help' => 'Enter the text "DELETE" in the box below to purge your deleted records. This action cannot be undone and will PERMANENTLY delete all soft-deleted items and users. (You should make a backup first, just to be safe.)',
|
||||
'custom_css' => 'Custom CSS',
|
||||
'custom_css_placeholder' => 'Add your custom CSS',
|
||||
'custom_css_help' => 'Enter any custom CSS overrides you would like to use. Do not include the <style></style> tags.',
|
||||
'custom_forgot_pass_url' => 'Custom Password Reset URL',
|
||||
'custom_forgot_pass_url_help' => 'This replaces the built-in forgotten password URL on the login screen, useful to direct people to internal or hosted LDAP password reset functionality. It will effectively disable local user forgotten password functionality.',
|
||||
@@ -69,6 +70,7 @@ return [
|
||||
'favicon_size' => 'Favicons should be square images, 16x16 pixels.',
|
||||
'footer_text' => 'Additional Footer Text ',
|
||||
'footer_text_help' => 'This text will appear in the right-side footer. Links are allowed using <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>. Line breaks, headers, images, etc may result in unpredictable results.',
|
||||
'footer_text_placeholder' => 'Optional footer text',
|
||||
'general_settings' => 'General Settings',
|
||||
'general_settings_help' => 'Default EULA and more',
|
||||
'generate_backup' => 'Generate Backup',
|
||||
@@ -118,6 +120,8 @@ return [
|
||||
'ldap_version' => 'LDAP Version',
|
||||
'ldap_active_flag' => 'LDAP Active Flag',
|
||||
'ldap_activated_flag_help' => 'This value is used to determine whether a synced user can login to Snipe-IT. <strong>It does not affect the ability to check items in or out to them</strong>, and should be the <strong>attribute name</strong> within your AD/LDAP, <strong>not the value</strong>. <br><br>If this field is set to a field name that does not exist in your AD/LDAP, or the value in the AD/LDAP field is set to <code>0</code> or <code>false</code>, <strong>user login will be disabled</strong>. If the value in the AD/LDAP field is set to <code>1</code> or <code>true</code> or <em>any other text</em> means the user can log in. When the field is blank in your AD, we respect the <code>userAccountControl</code> attribute, which usually allows non-suspended users to log in.',
|
||||
'ldap_invert_active_flag' => 'LDAP Invert Active Flag',
|
||||
'ldap_invert_active_flag_help' => 'If enabled: when the value returned by LDAP Active Flag is <code>0</code> or <code>false</code> the user account will be active.',
|
||||
'ldap_emp_num' => 'LDAP Employee Number',
|
||||
'ldap_email' => 'LDAP Email',
|
||||
'ldap_test' => 'Test LDAP',
|
||||
@@ -132,6 +136,7 @@ return [
|
||||
'login_user_agent' => 'User Agent',
|
||||
'login_help' => 'List of attempted logins',
|
||||
'login_note' => 'Login Note',
|
||||
'login_note_placeholder' => "If you do not have a login or have found a device belonging to this company, please call technical support at 888-555-1212. Thank you.",
|
||||
'login_note_help' => 'Optionally include a few sentences on your login screen, for example to assist people who have found a lost or stolen device. This field accepts <a href="https://help.github.com/articles/github-flavored-markdown/">Github flavored markdown</a>',
|
||||
'login_remote_user_text' => 'Remote User login options',
|
||||
'login_remote_user_enabled_text' => 'Enable Login with Remote User Header',
|
||||
@@ -345,6 +350,8 @@ return [
|
||||
'setup_migration_create_user' => 'Next: Create User',
|
||||
'ldap_settings_link' => 'LDAP Settings Page',
|
||||
'slack_test' => 'Test <i class="fab fa-slack"></i> Integration',
|
||||
'status_label_name' => 'Status Label Name',
|
||||
'super_admin_only' => 'Super Admin Only',
|
||||
'label2_enable' => 'New Label Engine',
|
||||
'label2_enable_help' => 'Switch to the new label engine. <b>Note: You will need to save this setting before setting others.</b>',
|
||||
'label2_template' => 'Template',
|
||||
@@ -378,6 +385,7 @@ return [
|
||||
'database_driver' => 'Database Driver',
|
||||
'bs_table_storage' => 'Table Storage',
|
||||
'timezone' => 'Timezone',
|
||||
'test_mail' => 'Test Mail',
|
||||
'profile_edit' => 'Edit Profile',
|
||||
'profile_edit_help' => 'Allow users to edit their own profiles.',
|
||||
'default_avatar' => 'Upload custom default avatar',
|
||||
@@ -387,6 +395,15 @@ return [
|
||||
'due_checkin_days' => 'Due For Checkin Warning',
|
||||
'due_checkin_days_help' => 'How many days before the expected checkin of an asset should it be listed in the "Due for checkin" page?',
|
||||
'no_groups' => 'No groups have been created yet. Visit <code>Admin Settings > Permission Groups</code> to add one.',
|
||||
'text' => 'Text',
|
||||
|
||||
|
||||
'logo_option_types' => [
|
||||
'text' => 'Text',
|
||||
'logo' => 'Logo',
|
||||
'logo_and_text' => 'Logo and Text',
|
||||
],
|
||||
|
||||
|
||||
|
||||
/* Keywords for settings overview help */
|
||||
|
||||
@@ -599,5 +599,6 @@ return [
|
||||
'generic_model_not_found' => 'That :model was not found or you do not have permission to access it',
|
||||
'deleted_models' => 'Deleted Asset Models',
|
||||
'deleted_users' => 'Deleted Users',
|
||||
'cost_each' => ':amount each',
|
||||
|
||||
];
|
||||
|
||||
@@ -26,9 +26,9 @@
|
||||
<livewire:category-edit-form
|
||||
:default-eula-text="$snipeSettings->default_eula_text"
|
||||
:eula-text="old('eula_text', $item->eula_text)"
|
||||
:require-acceptance="old('require_acceptance', $item->require_acceptance)"
|
||||
:send-check-in-email="old('checkin_email', $item->checkin_email)"
|
||||
:use-default-eula="old('use_default_eula', $item->use_default_eula)"
|
||||
:require-acceptance="(bool) old('require_acceptance', $item->require_acceptance)"
|
||||
:send-check-in-email="(bool) old('checkin_email', $item->checkin_email)"
|
||||
:use-default-eula="(bool) old('use_default_eula', $item->use_default_eula)"
|
||||
/>
|
||||
|
||||
@include ('partials.forms.edit.image-upload', ['image_path' => app('categories_upload_path')])
|
||||
|
||||
@@ -1211,7 +1211,7 @@
|
||||
<a href="{{ route('components.show', $component->id) }}">{{ $component->name }}</a>
|
||||
</td>
|
||||
<td>{{ $component->pivot->assigned_qty }}</td>
|
||||
<td>{{ Helper::formatCurrencyOutput($component->purchase_cost) }} each</td>
|
||||
<td>{{ trans('general.cost_each', ['amount' => Helper::formatCurrencyOutput($component->purchase_cost)]) }} </td>
|
||||
<td>{{ $component->serial }}</td>
|
||||
<td>
|
||||
<a href="{{ route('components.checkin.show', $component->pivot->id) }}" class="btn btn-sm bg-purple hidden-print" data-tooltip="true">{{ trans('general.checkin') }}</a>
|
||||
|
||||
@@ -23,12 +23,25 @@
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
@if ($defaultEulaText!='')
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('use_default_eula', '1', $useDefaultEula, ['wire:model.live' => 'useDefaultEula', 'aria-label'=>'use_default_eula']) }}
|
||||
<input
|
||||
type="checkbox"
|
||||
name="use_default_eula"
|
||||
value="1"
|
||||
wire:model.live="useDefaultEula"
|
||||
aria-label="use_default_eula"
|
||||
/>
|
||||
<span>{!! trans('admin/categories/general.use_default_eula') !!}</span>
|
||||
</label>
|
||||
@else
|
||||
<label class="form-control form-control--disabled">
|
||||
{{ Form::checkbox('use_default_eula', '0', $useDefaultEula, ['wire:model.live' => 'useDefaultEula', 'class'=>'disabled','disabled' => 'disabled', 'aria-label'=>'use_default_eula']) }}
|
||||
<input
|
||||
type="checkbox"
|
||||
name="use_default_eula"
|
||||
value="0"
|
||||
wire:model.live="useDefaultEula"
|
||||
aria-label="use_default_eula"
|
||||
disabled
|
||||
/>
|
||||
<span>{!! trans('admin/categories/general.use_default_eula_disabled') !!}</span>
|
||||
</label>
|
||||
@endif
|
||||
@@ -39,7 +52,13 @@
|
||||
<div class="form-group">
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('require_acceptance', '1', $requireAcceptance, ['wire:model.live' => 'requireAcceptance', 'aria-label'=>'require_acceptance']) }}
|
||||
<input
|
||||
type="checkbox"
|
||||
name="require_acceptance"
|
||||
value="1"
|
||||
wire:model.live="requireAcceptance"
|
||||
aria-label="require_acceptance"
|
||||
/>
|
||||
{{ trans('admin/categories/general.require_acceptance') }}
|
||||
</label>
|
||||
</div>
|
||||
@@ -49,7 +68,14 @@
|
||||
<div class="form-group">
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('checkin_email', '1', $sendCheckInEmail, ['wire:model.live' => 'sendCheckInEmail', 'aria-label'=>'checkin_email', 'disabled' => $this->sendCheckInEmailDisabled]) }}
|
||||
<input
|
||||
type="checkbox"
|
||||
name="checkin_email"
|
||||
value="1"
|
||||
wire:model.live="sendCheckInEmail"
|
||||
aria-label="checkin_email"
|
||||
@disabled($this->sendCheckInEmailDisabled)
|
||||
/>
|
||||
{{ trans('admin/categories/general.checkin_email') }}
|
||||
</label>
|
||||
@if ($this->shouldDisplayEmailMessage)
|
||||
|
||||
@@ -10,8 +10,15 @@
|
||||
<div class="col-md-3">
|
||||
@if ($fieldset_id)
|
||||
<label class="form-control">
|
||||
|
||||
{{ Form::checkbox('add_default_values', 1, old('add_default_values', $add_default_values), ['data-livewire-component' => $this->getId(), 'id' => 'add_default_values', 'wire:model.live' => 'add_default_values', 'disabled' => $this->fields->isEmpty()]) }}
|
||||
<input
|
||||
type="checkbox"
|
||||
name="add_default_values"
|
||||
value="1"
|
||||
id="add_default_values"
|
||||
wire:model.live="add_default_values"
|
||||
data-livewire-component="{{ $this->getId() }}"
|
||||
@disabled($this->fields->isEmpty())
|
||||
/>
|
||||
{{ trans('admin/models/general.add_default_values') }}
|
||||
</label>
|
||||
@endif
|
||||
|
||||
@@ -29,7 +29,16 @@
|
||||
data_export_options = $(this).attr('data-export-options');
|
||||
export_options = data_export_options ? JSON.parse(data_export_options) : {};
|
||||
export_options['htmlContent'] = false; // this is already the default; but let's be explicit about it
|
||||
export_options['jspdf']= {"orientation": "l"};
|
||||
export_options['jspdf'] = {
|
||||
"orientation": "l",
|
||||
"autotable": {
|
||||
"styles": {
|
||||
overflow: 'linebreak'
|
||||
},
|
||||
tableWidth: 'wrap'
|
||||
}
|
||||
};
|
||||
// tableWidth: 'wrap',
|
||||
// the following callback method is necessary to prevent XSS vulnerabilities
|
||||
// (this is taken from Bootstrap Tables's default wrapper around jQuery Table Export)
|
||||
export_options['onCellHtmlData'] = function (cell, rowIndex, colIndex, htmlData) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<div class="form-group {{ $errors->has('email') ? ' has-error' : '' }}">
|
||||
<label for="email" class="col-md-3 col-xs-12 control-label">{{ trans('admin/suppliers/table.email') }}</label>
|
||||
<div class="col-md-8 col-xs-12">
|
||||
<input type="text" name="email" id="email" value="{{ old('email', ($item->email ?? $user->email)) }}" class="form-control" maxlength="191" style="width:100%; display:flex;">
|
||||
<input type="text" name="email" id="email" value="{{ old('email', $item->email) }}" class="form-control" maxlength="191" style="width:100%; display:flex;">
|
||||
{!! $errors->first('email', '<span class="alert-msg" aria-hidden="true"><i class="fas fa-times" aria-hidden="true"></i> :message</span>') !!}
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -68,7 +68,7 @@
|
||||
@foreach ($assetsForReport as $item)
|
||||
@if ($item['assetItem'])
|
||||
<tr @if($item['acceptance']->trashed()) style="text-decoration: line-through" @endif>
|
||||
<td>{{ $item['acceptance']->created_at }}</td>
|
||||
<td>{{ Helper::getFormattedDateObject($item['acceptance']->created_at, 'datetime', false) }}</td>
|
||||
<td>{{ ($item['assetItem']->company) ? $item['assetItem']->company->name : '' }}</td>
|
||||
<td>{!! $item['assetItem']->model->category->present()->nameUrl() !!}</td>
|
||||
<td>{!! $item['assetItem']->present()->modelUrl() !!}</td>
|
||||
@@ -79,13 +79,18 @@
|
||||
<nobr>
|
||||
@if(!$item['acceptance']->trashed())
|
||||
<form method="post" class="white-space: nowrap;" action="{{ route('reports/unaccepted_assets_sent_reminder') }}">
|
||||
@if ($item['acceptance']->assignedTo)
|
||||
@if (($item['acceptance']->assignedTo) && ($item['acceptance']->assignedTo->email))
|
||||
@csrf
|
||||
<input type="hidden" name="acceptance_id" value="{{ $item['acceptance']->id }}">
|
||||
<button class="btn btn-sm btn-warning" data-tooltip="true" data-title="{{ trans('admin/reports/general.send_reminder') }}">
|
||||
<i class="fa fa-repeat" aria-hidden="true"></i>
|
||||
</button>
|
||||
|
||||
@else
|
||||
<span data-tooltip="true" data-title="{{ trans('admin/reports/general.cannot_send_reminder') }}">
|
||||
<a class="btn btn-sm btn-warning disabled" href="#">
|
||||
<i class="fa fa-repeat" aria-hidden="true"></i>
|
||||
</a>
|
||||
</span>
|
||||
@endif
|
||||
<a href="{{ route('reports/unaccepted_assets_delete', ['acceptanceId' => $item['acceptance']->id]) }}" class="btn btn-sm btn-danger delete-asset" data-tooltip="true" data-toggle="modal" data-content="{{ trans('general.delete_confirm', ['item' =>trans('admin/reports/general.acceptance_request')]) }}" data-title="{{ trans('general.delete') }}" onClick="return false;"><i class="fa fa-trash"></i></a>
|
||||
</form>
|
||||
|
||||
@@ -68,7 +68,9 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
|
||||
@php
|
||||
$optionTypes = trans('admin/settings/general.logo_option_types');
|
||||
@endphp
|
||||
|
||||
<!-- Branding -->
|
||||
<div class="form-group {{ $errors->has('brand') ? 'error' : '' }}">
|
||||
@@ -76,8 +78,13 @@
|
||||
<label for="brand">{{ trans('admin/settings/general.web_brand') }}</label>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{!! Form::select('brand', array('1'=>'Text','2'=>'Logo','3'=>'Logo + Text'), old('brand', $setting->brand), array('class' => 'form-control select2', 'style'=>'width: 150px ;')) !!}
|
||||
{!! $errors->first('brand', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
<select name="brand" id="brand" class="form-control select2 minimumResultsForSearch" style="width: 150px;">
|
||||
@foreach($optionTypes as $value => $label)
|
||||
<option value="{{ $value }}" {{ old('brand', $setting->brand) == $value ? 'selected' : '' }}>
|
||||
{{ $label }}
|
||||
</option>
|
||||
@endforeach
|
||||
</select>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -135,7 +142,7 @@
|
||||
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('restore_default_avatar', '1', old('restore_default_avatar', $setting->restore_default_avatar)) }}
|
||||
<input type="checkbox" name="restore_default_avatar" value="1" @checked(old('restore_default_avatar', $setting->restore_default_avatar)) />
|
||||
<span>{!! trans('admin/settings/general.restore_default_avatar', ['default_avatar'=> Storage::disk('public')->url('default.png')]) !!}</span>
|
||||
</label>
|
||||
<p class="help-block">
|
||||
@@ -152,7 +159,7 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('load_remote', '1', old('load_remote', $setting->load_remote)) }}
|
||||
<input type="checkbox" name="load_remote" value="1" @checked(old('load_remote', $setting->load_remote)) />
|
||||
{{ trans('general.yes') }}
|
||||
{!! $errors->first('load_remote', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</label>
|
||||
@@ -172,7 +179,7 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('logo_print_assets', '1', old('logo_print_assets', $setting->logo_print_assets),array('aria-label'=>'logo_print_assets')) }}
|
||||
<input type="checkbox" name="logo_print_assets" value="1" @checked(old('logo_print_assets', $setting->logo_print_assets)) aria-label="logo_print_assets"/>
|
||||
{{ trans('admin/settings/general.logo_print_assets_help') }}
|
||||
</label>
|
||||
|
||||
@@ -187,7 +194,7 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('show_url_in_emails', '1', old('show_url_in_emails', $setting->show_url_in_emails),array('aria-label'=>'show_url_in_emails')) }}
|
||||
<input type="checkbox" name="show_url_in_emails" value="1" @checked(old('show_url_in_emails', $setting->show_url_in_emails)) aria-label="show_url_in_emails" />
|
||||
{{ trans('general.yes') }}
|
||||
</label>
|
||||
<p class="help-block">{{ trans('admin/settings/general.show_url_in_emails_help_text') }}</p>
|
||||
@@ -228,7 +235,7 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('allow_user_skin', '1', old('allow_user_skin', $setting->allow_user_skin)) }}
|
||||
<input type="checkbox" name="allow_user_skin" value="1" @checked(old('allow_user_skin', $setting->allow_user_skin))/>
|
||||
{{ trans('general.yes') }}
|
||||
</label>
|
||||
<p class="help-block">{{ trans('admin/settings/general.allow_user_skin_help_text') }}</p>
|
||||
@@ -272,10 +279,10 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
@if (config('app.lock_passwords')===true)
|
||||
{!! Form::select('support_footer', array('on'=>'Enabled','off'=>'Disabled','admin'=>'Superadmin Only'), old('support_footer', $setting->support_footer), ['class' => 'form-control select2 disabled', 'style'=>'width: 150px ;', 'disabled' => 'disabled']) !!}
|
||||
{!! Form::select('support_footer', array('on'=>trans('admin/settings/general.enabled'),'off'=>trans('admin/settings/general.two_factor_disabled'),'admin'=>trans('admin/settings/general.super_admin_only')), old('support_footer', $setting->support_footer), ['class' => 'form-control select2 disabled', 'style'=>'width: 150px ;', 'disabled' => 'disabled']) !!}
|
||||
<p class="text-warning"><i class="fas fa-lock"></i> {{ trans('general.feature_disabled') }}</p>
|
||||
@else
|
||||
{!! Form::select('support_footer', array('on'=>'Enabled','off'=>'Disabled','admin'=>'Superadmin Only'), old('support_footer', $setting->support_footer), array('class' => 'form-control select2', 'style'=>'width: 150px ;')) !!}
|
||||
{!! Form::select('support_footer', array('on'=>trans('admin/settings/general.enabled'),'off'=>trans('admin/settings/general.two_factor_disabled'),'admin'=>trans('admin/settings/general.super_admin_only')), old('support_footer', $setting->support_footer), array('class' => 'form-control select2', 'style'=>'width: 150px ;')) !!}
|
||||
@endif
|
||||
|
||||
|
||||
@@ -291,10 +298,10 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
@if (config('app.lock_passwords')===true)
|
||||
{!! Form::select('version_footer', array('on'=>'Enabled','off'=>'Disabled','admin'=>'Superadmin Only'), old('version_footer', $setting->version_footer), ['class' => 'form-control select2 disabled', 'style'=>'width: 150px ;', 'disabled' => 'disabled']) !!}
|
||||
{!! Form::select('version_footer', array('on'=>trans('admin/settings/general.enabled'),'off'=>trans('admin/settings/general.two_factor_disabled'),'admin'=>trans('admin/settings/general.super_admin_only')), old('version_footer', $setting->version_footer), ['class' => 'form-control select2 disabled', 'style'=>'width: 150px ;', 'disabled' => 'disabled']) !!}
|
||||
<p class="text-warning"><i class="fas fa-lock"></i> {{ trans('general.feature_disabled') }}</p>
|
||||
@else
|
||||
{!! Form::select('version_footer', array('on'=>'Enabled','off'=>'Disabled','admin'=>'Superadmin Only'), old('version_footer', $setting->version_footer), array('class' => 'form-control select2', 'style'=>'width: 150px ;')) !!}
|
||||
{!! Form::select('version_footer', array('on'=>trans('admin/settings/general.enabled'),'off'=>trans('admin/settings/general.two_factor_disabled'),'admin'=>trans('admin/settings/general.super_admin_only')), old('version_footer', $setting->version_footer), array('class' => 'form-control select2', 'style'=>'width: 150px ;')) !!}
|
||||
@endif
|
||||
|
||||
<p class="help-block">{{ trans('admin/settings/general.version_footer_help') }}</p>
|
||||
|
||||
@@ -45,7 +45,7 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('full_multiple_companies_support', '1', old('full_multiple_companies_support', $setting->full_multiple_companies_support),array('aria-label'=>'full_multiple_companies_support')) }}
|
||||
<input type="checkbox" name="full_multiple_companies_support" value="1" @checked(old('full_multiple_companies_support', $setting->full_multiple_companies_support)) aria-label="full_multiple_companies_support" />
|
||||
{{ trans('admin/settings/general.full_multiple_companies_support_text') }}
|
||||
</label>
|
||||
{!! $errors->first('full_multiple_companies_support', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
@@ -64,7 +64,7 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('require_accept_signature', '1', old('require_accept_signature', $setting->require_accept_signature)) }}
|
||||
<input type="checkbox" name="require_accept_signature" value="1" @checked(old('require_accept_signature', $setting->require_accept_signature)) />
|
||||
{{ trans('general.yes') }}
|
||||
</label>
|
||||
{!! $errors->first('require_accept_signature', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
@@ -136,7 +136,7 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('show_images_in_email', '1', old('show_images_in_email', $setting->show_images_in_email)) }}
|
||||
<input type="checkbox" name="show_images_in_email" value="1" @checked(old('show_images_in_email', $setting->show_images_in_email)) />
|
||||
{{ trans('general.yes') }}
|
||||
{!! $errors->first('show_images_in_email', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</label>
|
||||
@@ -152,7 +152,7 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('unique_serial', '1', old('unique_serial', $setting->unique_serial),array('class' => 'minimal')) }}
|
||||
<input type="checkbox" name="unique_serial" value="1" @checked(old('unique_serial', $setting->unique_serial)) />
|
||||
{{ trans('general.yes') }}
|
||||
{!! $errors->first('unique_serial', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
</label>
|
||||
@@ -245,11 +245,11 @@
|
||||
<div class="col-md-9">
|
||||
@if (config('app.lock_passwords'))
|
||||
|
||||
<textarea class="form-control disabled" name="login_note" placeholder="If you do not have a login or have found a device belonging to this company, please call technical support at 888-555-1212. Thank you." rows="2" aria-label="login_note" readonly>{{ old('login_note', $setting->login_note) }}</textarea>
|
||||
<textarea class="form-control disabled" name="login_note" placeholder="{{trans('admin/settings/general.login_note_placeholder')}}" rows="2" aria-label="login_note" readonly>{{ old('login_note', $setting->login_note) }}</textarea>
|
||||
{!! $errors->first('login_note', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
<p class="text-warning"><i class="fas fa-lock"></i> {{ trans('general.feature_disabled') }}</p>
|
||||
@else
|
||||
<textarea class="form-control" name="login_note" aria-label="login_note" placeholder="If you do not have a login or have found a device belonging to this company, please call technical support at 888-555-1212. Thank you." rows="2">{{ old('login_note', $setting->login_note) }}</textarea>
|
||||
<textarea class="form-control" name="login_note" aria-label="login_note" placeholder="{{trans('admin/settings/general.login_note_placeholder')}}" rows="2">{{ old('login_note', $setting->login_note) }}</textarea>
|
||||
{!! $errors->first('login_note', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
@endif
|
||||
<p class="help-block">{!! trans('admin/settings/general.login_note_help') !!}</p>
|
||||
@@ -259,7 +259,7 @@
|
||||
<!-- Mail test -->
|
||||
<div class="form-group">
|
||||
<div class="col-md-3">
|
||||
<label for="login_note">Test Mail</label>
|
||||
<label for="login_note">{{trans('admin/settings/general.test_mail')}}</label>
|
||||
</div>
|
||||
<div class="col-md-9" id="mailtestrow">
|
||||
<a class="btn btn-default btn-sm pull-left" id="mailtest" style="margin-right: 10px;">
|
||||
@@ -311,7 +311,7 @@
|
||||
<div class="col-md-9">
|
||||
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('show_archived_in_list', '1', old('show_archived_in_list', $setting->show_archived_in_list),array('aria-label'=>'show_archived_in_list')) }}
|
||||
<input type="checkbox" name="show_archived_in_list" value="1" @checked(old('show_archived_in_list', $setting->show_archived_in_list)) aria-label="show_archived_in_list" />
|
||||
{{ trans('admin/settings/general.show_archived_in_list_text') }}
|
||||
</label>
|
||||
{!! $errors->first('show_archived_in_list', '<span class="alert-msg" aria-hidden="true">:message</span>') !!}
|
||||
@@ -325,7 +325,7 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('show_assigned_assets', '1', old('show_assigned_assets', $setting->show_assigned_assets),array('class' => 'minimal')) }}
|
||||
<input type="checkbox" name="show_assigned_assets" value="1" @checked(old('show_assigned_assets', $setting->show_assigned_assets)) />
|
||||
{{ trans('general.yes') }}
|
||||
</label>
|
||||
<p class="help-block">{{ trans('admin/settings/general.show_assigned_assets_help') }}</p>
|
||||
@@ -340,15 +340,19 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('show_in_model_list[]', 'image', old('show_in_model_list', $snipeSettings->modellistCheckedValue('image')),array('class' => 'minimal', 'aria-label'=>'show_in_model_list' )) }} {{ trans('general.image') }}
|
||||
<input type="checkbox" name="show_in_model_list[]" value="image" @checked(old('show_in_model_list', $snipeSettings->modellistCheckedValue('image'))) aria-label="show_in_model_list"/>
|
||||
{{ trans('general.image') }}
|
||||
</label>
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('show_in_model_list[]', 'category', old('show_in_model_list', $snipeSettings->modellistCheckedValue('category')),array('class' => 'minimal', 'aria-label'=>'show_in_model_list' )) }} {{ trans('general.category') }}
|
||||
<input type="checkbox" name="show_in_model_list[]" value="category" @checked(old('show_in_model_list', $snipeSettings->modellistCheckedValue('category'))) aria-label="show_in_model_list"/>
|
||||
{{ trans('general.category') }}
|
||||
</label>
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('show_in_model_list[]', 'manufacturer', old('show_in_model_list', $snipeSettings->modellistCheckedValue('manufacturer')),array('class' => 'minimal', 'aria-label'=>'show_in_model_list' )) }} {{ trans('general.manufacturer') }} </label>
|
||||
<input type="checkbox" name="show_in_model_list[]" value="manufacturer" @checked(old('show_in_model_list', $snipeSettings->modellistCheckedValue('manufacturer'))) aria-label="show_in_model_list"/>
|
||||
{{ trans('general.manufacturer') }} </label>
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('show_in_model_list[]', 'model_number', old('show_in_model_list', $snipeSettings->modellistCheckedValue('model_number')),array('class' => 'minimal', 'aria-label'=>'show_in_model_list' )) }} {{ trans('general.model_no') }}
|
||||
<input type="checkbox" name="show_in_model_list[]" value="model_number" @checked(old('show_in_model_list', $snipeSettings->modellistCheckedValue('model_number'))) aria-label="show_in_model_list"/>
|
||||
{{ trans('general.model_no') }}
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
@@ -370,13 +374,13 @@
|
||||
<!-- Depreciation method -->
|
||||
<div class="form-group {{ $errors->has('depreciation_method') ? 'error' : '' }}">
|
||||
<div class="col-md-3">
|
||||
<label for="depreciation_method">{{ trans('Depreciation method') }}</label>
|
||||
<label for="depreciation_method">{{ trans('admin/depreciations/general.depreciation_method') }}</label>
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
{{ Form::select('depreciation_method', array(
|
||||
'default' => 'Linear (default)',
|
||||
'half_1' => 'Half-year convention, always applied',
|
||||
'half_2' => 'Half-year convention, applied with condition',
|
||||
'default' => trans('admin/depreciations/general.linear_depreciation'),
|
||||
'half_1' => trans('admin/depreciations/general.half_1'),
|
||||
'half_2' => trans('admin/depreciations/general.half_2'),
|
||||
), old('username_format', $setting->depreciation_method), ['class' =>'select2', 'style' => 'width: 80%']) }}
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -144,7 +144,7 @@
|
||||
<div class="form-group">
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('alt_barcode_enabled', '1', old('alt_barcode_enabled', $setting->alt_barcode_enabled),array( 'aria-label'=>'alt_barcode_enabled')) }}
|
||||
<input type="checkbox" name="alt_barcode_enabled" value="1" @checked(old('alt_barcode_enabled', $setting->alt_barcode_enabled)) aria-label="alt_barcode_enabled"/>
|
||||
{{ trans('admin/settings/general.display_alt_barcode') }}
|
||||
</label>
|
||||
</div>
|
||||
@@ -189,7 +189,7 @@
|
||||
<div class="form-group">
|
||||
<div class="col-md-9 col-md-offset-3">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('qr_code', '1', old('qr_code', $setting->qr_code),array('aria-label'=>'qr_code')) }}
|
||||
<input type="checkbox" name="qr_code" value="1" @checked(old('qr_code', $setting->qr_code)) aria-label="qr_code" />
|
||||
{{ trans('admin/settings/general.display_qr') }}
|
||||
</label>
|
||||
</div>
|
||||
@@ -480,23 +480,23 @@
|
||||
</div>
|
||||
<div class="col-md-9">
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('labels_display_name', '1', old('labels_display_name', $setting->labels_display_name),['class' => 'minimal', 'aria-label'=>'labels_display_name']) }}
|
||||
<input type="checkbox" name="labels_display_name" value="1" @checked(old('labels_display_name', $setting->labels_display_name)) aria-label="labels_display_name" />
|
||||
{{ trans('admin/hardware/form.name') }}
|
||||
</label>
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('labels_display_serial', '1', old('labels_display_serial', $setting->labels_display_serial),['class' => 'minimal', 'aria-label'=>'labels_display_serial']) }}
|
||||
<input type="checkbox" name="labels_display_serial" value="1" @checked(old('labels_display_serial', $setting->labels_display_serial)) aria-label="labels_display_serial" />
|
||||
{{ trans('admin/hardware/form.serial') }}
|
||||
</label>
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('labels_display_tag', '1', old('labels_display_tag', $setting->labels_display_tag),['class' => 'minimal', 'aria-label'=>'labels_display_tag']) }}
|
||||
<input type="checkbox" name="labels_display_tag" value="1" @checked(old('labels_display_tag', $setting->labels_display_tag)) aria-label="labels_display_tag" />
|
||||
{{ trans('admin/hardware/form.tag') }}
|
||||
</label>
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('labels_display_model', '1', old('labels_display_model', $setting->labels_display_model),['class' => 'minimal', 'aria-label'=>'labels_display_model']) }}
|
||||
<input type="checkbox" name="labels_display_model" value="1" @checked(old('labels_display_model', $setting->labels_display_model)) aria-label="labels_display_model" />
|
||||
{{ trans('admin/hardware/form.model') }}
|
||||
</label>
|
||||
<label class="form-control">
|
||||
{{ Form::checkbox('labels_display_company_name', '1', old('labels_display_company_name', $setting->labels_display_company_name),['class' => 'minimal', 'aria-label'=>'labels_display_company_name']) }}
|
||||
<input type="checkbox" name="labels_display_company_name" value="1" @checked(old('labels_display_company_name', $setting->labels_display_company_name)) aria-label="labels_display_company_name"/>
|
||||
{{ trans('admin/companies/table.name') }}
|
||||
</label>
|
||||
</div> <!--/.col-md-9-->
|
||||
|
||||
@@ -554,6 +554,32 @@
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- LDAP invert active flag -->
|
||||
<div class="form-group">
|
||||
<div class="col-md-3">
|
||||
{{ Form::label('ldap_invert_active_flag', trans('admin/settings/general.ldap_invert_active_flag')) }}
|
||||
</div>
|
||||
<div class="col-md-8">
|
||||
<label class="form-control">
|
||||
<input type="checkbox" name="ldap_invert_active_flag" value="1" id="ldap_invert_active_flag" @checked(old('ldap_invert_active_flag', $setting->ldap_invert_active_flag)) />
|
||||
<p class="help-block">{!! trans('admin/settings/general.ldap_invert_active_flag_help') !!}</p>
|
||||
</label>
|
||||
@error('ldap_invert_active_flag')
|
||||
<span class="alert-msg">
|
||||
<x-icon type="x" />
|
||||
{{ $message }}
|
||||
</span>
|
||||
@enderror
|
||||
|
||||
@if (config('app.lock_passwords')===true)
|
||||
<p class="text-warning">
|
||||
<x-icon type="locked" />
|
||||
{{ trans('general.feature_disabled') }}
|
||||
</p>
|
||||
@endif
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- LDAP emp number -->
|
||||
<div class="form-group {{ $errors->has('ldap_emp_num') ? 'error' : '' }}">
|
||||
<div class="col-md-3">
|
||||
|
||||
@@ -45,4 +45,24 @@ class ImportTest extends TestCase
|
||||
]);
|
||||
$this->assertEquals($evil_string, $results->json()['files'][0]['first_row'][0]);
|
||||
}
|
||||
|
||||
public function testStoreInternationalAssetMisparse(): void
|
||||
{
|
||||
$evil_maker = function ($arr) {
|
||||
$results = '';
|
||||
foreach ($arr as $thing) {
|
||||
$results .= chr($thing);
|
||||
}
|
||||
return $results;
|
||||
};
|
||||
|
||||
// 0xC0 makes it 'not unicode', and 0xFF makes it 'likely WINDOWS-1251', and 0x98 at the end makes it 'not-valid-Windows-1251'
|
||||
$evil_content = $evil_maker([0xC0, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x01, 0x02, 0x03, 0x98]);
|
||||
|
||||
$this->actingAsForApi(User::factory()->superuser()->create());
|
||||
$results = $this->post(route('api.imports.store'), ['files' => [UploadedFile::fake()->createWithContent("myname.csv", $evil_content)]])
|
||||
->assertStatus(422)
|
||||
->assertStatusMessageIs('error')
|
||||
->assertMessagesAre(trans('admin/hardware/message.import.transliterate_failure', ["encoding" => "windows-1251"]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,7 +10,10 @@ class CategoryEditFormTest extends TestCase
|
||||
{
|
||||
public function testTheComponentCanRender()
|
||||
{
|
||||
Livewire::test(CategoryEditForm::class)->assertStatus(200);
|
||||
Livewire::test(CategoryEditForm::class, [
|
||||
'sendCheckInEmail' => true,
|
||||
'useDefaultEula' => true,
|
||||
])->assertStatus(200);
|
||||
}
|
||||
|
||||
public function testSendEmailCheckboxIsCheckedOnLoadWhenSendEmailIsExistingSetting()
|
||||
|
||||
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace Tests\Feature\Notifications\Email;
|
||||
|
||||
use App\Mail\CheckoutAssetMail;
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use PHPUnit\Framework\Attributes\DataProvider;
|
||||
use Tests\TestCase;
|
||||
|
||||
class AssetAcceptanceReminderTest extends TestCase
|
||||
{
|
||||
protected function setUp(): void
|
||||
{
|
||||
parent::setUp();
|
||||
|
||||
Mail::fake();
|
||||
}
|
||||
|
||||
public function testMustHavePermissionToSendReminder()
|
||||
{
|
||||
$checkoutAcceptance = CheckoutAcceptance::factory()->pending()->create();
|
||||
$userWithoutPermission = User::factory()->create();
|
||||
|
||||
$this->actingAs($userWithoutPermission)
|
||||
->post($this->routeFor($checkoutAcceptance))
|
||||
->assertForbidden();
|
||||
|
||||
Mail::assertNotSent(CheckoutAssetMail::class);
|
||||
}
|
||||
|
||||
public function testReminderNotSentIfAcceptanceDoesNotExist()
|
||||
{
|
||||
$this->actingAs(User::factory()->canViewReports()->create())
|
||||
->post(route('reports/unaccepted_assets_sent_reminder', [
|
||||
'acceptance_id' => 999999,
|
||||
]));
|
||||
|
||||
Mail::assertNotSent(CheckoutAssetMail::class);
|
||||
}
|
||||
|
||||
public function testReminderNotSentIfAcceptanceAlreadyAccepted()
|
||||
{
|
||||
$checkoutAcceptanceAlreadyAccepted = CheckoutAcceptance::factory()->accepted()->create();
|
||||
|
||||
$this->actingAs(User::factory()->canViewReports()->create())
|
||||
->post($this->routeFor($checkoutAcceptanceAlreadyAccepted));
|
||||
|
||||
Mail::assertNotSent(CheckoutAssetMail::class);
|
||||
}
|
||||
|
||||
public static function CheckoutAcceptancesToUsersWithoutEmailAddresses()
|
||||
{
|
||||
yield 'User with null email address' => [
|
||||
function () {
|
||||
return CheckoutAcceptance::factory()
|
||||
->pending()
|
||||
->forAssignedTo(['email' => null])
|
||||
->create();
|
||||
}
|
||||
];
|
||||
|
||||
yield 'User with empty string email address' => [
|
||||
function () {
|
||||
return CheckoutAcceptance::factory()
|
||||
->pending()
|
||||
->forAssignedTo(['email' => ''])
|
||||
->create();
|
||||
}
|
||||
];
|
||||
}
|
||||
|
||||
#[DataProvider('CheckoutAcceptancesToUsersWithoutEmailAddresses')]
|
||||
public function testUserWithoutEmailAddressHandledGracefully($callback)
|
||||
{
|
||||
$checkoutAcceptance = $callback();
|
||||
|
||||
$this->actingAs(User::factory()->canViewReports()->create())
|
||||
->post($this->routeFor($checkoutAcceptance))
|
||||
// check we didn't crash...
|
||||
->assertRedirect();
|
||||
|
||||
Mail::assertNotSent(CheckoutAssetMail::class);
|
||||
}
|
||||
|
||||
public function testReminderIsSentToUser()
|
||||
{
|
||||
$checkoutAcceptance = CheckoutAcceptance::factory()->pending()->create();
|
||||
|
||||
$this->actingAs(User::factory()->canViewReports()->create())
|
||||
->post($this->routeFor($checkoutAcceptance))
|
||||
->assertRedirect(route('reports/unaccepted_assets'));
|
||||
|
||||
Mail::assertSent(CheckoutAssetMail::class, 1);
|
||||
Mail::assertSent(CheckoutAssetMail::class, function (CheckoutAssetMail $mail) use ($checkoutAcceptance) {
|
||||
return $mail->hasTo($checkoutAcceptance->assignedTo->email)
|
||||
&& $mail->hasSubject(trans('mail.unaccepted_asset_reminder'));
|
||||
});
|
||||
}
|
||||
|
||||
private function routeFor(CheckoutAcceptance $checkoutAcceptance): string
|
||||
{
|
||||
return route('reports/unaccepted_assets_sent_reminder', [
|
||||
'acceptance_id' => $checkoutAcceptance->id,
|
||||
]);
|
||||
}
|
||||
}
|
||||
@@ -4,6 +4,7 @@ namespace Tests\Feature\Notifications\Email;
|
||||
|
||||
use App\Mail\ExpiringAssetsMail;
|
||||
use App\Mail\ExpiringLicenseMail;
|
||||
use App\Mail\SendUpcomingAuditMail;
|
||||
use App\Models\Asset;
|
||||
use App\Models\License;
|
||||
use App\Models\Setting;
|
||||
@@ -88,4 +89,38 @@ class ExpiringAlertsNotificationTest extends TestCase
|
||||
return $mail->licenses->contains($expiredLicense) || $mail->licenses->contains($notExpiringLicense);
|
||||
});
|
||||
}
|
||||
|
||||
public function testAuditWarningThresholdEmailNotification()
|
||||
{
|
||||
$this->markIncompleteIfSqlite();
|
||||
Mail::fake();
|
||||
$this->settings->enableAlertEmail('admin@example.com');
|
||||
$this->settings->setAuditWarningDays(15);
|
||||
|
||||
$alert_email = Setting::first()->alert_email;
|
||||
|
||||
$upcomingAuditableAsset = Asset::factory()->create([
|
||||
'next_audit_date' => now()->addDays(14)->format('Y-m-d'),
|
||||
'deleted_at' => null,
|
||||
]);
|
||||
|
||||
$overDueForAuditableAsset = Asset::factory()->create([
|
||||
'next_audit_date' => now()->subDays(1)->format('Y-m-d'),
|
||||
'deleted_at' => null,
|
||||
]);
|
||||
|
||||
$notAuditableAsset = Asset::factory()->create([
|
||||
'next_audit_date' => now()->addDays(30)->format('Y-m-d'),
|
||||
'deleted_at' => null,
|
||||
]);
|
||||
|
||||
$this->artisan('snipeit:upcoming-audits')->assertExitCode(0);
|
||||
|
||||
Mail::assertSent(SendUpcomingAuditMail::class, function($mail) use ($alert_email, $upcomingAuditableAsset, $overDueForAuditableAsset) {
|
||||
return $mail->hasTo($alert_email) && ($mail->assets->contains($upcomingAuditableAsset) && $mail->assets->contains($overDueForAuditableAsset));
|
||||
});
|
||||
Mail::assertNotSent(SendUpcomingAuditMail::class, function($mail) use ($alert_email, $notAuditableAsset) {
|
||||
return $mail->hasTo($alert_email) && $mail->assets->contains($notAuditableAsset);
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -32,6 +32,12 @@ class Settings
|
||||
'alert_threshold' => $days,
|
||||
]);
|
||||
}
|
||||
public function setAuditWarningDays(int $days): Settings
|
||||
{
|
||||
return $this->update([
|
||||
'audit_warning_days' => $days,
|
||||
]);
|
||||
}
|
||||
public function disableAlertEmail(): Settings
|
||||
{
|
||||
return $this->update([
|
||||
|
||||
@@ -7,9 +7,7 @@ use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
use Carbon\Carbon;
|
||||
use App\Notifications\CheckoutAssetNotification;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Tests\TestCase;
|
||||
|
||||
class NotificationTest extends TestCase
|
||||
@@ -33,8 +31,8 @@ class NotificationTest extends TestCase
|
||||
|
||||
Mail::fake();
|
||||
$asset->checkOut($user, $admin->id);
|
||||
Mail::assertSent(CheckoutAssetMail::class, function ($mail) use ($user) {
|
||||
return $mail->hasTo($user->email);
|
||||
Mail::assertSent(CheckoutAssetMail::class, function (CheckoutAssetMail $mail) use ($user) {
|
||||
return $mail->hasTo($user->email) && $mail->hasSubject(trans('mail.Asset_Checkout_Notification'));
|
||||
});
|
||||
}
|
||||
public function testDefaultEulaIsSentWhenSetInCategory()
|
||||
|
||||
@@ -261,7 +261,7 @@ if ($env_bad !='') {
|
||||
|
||||
if(!$skip_php_checks){
|
||||
echo "\n\e[95m--------------------------------------------------------\n";
|
||||
echo "STEP 2: Checking PHP requirements: (Required PHP >=". $php_min_works. " - <".$php_max_wontwork.") \e[39m\n";
|
||||
echo "STEP 2: Checking PHP requirements: (Required PHP >=". $php_min_works. " - <".$php_max_wontwork.")\n";
|
||||
echo "--------------------------------------------------------\e[39m\n\n";
|
||||
|
||||
if ((version_compare(phpversion(), $php_min_works, '>=')) && (version_compare(phpversion(), $php_max_wontwork, '<'))) {
|
||||
@@ -540,7 +540,7 @@ echo "--------------------------------------------------------\e[39m\n\n";
|
||||
exec('php artisan down', $down_results, $return_code);
|
||||
echo '-- ' . implode("\n", $down_results) . "\n";
|
||||
if ($return_code > 0) {
|
||||
die("Something went wrong with downing your site. This can't be good. Please investigate the error. Aborting!n\n");
|
||||
die("Something went wrong with downing your site. This can't be good. Please investigate the error. Aborting!\n\n");
|
||||
}
|
||||
unset($return_code);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user