Compare commits
3 Commits
use-tcpdf-
...
smaller-ap
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a4ba070c84 | ||
|
|
2225c44b12 | ||
|
|
77c6392b16 |
@@ -4189,51 +4189,6 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "mckaygerhard",
|
||||
"name": "Герхард PICCORO Lenz McKAY ",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1571724?v=4",
|
||||
"profile": "https://github-readme-stats.vercel.app/api?username=mckaygerhard",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "FlorestanII",
|
||||
"name": "Johannes Pollitt",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/15015119?v=4",
|
||||
"profile": "https://github.com/FlorestanII",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "strobelm",
|
||||
"name": "Michael Strobel",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/14185442?v=4",
|
||||
"profile": "https://strobelm.de",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "nickwest",
|
||||
"name": "Nicky West",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/634790?v=4",
|
||||
"profile": "http://nickwest.me",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "akaspeh1",
|
||||
"name": "akaspeh1",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1347327?v=4",
|
||||
"profile": "https://github.com/akaspeh1",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -28,7 +28,6 @@ PUBLIC_FILESYSTEM_DISK=local_public
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=db
|
||||
DB_SOCKET=null
|
||||
DB_PORT='3306'
|
||||
DB_DATABASE=snipeit
|
||||
DB_USERNAME=snipeit
|
||||
@@ -169,7 +168,6 @@ AWS_DEFAULT_REGION=null
|
||||
LOGIN_MAX_ATTEMPTS=5
|
||||
LOGIN_LOCKOUT_DURATION=60
|
||||
RESET_PASSWORD_LINK_EXPIRES=900
|
||||
INVITE_PASSWORD_LINK_EXPIRES=1500
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: MISC
|
||||
|
||||
10
.env.example
10
.env.example
@@ -24,7 +24,6 @@ PUBLIC_FILESYSTEM_DISK=local_public
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_SOCKET=null
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=null
|
||||
DB_USERNAME=null
|
||||
@@ -175,7 +174,6 @@ LOGIN_AUTOCOMPLETE=false
|
||||
RESET_PASSWORD_LINK_EXPIRES=15
|
||||
PASSWORD_CONFIRM_TIMEOUT=10800
|
||||
PASSWORD_RESET_MAX_ATTEMPTS_PER_MIN=50
|
||||
INVITE_PASSWORD_LINK_EXPIRES=1500
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: MISC
|
||||
@@ -193,17 +191,11 @@ LDAP_TIME_LIM=600
|
||||
IMPORT_TIME_LIMIT=600
|
||||
IMPORT_MEMORY_LIMIT=500M
|
||||
REPORT_TIME_LIMIT=12000
|
||||
REQUIRE_SAML=false
|
||||
API_THROTTLE_PER_MINUTE=120
|
||||
CSV_ESCAPE_FORMULAS=true
|
||||
LIVEWIRE_URL_PREFIX=null
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SAML SETTINGS
|
||||
# --------------------------------------------
|
||||
REQUIRE_SAML=false
|
||||
SAML_KEY_SIZE=2048
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: HASHING
|
||||
# --------------------------------------------
|
||||
|
||||
2
.github/workflows/SA-codeql.yml
vendored
2
.github/workflows/SA-codeql.yml
vendored
@@ -26,7 +26,7 @@ jobs:
|
||||
language: [ 'javascript' ]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
4
.github/workflows/codacy-analysis.yml
vendored
4
.github/workflows/codacy-analysis.yml
vendored
@@ -32,11 +32,11 @@ jobs:
|
||||
steps:
|
||||
# Checkout the repository to the GitHub Actions runner
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Run Codacy Analysis CLI
|
||||
uses: codacy/codacy-analysis-cli-action@v4.4.7
|
||||
uses: codacy/codacy-analysis-cli-action@v4.4.5
|
||||
with:
|
||||
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
||||
# You can also omit the token and run the tools that support default configurations
|
||||
|
||||
2
.github/workflows/crowdin-upload.yml
vendored
2
.github/workflows/crowdin-upload.yml
vendored
@@ -9,7 +9,7 @@ jobs:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
- name: Crowdin push
|
||||
uses: crowdin/github-action@v2
|
||||
|
||||
2
.github/workflows/docker-alpine.yml
vendored
2
.github/workflows/docker-alpine.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
steps:
|
||||
# https://github.com/actions/checkout
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# https://github.com/docker/setup-buildx-action
|
||||
- name: Setup Docker Buildx
|
||||
|
||||
2
.github/workflows/docker-ubuntu.yml
vendored
2
.github/workflows/docker-ubuntu.yml
vendored
@@ -42,7 +42,7 @@ jobs:
|
||||
steps:
|
||||
# https://github.com/actions/checkout
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v5
|
||||
uses: actions/checkout@v4
|
||||
|
||||
# https://github.com/docker/setup-buildx-action
|
||||
- name: Setup Docker Buildx
|
||||
|
||||
2
.github/workflows/dockerhub-description.yml
vendored
2
.github/workflows/dockerhub-description.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
||||
dockerHubDescription:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Docker Hub Description
|
||||
uses: grokability/dockerhub-description@7ea9d275c7cdbe2b676a093a0308c50665e3b8b4
|
||||
|
||||
14
.github/workflows/tests-mysql.yml
vendored
14
.github/workflows/tests-mysql.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
coverage: none
|
||||
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
@@ -76,16 +76,4 @@ jobs:
|
||||
DB_DATABASE: snipeit
|
||||
DB_PORT: ${{ job.services.mysql.ports[3306] }}
|
||||
DB_USERNAME: root
|
||||
LOG_CHANNEL: single
|
||||
LOG_LEVEL: debug
|
||||
run: php artisan test
|
||||
|
||||
- name: Upload Laravel logs as artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: laravel-logs-php-${{ matrix.php-version }}-run-${{ github.run_attempt }}
|
||||
path: |
|
||||
storage/logs/*.log
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
|
||||
14
.github/workflows/tests-postgres.yml
vendored
14
.github/workflows/tests-postgres.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
coverage: none
|
||||
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
@@ -75,16 +75,4 @@ jobs:
|
||||
DB_PORT: ${{ job.services.postgresql.ports[5432] }}
|
||||
DB_USERNAME: snipeit
|
||||
DB_PASSWORD: password
|
||||
LOG_CHANNEL: single
|
||||
LOG_LEVEL: debug
|
||||
run: php artisan test
|
||||
|
||||
- name: Upload Laravel logs as artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: laravel-logs-php-${{ matrix.php-version }}-run-${{ github.run_attempt }}
|
||||
path: |
|
||||
storage/logs/*.log
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
|
||||
14
.github/workflows/tests-sqlite.yml
vendored
14
.github/workflows/tests-sqlite.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
coverage: none
|
||||
|
||||
- uses: actions/checkout@v5
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
@@ -61,16 +61,4 @@ jobs:
|
||||
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
||||
env:
|
||||
DB_CONNECTION: sqlite
|
||||
LOG_CHANNEL: single
|
||||
LOG_LEVEL: debug
|
||||
run: php artisan test
|
||||
|
||||
- name: Upload Laravel logs as artifacts
|
||||
if: always()
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: laravel-logs-php-${{ matrix.php-version }}-run-${{ github.run_attempt }}
|
||||
path: |
|
||||
storage/logs/*.log
|
||||
if-no-files-found: ignore
|
||||
retention-days: 7
|
||||
|
||||
@@ -68,7 +68,6 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
| [<img src="https://avatars.githubusercontent.com/u/181059?v=4" width="110px;"/><br /><sub>Juan Font</sub>](https://github.com/juanfont)<br />[💻](https://github.com/snipe/snipe-it/commits?author=juanfont "Code") | [<img src="https://avatars.githubusercontent.com/u/13137708?v=4" width="110px;"/><br /><sub>Juho Taipale</sub>](https://github.com/juhotaipale)<br />[💻](https://github.com/snipe/snipe-it/commits?author=juhotaipale "Code") | [<img src="https://avatars.githubusercontent.com/u/1007419?v=4" width="110px;"/><br /><sub>Korvin Szanto</sub>](https://github.com/KorvinSzanto)<br />[💻](https://github.com/snipe/snipe-it/commits?author=KorvinSzanto "Code") | [<img src="https://avatars.githubusercontent.com/u/8513053?v=4" width="110px;"/><br /><sub>Lewis Foster</sub>](https://lewisfoster.foo/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sniff122 "Code") | [<img src="https://avatars.githubusercontent.com/u/33877541?v=4" width="110px;"/><br /><sub>Logan Swartzendruber</sub>](https://github.com/loganswartz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=loganswartz "Code") | [<img src="https://avatars.githubusercontent.com/u/1156208?v=4" width="110px;"/><br /><sub>Lorenzo P.</sub>](https://github.com/lopezio)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lopezio "Code") | [<img src="https://avatars.githubusercontent.com/u/33946590?v=4" width="110px;"/><br /><sub>Lukas Jung</sub>](https://github.com/m4us1ne)<br />[💻](https://github.com/snipe/snipe-it/commits?author=m4us1ne "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/10965027?v=4" width="110px;"/><br /><sub>Ellie</sub>](https://leafedfox.xyz/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=LeafedFox "Code") | [<img src="https://avatars.githubusercontent.com/u/20960555?v=4" width="110px;"/><br /><sub>GA Stamper</sub>](https://github.com/gastamper)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gastamper "Code") | [<img src="https://avatars.githubusercontent.com/u/206553556?v=4" width="110px;"/><br /><sub>Guillaume Lefranc</sub>](https://github.com/gl-pup)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gl-pup "Code") | [<img src="https://avatars.githubusercontent.com/u/733892?v=4" width="110px;"/><br /><sub>Hajo Möller</sub>](https://github.com/dasjoe)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dasjoe "Code") | [<img src="https://avatars.githubusercontent.com/u/3420063?v=4" width="110px;"/><br /><sub>Istvan Basa</sub>](https://github.com/pottom)<br />[💻](https://github.com/snipe/snipe-it/commits?author=pottom "Code") | [<img src="https://avatars.githubusercontent.com/u/810824?v=4" width="110px;"/><br /><sub>JJ Asghar</sub>](https://jjasghar.github.io/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jjasghar "Code") | [<img src="https://avatars.githubusercontent.com/u/40404495?v=4" width="110px;"/><br /><sub>James E. Msenga</sub>](https://github.com/JemCdo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JemCdo "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/6865786?v=4" width="110px;"/><br /><sub>Jan Felix Wiebe</sub>](https://github.com/jfwiebe)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jfwiebe "Code") | [<img src="https://avatars.githubusercontent.com/u/43412008?v=4" width="110px;"/><br /><sub>Jo Drexl</sub>](https://www.nfon.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=drexljo "Code") | [<img src="https://avatars.githubusercontent.com/u/4807843?v=4" width="110px;"/><br /><sub>Austin Sasko</sub>](https://github.com/austinsasko)<br />[💻](https://github.com/snipe/snipe-it/commits?author=austinsasko "Code") | [<img src="https://avatars.githubusercontent.com/u/4875039?v=4" width="110px;"/><br /><sub>Jasson</sub>](http://jassoncordones.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JassonCordones "Code") | [<img src="https://avatars.githubusercontent.com/u/76069640?v=4" width="110px;"/><br /><sub>Okean</sub>](https://github.com/Tinyblargon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Tinyblargon "Code") | [<img src="https://avatars.githubusercontent.com/u/6515064?v=4" width="110px;"/><br /><sub>Alejandro Medrano</sub>](https://www.lst.tfo.upm.es/alejandro-medrano/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=amedranogil "Code") | [<img src="https://avatars.githubusercontent.com/u/58696401?v=4" width="110px;"/><br /><sub>Lukas Kraic</sub>](https://github.com/lukaskraic)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lukaskraic "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/1571724?v=4" width="110px;"/><br /><sub>Герхард PICCORO Lenz McKAY </sub>](https://github-readme-stats.vercel.app/api?username=mckaygerhard)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mckaygerhard "Code") | [<img src="https://avatars.githubusercontent.com/u/15015119?v=4" width="110px;"/><br /><sub>Johannes Pollitt</sub>](https://github.com/FlorestanII)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FlorestanII "Code") | [<img src="https://avatars.githubusercontent.com/u/14185442?v=4" width="110px;"/><br /><sub>Michael Strobel</sub>](https://strobelm.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=strobelm "Code") | [<img src="https://avatars.githubusercontent.com/u/634790?v=4" width="110px;"/><br /><sub>Nicky West</sub>](http://nickwest.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nickwest "Code") | [<img src="https://avatars.githubusercontent.com/u/1347327?v=4" width="110px;"/><br /><sub>akaspeh1</sub>](https://github.com/akaspeh1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=akaspeh1 "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class CleanIncorrectCheckoutAcceptances extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:clean-checkout-acceptances';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = "Delete checkout acceptances for checkouts to non-users";
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$deletions = 0;
|
||||
$skips = 0;
|
||||
|
||||
// This walks *every* checkoutacceptance. That's gnarly. But necessary
|
||||
$this->withProgressBar(CheckoutAcceptance::all(), function ($checkoutAcceptance) use (&$deletions, &$skips) {
|
||||
$item = $checkoutAcceptance->checkoutable;
|
||||
$checkout_to_id = $checkoutAcceptance->assigned_to_id;
|
||||
if(is_null($item)) {
|
||||
$this->info("'Checkoutable' Item is null, going to next record");
|
||||
return; //'false' allegedly breaks execution entirely, so 'true' maybe doesn't? hrm. just straight return maybe?
|
||||
}
|
||||
if(get_class($item) == LicenseSeat::class) {
|
||||
$item = $item->license;
|
||||
}
|
||||
foreach($item->assetlog()->where('action_type','checkout')->get() as $assetlog) {
|
||||
if ($assetlog->target_id == $checkout_to_id && $assetlog->target_type != User::class) {
|
||||
//We have a checkout-to an ID for a non-User, which matches to an ID in the checkout_acceptances table
|
||||
|
||||
//now, let's compare the _times_ - are they close?
|
||||
//I'm picking `created_at` over `action_date` because I'm more interested in when the actionlogs
|
||||
//were _created_, not when they were alleged to have happened - those created_at times need to be within 'X' seconds of
|
||||
//each other (currently 5)
|
||||
if ($assetlog->created_at->diffInSeconds($checkoutAcceptance->created_at, true) <= 5) { //we're allowing for five _ish_ seconds of slop
|
||||
$deletions++;
|
||||
$checkoutAcceptance->forceDelete(); // HARD delete this record; it should have never been
|
||||
return;
|
||||
} else {
|
||||
//$this->info("The two records are too far apart");
|
||||
}
|
||||
} else {
|
||||
//$this->info("No match! checkout to id: " . $checkout_to_id." target_id: ".$assetlog->target_id." target_type: ".$assetlog->target_type);
|
||||
}
|
||||
}
|
||||
$skips++;
|
||||
});
|
||||
$this->error("Final deletion count: $deletions, and skip count: $skips");
|
||||
}
|
||||
}
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\CheckoutRequest;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class CleanOldCheckoutRequests extends Command
|
||||
{
|
||||
private int $deletions = 0;
|
||||
private int $skips = 0;
|
||||
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:clean-old-checkout-requests';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Removes checkout requests that reference deleted assets or users.';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$requests = CheckoutRequest::with([
|
||||
'user' => function ($query) {
|
||||
$query->withTrashed();
|
||||
},
|
||||
'requestedItem' => function ($query) {
|
||||
$query->withTrashed();
|
||||
},
|
||||
])->get();
|
||||
|
||||
$this->info("Processing {$requests->count()} checkout requests");
|
||||
|
||||
$this->withProgressBar($requests, function ($request) {
|
||||
if ($this->shouldForceDelete($request)) {
|
||||
$request->forceDelete();
|
||||
$this->deletions++;
|
||||
return;
|
||||
}
|
||||
|
||||
if ($this->shouldSoftDelete($request)) {
|
||||
$request->delete();
|
||||
$this->deletions++;
|
||||
return;
|
||||
}
|
||||
|
||||
$this->skips++;
|
||||
});
|
||||
|
||||
$this->info("Final deletion count: $this->deletions, and skip count: $this->skips");
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
private function shouldForceDelete(CheckoutRequest $request)
|
||||
{
|
||||
// check if the requestable or user relationship is null
|
||||
return !$request->requestable || !$request->user;
|
||||
}
|
||||
|
||||
private function shouldSoftDelete(CheckoutRequest $request)
|
||||
{
|
||||
return $request->requestable->trashed() || $request->user->trashed();
|
||||
}
|
||||
}
|
||||
@@ -55,8 +55,6 @@ class LdapSync extends Command
|
||||
ini_set('max_execution_time', env('LDAP_TIME_LIM', 600)); //600 seconds = 10 minutes
|
||||
ini_set('memory_limit', env('LDAP_MEM_LIM', '500M'));
|
||||
|
||||
|
||||
// Map the LDAP attributes to the Snipe-IT user fields.
|
||||
$ldap_map = [
|
||||
"username" => Setting::getSettings()->ldap_username_field,
|
||||
"last_name" => Setting::getSettings()->ldap_lname_field,
|
||||
@@ -65,17 +63,11 @@ class LdapSync extends Command
|
||||
"emp_num" => Setting::getSettings()->ldap_emp_num,
|
||||
"email" => Setting::getSettings()->ldap_email,
|
||||
"phone" => Setting::getSettings()->ldap_phone_field,
|
||||
"mobile" => Setting::getSettings()->ldap_mobile,
|
||||
"jobtitle" => Setting::getSettings()->ldap_jobtitle,
|
||||
"address" => Setting::getSettings()->ldap_address,
|
||||
"city" => Setting::getSettings()->ldap_city,
|
||||
"state" => Setting::getSettings()->ldap_state,
|
||||
"zip" => Setting::getSettings()->ldap_zip,
|
||||
"country" => Setting::getSettings()->ldap_country,
|
||||
"location" => Setting::getSettings()->ldap_location,
|
||||
"dept" => Setting::getSettings()->ldap_dept,
|
||||
"manager" => Setting::getSettings()->ldap_manager,
|
||||
"display_name" => Setting::getSettings()->ldap_display_name,
|
||||
];
|
||||
|
||||
$ldap_default_group = Setting::getSettings()->ldap_default_group;
|
||||
@@ -242,11 +234,9 @@ class LdapSync extends Command
|
||||
}
|
||||
|
||||
|
||||
// Assign the mapped LDAP attributes for each user to the Snipe-IT user fields
|
||||
for ($i = 0; $i < $results['count']; $i++) {
|
||||
$item = [];
|
||||
$item['username'] = $results[$i][$ldap_map["username"]][0] ?? '';
|
||||
$item['display_name'] = $results[$i][$ldap_map["display_name"]][0] ?? '';
|
||||
$item['employee_number'] = $results[$i][$ldap_map["emp_num"]][0] ?? '';
|
||||
$item['lastname'] = $results[$i][$ldap_map["last_name"]][0] ?? '';
|
||||
$item['firstname'] = $results[$i][$ldap_map["first_name"]][0] ?? '';
|
||||
@@ -254,13 +244,8 @@ class LdapSync extends Command
|
||||
$item['ldap_location_override'] = $results[$i]['ldap_location_override'] ?? '';
|
||||
$item['location_id'] = $results[$i]['location_id'] ?? '';
|
||||
$item['telephone'] = $results[$i][$ldap_map["phone"]][0] ?? '';
|
||||
$item['mobile'] = $results[$i][$ldap_map["mobile"]][0] ?? '';
|
||||
$item['jobtitle'] = $results[$i][$ldap_map["jobtitle"]][0] ?? '';
|
||||
$item['address'] = $results[$i][$ldap_map["address"]][0] ?? '';
|
||||
$item['city'] = $results[$i][$ldap_map["city"]][0] ?? '';
|
||||
$item['state'] = $results[$i][$ldap_map["state"]][0] ?? '';
|
||||
$item['country'] = $results[$i][$ldap_map["country"]][0] ?? '';
|
||||
$item['zip'] = $results[$i][$ldap_map["zip"]][0] ?? '';
|
||||
$item['department'] = $results[$i][$ldap_map["dept"]][0] ?? '';
|
||||
$item['manager'] = $results[$i][$ldap_map["manager"]][0] ?? '';
|
||||
$item['location'] = $results[$i][$ldap_map["location"]][0] ?? '';
|
||||
@@ -293,9 +278,6 @@ class LdapSync extends Command
|
||||
if($ldap_map["username"] != null){
|
||||
$user->username = $item['username'];
|
||||
}
|
||||
if($ldap_map["display_name"] != null){
|
||||
$user->display_name = $item['display_name'];
|
||||
}
|
||||
if($ldap_map["last_name"] != null){
|
||||
$user->last_name = $item['lastname'];
|
||||
}
|
||||
@@ -311,9 +293,6 @@ class LdapSync extends Command
|
||||
if($ldap_map["phone"] != null){
|
||||
$user->phone = $item['telephone'];
|
||||
}
|
||||
if($ldap_map["mobile"] != null){
|
||||
$user->mobile = $item['mobile'];
|
||||
}
|
||||
if($ldap_map["jobtitle"] != null){
|
||||
$user->jobtitle = $item['jobtitle'];
|
||||
}
|
||||
|
||||
@@ -6,7 +6,6 @@ use Illuminate\Console\Command;
|
||||
use App\Models\Setting;
|
||||
use Exception;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use App\Models\Ldap;
|
||||
|
||||
/**
|
||||
* Check if a given ip is in a network
|
||||
@@ -161,15 +160,7 @@ class LdapTroubleshooter extends Command
|
||||
$output[] = "-x";
|
||||
$output[] = "-b ".escapeshellarg($settings->ldap_basedn);
|
||||
$output[] = "-D ".escapeshellarg($settings->ldap_uname);
|
||||
|
||||
try {
|
||||
$w = Crypt::Decrypt($settings->ldap_pword);
|
||||
} catch (\Exception $e) {
|
||||
$this->warn("Could not decrypt password. This usually means an LDAP password was not set or the APP_KEY was changed since the LDAP pasword was last saved. Aborting.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
$output[] = "-w ". escapeshellarg($w);
|
||||
$output[] = "-w ".escapeshellarg(Crypt::Decrypt($settings->ldap_pword));
|
||||
$output[] = escapeshellarg(parenthesized_filter($settings->ldap_filter));
|
||||
if($settings->ldap_tls) {
|
||||
$this->line("# adding STARTTLS option");
|
||||
@@ -180,23 +171,6 @@ class LdapTroubleshooter extends Command
|
||||
$this->line(implode(" \\\n",$output));
|
||||
exit(0);
|
||||
}
|
||||
|
||||
//PHP Version check for warning
|
||||
$php_version = phpversion();
|
||||
list($major, $minor, $patch) = explode('.', $php_version);
|
||||
if (
|
||||
$major < 8 ||
|
||||
($major == 8 && $minor < 3) ||
|
||||
($major == 8 && $minor == 3 && $patch < 21) ||
|
||||
($major == 8 && $minor == 4 && $patch < 7)
|
||||
) {
|
||||
$this->warn("PHP Version: $php_version WARNING - Versions before 8.3.21 or 8.4.7 will return INCONSISTENT results!");
|
||||
if (!$this->confirm("Are you sure you wish to continue?")) {
|
||||
$this->warn("ABORTING");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
|
||||
if(!$this->option('force')) {
|
||||
$confirmation = $this->confirm('WARNING: This command will make several attempts to connect to your LDAP server. Are you sure this is ok?');
|
||||
if(!$confirmation) {
|
||||
@@ -205,7 +179,7 @@ class LdapTroubleshooter extends Command
|
||||
}
|
||||
}
|
||||
//$this->line(print_r($settings,true));
|
||||
$this->line("STAGE 1: Checking settings");
|
||||
$this->info("STAGE 1: Checking settings");
|
||||
if(!$settings->ldap_enabled) {
|
||||
$this->error("WARNING: Snipe-IT's LDAP setting is not turned on. (That may be OK if you're still trying to figure out settings)");
|
||||
}
|
||||
@@ -236,40 +210,32 @@ class LdapTroubleshooter extends Command
|
||||
$this->info("Determined LDAP hostname to be: ".$parsed['host']);
|
||||
}
|
||||
|
||||
$this->info("Performing DNS lookup of: ".$parsed['host']);
|
||||
$ips = dns_get_record($parsed['host']);
|
||||
$raw_ips = [];
|
||||
|
||||
if (inet_pton($parsed['host']) !== false) {
|
||||
$this->line($parsed['host'] . " already looks like an address; skipping DNS lookup");
|
||||
$raw_ips[] = $parsed['host'];
|
||||
} else {
|
||||
$this->line("Performing DNS lookup of: " . $parsed['host']);
|
||||
$ips = dns_get_record($parsed['host']);
|
||||
//$this->info("Host IP is: ".print_r($ips,true));
|
||||
|
||||
//$this->info("Host IP is: ".print_r($ips,true));
|
||||
|
||||
if (!$ips || count($ips) == 0) {
|
||||
$this->error("ERROR: DNS lookup of host: " . $parsed['host'] . " has failed. ABORTING.");
|
||||
exit(-1);
|
||||
}
|
||||
$this->debugout("IP's? " . print_r($ips, true));
|
||||
foreach ($ips as $ip) {
|
||||
if (!isset($ip['ip'])) {
|
||||
continue;
|
||||
}
|
||||
$raw_ips[] = $ip['ip'];
|
||||
}
|
||||
if(!$ips || count($ips) == 0) {
|
||||
$this->error("ERROR: DNS lookup of host: ".$parsed['host']." has failed. ABORTING.");
|
||||
exit(-1);
|
||||
}
|
||||
foreach ($raw_ips as $ip) {
|
||||
if ($ip == "127.0.0.1") {
|
||||
$this->debugout("IP's? ".print_r($ips,true));
|
||||
foreach($ips as $ip) {
|
||||
if(!isset($ip['ip'])) {
|
||||
continue;
|
||||
}
|
||||
$raw_ips[]=$ip['ip'];
|
||||
if($ip['ip'] == "127.0.0.1") {
|
||||
$this->error("WARNING: Using the localhost IP as the LDAP server. This is usually wrong");
|
||||
}
|
||||
if (ip_in_range($ip, '10.0.0.0/8') || ip_in_range($ip, '192.168.0.0/16') || ip_in_range($ip, '172.16.0.0/12')) {
|
||||
if(ip_in_range($ip['ip'],'10.0.0.0/8') || ip_in_range($ip['ip'],'192.168.0.0/16') || ip_in_range($ip['ip'], '172.16.0.0/12')) {
|
||||
$this->error("WARNING: Using an RFC1918 Private address for LDAP server. This may be correct, but it can be a problem if your Snipe-IT instance is not hosted on your private network");
|
||||
}
|
||||
}
|
||||
|
||||
$this->line("STAGE 2: Checking basic network connectivity");
|
||||
$ports = [636, 389];
|
||||
$this->info("STAGE 2: Checking basic network connectivity");
|
||||
$ports = [389,636];
|
||||
if(@$parsed['port'] && !in_array($parsed['port'],$ports)) {
|
||||
$ports[] = $parsed['port'];
|
||||
}
|
||||
@@ -280,7 +246,7 @@ class LdapTroubleshooter extends Command
|
||||
$errstr = '';
|
||||
$timeout = 30.0;
|
||||
$result = '';
|
||||
$this->line("Attempting to connect to port: " . $port . " - may take up to $timeout seconds");
|
||||
$this->info("Attempting to connect to port: ".$port." - may take up to $timeout seconds");
|
||||
try {
|
||||
$result = fsockopen($parsed['host'], $port, $errno, $errstr, 30.0);
|
||||
} catch(Exception $e) {
|
||||
@@ -299,9 +265,9 @@ class LdapTroubleshooter extends Command
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
$this->line("STAGE 3: Determine encryption algorithm, if any");
|
||||
$this->info("STAGE 3: Determine encryption algorithm, if any");
|
||||
|
||||
$ldap_urls = []; // [url, cert-check?, start_tls?]
|
||||
$ldap_urls = [];
|
||||
$pretty_ldap_urls = [];
|
||||
foreach($open_ports as $port) {
|
||||
$this->line("Trying TLS first for port $port");
|
||||
@@ -309,46 +275,35 @@ class LdapTroubleshooter extends Command
|
||||
if($this->test_anonymous_bind($ldap_url)) {
|
||||
$this->info("Anonymous bind succesful to $ldap_url!");
|
||||
$ldap_urls[] = [ $ldap_url, true, false ];
|
||||
$pretty_ldap_urls[] = [$ldap_url, "enabled", "n/a (no)"];
|
||||
$pretty_ldap_urls[] = [ $ldap_url, "YES", "no" ];
|
||||
continue; // TODO - lots of copypasta in these if(test_anonymous_bind()) routines...
|
||||
} else {
|
||||
$this->error("WARNING: Failed to bind to $ldap_url - trying without certificate checks.");
|
||||
}
|
||||
|
||||
if($this->test_anonymous_bind($ldap_url, false)) {
|
||||
$this->info("Anonymous bind successful to $ldap_url with certificate-checks disabled");
|
||||
$ldap_urls[] = [$ldap_url, false, false];
|
||||
$pretty_ldap_urls[] = [$ldap_url, "DISABLED", "n/a (no)"];
|
||||
$this->info("Anonymous bind succesful to $ldap_url with certifcate-checks disabled");
|
||||
$ldap_urls[] = [ $ldap_url, false, false ];
|
||||
$pretty_ldap_urls[] = [ $ldap_url, "no", "no" ];
|
||||
continue;
|
||||
} else {
|
||||
$this->error("WARNING: Failed to bind to $ldap_url with certificate checks disabled. Trying unencrypted with STARTTLS");
|
||||
}
|
||||
|
||||
// now switching to ldap:// URL's from ldaps://
|
||||
$ldap_url = "ldap://".$parsed['host'].":$port";
|
||||
|
||||
if($this->test_anonymous_bind($ldap_url, true, true)) {
|
||||
$this->info("Plain connection to $ldap_url with STARTTLS succesful!");
|
||||
$ldap_urls[] = [ $ldap_url, true, true ];
|
||||
$pretty_ldap_urls[] = [$ldap_url, "enabled", "STARTTLS ENABLED"];
|
||||
$pretty_ldap_urls[] = [ $ldap_url, "YES", "YES" ];
|
||||
continue;
|
||||
} else {
|
||||
$this->error("WARNING: Failed to bind to $ldap_url with STARTTLS enabled. Trying without certificate checks.");
|
||||
}
|
||||
|
||||
if ($this->test_anonymous_bind($ldap_url, false, true)) {
|
||||
$this->info("Plain connection to $ldap_url with STARTTLS and cert checks *disabled* successful!");
|
||||
$ldap_urls[] = [$ldap_url, false, true];
|
||||
$pretty_ldap_urls[] = [$ldap_url, "DISABLED", "STARTTLS ENABLED"];
|
||||
continue;
|
||||
} else {
|
||||
$this->error("WARNING: Failed to bind to $ldap_url with STARTTLS enabled, and cert checks disabled. Trying without STARTTLS");
|
||||
$this->error("WARNING: Failed to bind to $ldap_url with STARTTLS enabled. Trying without STARTTLS");
|
||||
}
|
||||
|
||||
if($this->test_anonymous_bind($ldap_url)) {
|
||||
$this->info("Plain connection to $ldap_url succesful!");
|
||||
$ldap_urls[] = [ $ldap_url, true, false ];
|
||||
$pretty_ldap_urls[] = [$ldap_url, "n/a", "starttls disabled"];
|
||||
$pretty_ldap_urls[] = [ $ldap_url, "YES", "no" ];
|
||||
continue;
|
||||
} else {
|
||||
$this->error("WARNING: Failed to bind to $ldap_url. Giving up on port $port");
|
||||
@@ -358,29 +313,23 @@ class LdapTroubleshooter extends Command
|
||||
$this->debugout(print_r($ldap_urls,true));
|
||||
|
||||
if(count($ldap_urls) > 0 ) {
|
||||
$this->debugout("Found working LDAP URL's: ");
|
||||
$this->info("Found working LDAP URL's: ");
|
||||
foreach($ldap_urls as $ldap_url) { // TODO maybe do this as a $this->table() instead?
|
||||
$this->debugout("LDAP URL: " . $ldap_url[0]);
|
||||
$this->debugout($ldap_url[0] . ($ldap_url[1] ? " certificate checks enabled" : " certificate checks disabled") . ($ldap_url[2] ? " STARTTLS Enabled " : " STARTTLS Disabled"));
|
||||
$this->info("LDAP URL: ".$ldap_url[0]);
|
||||
$this->info($ldap_url[0]. ($ldap_url[1] ? " certificate checks enabled" : " certificate checks disabled"). ($ldap_url[2] ? " STARTTLS Enabled ": " STARTTLS Disabled"));
|
||||
}
|
||||
$this->table(["URL", "Cert Checks?", "STARTTLS?"], $pretty_ldap_urls);
|
||||
$this->table(["URL", "Cert Checks Enabled?", "STARTTLS Enabled?"],$pretty_ldap_urls);
|
||||
} else {
|
||||
$this->error("ERROR - no valid LDAP URL's available - ABORTING");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$this->line("STAGE 4: Test Administrative Bind for LDAP Sync");
|
||||
$this->info("STAGE 4: Test Administrative Bind for LDAP Sync");
|
||||
foreach($ldap_urls AS $ldap_url) {
|
||||
try {
|
||||
$w = Crypt::Decrypt($settings->ldap_pword);
|
||||
} catch (\Exception $e) {
|
||||
$this->warn("Could not decrypt password. This usually means an LDAP password was not set or the APP_KEY was changed since the LDAP pasword was last saved. Aborting.");
|
||||
exit(0);
|
||||
}
|
||||
$this->test_authed_bind($ldap_url[0], $ldap_url[1], $ldap_url[2], $settings->ldap_uname, $w);
|
||||
$this->test_authed_bind($ldap_url[0], $ldap_url[1], $ldap_url[2], $settings->ldap_uname, Crypt::decrypt($settings->ldap_pword));
|
||||
}
|
||||
|
||||
$this->line("STAGE 5: Test BaseDN");
|
||||
$this->info("STAGE 5: Test BaseDN");
|
||||
//grab all LDAP_ constants and fill up a reversed array mapping from weird LDAP dotted-strings to (Constant Name)
|
||||
$all_defined_constants = get_defined_constants();
|
||||
$ldap_constants = [];
|
||||
@@ -392,23 +341,16 @@ class LdapTroubleshooter extends Command
|
||||
$this->debugout("LDAP constants are: ".print_r($ldap_constants,true));
|
||||
|
||||
foreach($ldap_urls AS $ldap_url) {
|
||||
try {
|
||||
$w = Crypt::Decrypt($settings->ldap_pword);
|
||||
} catch (\Exception $e) {
|
||||
$this->warn("Could not decrypt password. This usually means an LDAP password was not set or the APP_KEY was changed since the LDAP pasword was last saved. Aborting.");
|
||||
exit(0);
|
||||
}
|
||||
|
||||
if($this->test_informational_bind($ldap_url[0],$ldap_url[1],$ldap_url[2],$settings->ldap_uname,$w,$settings)) {
|
||||
if($this->test_informational_bind($ldap_url[0],$ldap_url[1],$ldap_url[2],$settings->ldap_uname,Crypt::decrypt($settings->ldap_pword),$settings)) {
|
||||
$this->info("Success getting informational bind!");
|
||||
} else {
|
||||
$this->error("Unable to get information from bind.");
|
||||
}
|
||||
}
|
||||
|
||||
$this->line("STAGE 6: Test LDAP Login to Snipe-IT");
|
||||
$this->info("STAGE 6: Test LDAP Login to Snipe-IT");
|
||||
foreach($ldap_urls AS $ldap_url) {
|
||||
$this->line("Starting auth to " . $ldap_url[0]);
|
||||
$this->info("Starting auth to ".$ldap_url[0]);
|
||||
while(true) {
|
||||
$with_tls = $ldap_url[1] ? "with": "without";
|
||||
$with_startssl = $ldap_url[2] ? "using": "not using";
|
||||
@@ -417,12 +359,7 @@ class LdapTroubleshooter extends Command
|
||||
}
|
||||
$username = $this->ask("Username");
|
||||
$password = $this->secret("Password");
|
||||
$results = $this->test_authed_bind($ldap_url[0], $ldap_url[1], $ldap_url[2], $username, $password); // FIXME - should do some other stuff here, maybe with the concatenating or something? maybe? and/or should put up some results?
|
||||
if ($results) {
|
||||
$this->info("Success authenticating with " . $username);
|
||||
} else {
|
||||
$this->error("Unable to authenticate with " . $username);
|
||||
}
|
||||
$this->test_authed_bind($ldap_url[0], $ldap_url[1], $ldap_url[2], $username, $password); // FIXME - should do some other stuff here, maybe with the concatenating or something? maybe? and/or should put up some results?
|
||||
}
|
||||
}
|
||||
|
||||
@@ -431,17 +368,14 @@ class LdapTroubleshooter extends Command
|
||||
|
||||
public function connect_to_ldap($ldap_url, $check_cert, $start_tls)
|
||||
{
|
||||
if ($check_cert) {
|
||||
$this->line("we *ARE* checking certs");
|
||||
Ldap::ignoreCertificates(false);
|
||||
|
||||
} else {
|
||||
$this->line("we are IGNORING certs");
|
||||
Ldap::ignoreCertificates(true);
|
||||
}
|
||||
$lconn = ldap_connect($ldap_url);
|
||||
ldap_set_option($lconn, LDAP_OPT_PROTOCOL_VERSION, 3); // should we 'test' different protocol versions here? Does anyone even use anything other than LDAPv3?
|
||||
// no - it's formally deprecated: https://tools.ietf.org/html/rfc3494
|
||||
if(!$check_cert) {
|
||||
putenv('LDAPTLS_REQCERT=never'); // This is horrible; is this *really* the only way to do it?
|
||||
} else {
|
||||
putenv('LDAPTLS_REQCERT'); // have to very explicitly and manually *UN* set the env var here to ensure it works
|
||||
}
|
||||
if($this->settings->ldap_client_tls_cert && $this->settings->ldap_client_tls_key) {
|
||||
// client-side TLS certificate support for LDAP (Google Secure LDAP)
|
||||
putenv('LDAPTLS_CERT=storage/ldap_client_tls.cert');
|
||||
@@ -470,10 +404,9 @@ class LdapTroubleshooter extends Command
|
||||
return $this->timed_boolean_execute(function () use ($ldap_url, $check_cert , $start_tls) {
|
||||
try {
|
||||
$lconn = $this->connect_to_ldap($ldap_url, $check_cert, $start_tls);
|
||||
$this->line("Attempting to bind now, this can take a while if we mess it up");
|
||||
$this->info("gonna try to bind now, this can take a while if we mess it up");
|
||||
$bind_results = ldap_bind($lconn);
|
||||
$this->line("Bind results are: " . $bind_results . " which translate into boolean: " . (bool)$bind_results);
|
||||
ldap_close($lconn);
|
||||
$this->info("Bind results are: ".$bind_results." which translate into boolean: ".(bool)$bind_results);
|
||||
return (bool)$bind_results;
|
||||
} catch (Exception $e) {
|
||||
$this->error("WARNING: Exception caught during bind - ".$e->getMessage());
|
||||
@@ -488,7 +421,6 @@ class LdapTroubleshooter extends Command
|
||||
try {
|
||||
$lconn = $this->connect_to_ldap($ldap_url, $check_cert, $start_tls);
|
||||
$bind_results = ldap_bind($lconn, $username, $password);
|
||||
ldap_close($lconn);
|
||||
if(!$bind_results) {
|
||||
$this->error("WARNING: Failed to bind to $ldap_url as $username");
|
||||
return false;
|
||||
@@ -514,62 +446,22 @@ class LdapTroubleshooter extends Command
|
||||
return false;
|
||||
}
|
||||
$this->info("SUCCESS - Able to bind to $ldap_url as $username");
|
||||
$cleaned_results = [];
|
||||
try {
|
||||
// This _may_ only work for Active Directory?
|
||||
$result = ldap_read($conn, '', '(objectClass=*)'/* , ['supportedControl']*/);
|
||||
$results = ldap_get_entries($conn, $result);
|
||||
$cleaned_results = $this->ldap_results_cleaner($results);
|
||||
//$this->line(print_r($cleaned_results,true));
|
||||
$default_naming_contexts = $cleaned_results[0]['namingcontexts'];
|
||||
$this->info("Default Naming Contexts:");
|
||||
$this->info(implode(", ", $default_naming_contexts));
|
||||
//okay, great - now how do we display those results? I have no idea.
|
||||
} catch (\Exception $e) {
|
||||
$this->error("Unable to get base naming contexts - here's what we *did* get:");
|
||||
$this->line(print_r($cleaned_results, true));
|
||||
}
|
||||
$result = ldap_read($conn, '', '(objectClass=*)'/* , ['supportedControl']*/);
|
||||
$results = ldap_get_entries($conn, $result);
|
||||
$cleaned_results = $this->ldap_results_cleaner($results);
|
||||
$this->line(print_r($cleaned_results,true));
|
||||
//okay, great - now how do we display those results? I have no idea.
|
||||
// I don't see why this throws an Exception for Google LDAP, but I guess we ought to try and catch it?
|
||||
$this->debugout("I guess we're trying to do the ldap search here, but sometimes it takes too long?");
|
||||
$this->comment("I guess we're trying to do the ldap search here, but sometimes it takes too long?");
|
||||
$this->debugout("Base DN is: ".$settings->ldap_basedn." and filter is: ".parenthesized_filter($settings->ldap_filter));
|
||||
$search_results = ldap_search($conn, $settings->ldap_basedn, parenthesized_filter($settings->ldap_filter));
|
||||
$entries = ldap_get_entries($conn, $search_results);
|
||||
$this->info("Printing first 10 results: ");
|
||||
$pretty_data = array_slice($this->ldap_results_cleaner($entries), 0, 10);
|
||||
//print_r($data);
|
||||
$headers = [];
|
||||
foreach ($pretty_data as $row) {
|
||||
//populate headers
|
||||
foreach ($row as $key => $value) {
|
||||
//skip objectsid and objectguid because it junks up output
|
||||
if ($key == "objectsid" || $key == "objectguid") {
|
||||
continue;
|
||||
}
|
||||
if (!in_array($key, $headers)) {
|
||||
$headers[] = $key;
|
||||
}
|
||||
}
|
||||
for($i=0;$i<10;$i++) {
|
||||
$this->info($search_results[$i]);
|
||||
}
|
||||
$table = [];
|
||||
//repeat again to populate table
|
||||
foreach ($pretty_data as $row) {
|
||||
$newrow = [];
|
||||
foreach ($headers as $header) {
|
||||
if (is_array(@$row[$header])) {
|
||||
$newrow[] = "[" . implode(", ", $row[$header]) . "]";
|
||||
} else {
|
||||
$newrow[] = @$row[$header];
|
||||
}
|
||||
}
|
||||
$table[] = $newrow;
|
||||
}
|
||||
|
||||
$this->table($headers, $table);
|
||||
} catch (\Exception $e) {
|
||||
$this->error("WARNING: Exception caught during Authed bind to $username - ".$e->getMessage());
|
||||
return false;
|
||||
} finally {
|
||||
ldap_close($conn);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -585,7 +477,7 @@ class LdapTroubleshooter extends Command
|
||||
{
|
||||
if(!(function_exists('pcntl_sigtimedwait') && function_exists('posix_getpid') && function_exists('pcntl_fork') && function_exists('posix_kill') && function_exists('pcntl_wifsignaled'))) {
|
||||
// POSIX functions needed for forking aren't present, just run the function inline (ignoring timeout)
|
||||
$this->line('WARNING: Unable to execute POSIX fork() commands, timeout may not be respected');
|
||||
$this->info('WARNING: Unable to execute POSIX fork() commands, timeout may not be respected');
|
||||
return $function();
|
||||
} else {
|
||||
$parent_pid = posix_getpid();
|
||||
@@ -622,6 +514,4 @@ class LdapTroubleshooter extends Command
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -96,7 +96,7 @@ class MoveUploadsToNewDisk extends Command
|
||||
$private_uploads['assets'] = glob('storage/private_uploads/assets'."/*.*");
|
||||
$private_uploads['signatures'] = glob('storage/private_uploads/signatures'."/*.*");
|
||||
$private_uploads['audits'] = glob('storage/private_uploads/audits'."/*.*");
|
||||
$private_uploads['assetmodels'] = glob('storage/private_uploads/models'."/*.*");
|
||||
$private_uploads['assetmodels'] = glob('storage/private_uploads/assetmodels'."/*.*");
|
||||
$private_uploads['imports'] = glob('storage/private_uploads/imports'."/*.*");
|
||||
$private_uploads['licenses'] = glob('storage/private_uploads/licenses'."/*.*");
|
||||
$private_uploads['users'] = glob('storage/private_uploads/users'."/*.*");
|
||||
|
||||
@@ -59,9 +59,6 @@ class PaveIt extends Command
|
||||
'migrations',
|
||||
'settings',
|
||||
'users',
|
||||
'telescope_entries',
|
||||
'telescope_entries_tags',
|
||||
'telescope_monitoring',
|
||||
];
|
||||
|
||||
// We only need to find out what these are so we can nuke these columns on the assets table.
|
||||
|
||||
@@ -62,19 +62,19 @@ class Purge extends Command
|
||||
$assetcount = $assets->count();
|
||||
$this->info($assets->count().' assets purged.');
|
||||
$asset_assoc = 0;
|
||||
$maintenances = 0;
|
||||
$asset_maintenances = 0;
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
$this->info('- Asset "'.$asset->display_name.'" deleted.');
|
||||
$this->info('- Asset "'.$asset->present()->name().'" deleted.');
|
||||
$asset_assoc += $asset->assetlog()->count();
|
||||
$asset->assetlog()->forceDelete();
|
||||
$maintenances += $asset->maintenances()->count();
|
||||
$asset->maintenances()->forceDelete();
|
||||
$asset_maintenances += $asset->assetmaintenances()->count();
|
||||
$asset->assetmaintenances()->forceDelete();
|
||||
$asset->forceDelete();
|
||||
}
|
||||
|
||||
$this->info($asset_assoc.' corresponding log records purged.');
|
||||
$this->info($maintenances.' corresponding maintenance records purged.');
|
||||
$this->info($asset_maintenances.' corresponding maintenance records purged.');
|
||||
|
||||
$locations = Location::whereNotNull('deleted_at')->withTrashed()->get();
|
||||
$this->info($locations->count().' locations purged.');
|
||||
|
||||
@@ -243,8 +243,6 @@ class RestoreFromBackup extends Command
|
||||
$private_dirs = [
|
||||
'storage/private_uploads/accessories',
|
||||
'storage/private_uploads/assetmodels',
|
||||
'storage/private_uploads/maintenances',
|
||||
'storage/private_uploads/models',
|
||||
'storage/private_uploads/assets', // these are asset _files_, not the pictures.
|
||||
'storage/private_uploads/audits',
|
||||
'storage/private_uploads/components',
|
||||
@@ -262,10 +260,9 @@ class RestoreFromBackup extends Command
|
||||
];
|
||||
$public_dirs = [
|
||||
'public/uploads/accessories',
|
||||
'public/uploads/assetmodels',
|
||||
'public/uploads/maintenances',
|
||||
'public/uploads/assets', // these are asset _pictures_, not asset files
|
||||
'public/uploads/avatars',
|
||||
//'public/uploads/barcodes', // we don't want this, let the barcodes be regenerated
|
||||
'public/uploads/categories',
|
||||
'public/uploads/companies',
|
||||
'public/uploads/components',
|
||||
|
||||
@@ -77,7 +77,7 @@ class SendAcceptanceReminder extends Command
|
||||
if(!$email){
|
||||
$no_email_list[] = [
|
||||
'id' => $acceptance->assignedTo?->id,
|
||||
'name' => $acceptance->assignedTo?->display_name,
|
||||
'name' => $acceptance->assignedTo?->present()->fullName(),
|
||||
];
|
||||
} else {
|
||||
$count++;
|
||||
|
||||
@@ -133,18 +133,9 @@ class Handler extends ExceptionHandler
|
||||
// This is traaaaash but it handles models that are not found while using route model binding :(
|
||||
// The only alternative is to set that at *each* route, which is crazypants
|
||||
if ($e instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
|
||||
$ids = method_exists($e, 'getIds') ? $e->getIds() : [];
|
||||
|
||||
if (in_array('bulkedit', $ids, true)) {
|
||||
$error_array = session()->get('bulk_asset_errors');
|
||||
return redirect()
|
||||
->route('hardware.index')
|
||||
->withErrors($error_array, 'bulk_asset_errors')
|
||||
->withInput();
|
||||
}
|
||||
|
||||
// This gets the MVC model name from the exception and formats in a way that's less fugly
|
||||
$model_name = trim(strtolower(implode(" ", preg_split('/(?=[A-Z])/', last(explode('\\', $e->getModel()))))));
|
||||
$model_name = strtolower(implode(" ", preg_split('/(?=[A-Z])/', last(explode('\\', $e->getModel())))));
|
||||
$route = str_plural(strtolower(last(explode('\\', $e->getModel())))).'.index';
|
||||
|
||||
// Sigh.
|
||||
@@ -160,7 +151,9 @@ class Handler extends ExceptionHandler
|
||||
$route = 'maintenances.index';
|
||||
} elseif ($route === 'licenseseats.index') {
|
||||
$route = 'licenses.index';
|
||||
} elseif (($route === 'customfieldsets.index') || ($route === 'customfields.index')) {
|
||||
} elseif ($route === 'customfields.index') {
|
||||
$route = 'fields.index';
|
||||
} elseif ($route === 'customfieldsets.index') {
|
||||
$route = 'fields.index';
|
||||
}
|
||||
|
||||
|
||||
@@ -82,13 +82,6 @@ class Helper
|
||||
'zu' => 'zu-ZA', // Zulu
|
||||
];
|
||||
|
||||
public static function hasRtl($value) {
|
||||
$rtlChar = '/[\x{0590}-\x{083F}]|[\x{08A0}-\x{08FF}]|[\x{FB1D}-\x{FDFF}]|[\x{FE70}-\x{FEFF}]/u';
|
||||
return preg_match($rtlChar, $value) != 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Simple helper to invoke the markdown parser
|
||||
*
|
||||
@@ -1204,30 +1197,19 @@ class Helper
|
||||
'webp' => 'far fa-image',
|
||||
'avif' => 'far fa-image',
|
||||
'svg' => 'fas fa-vector-square',
|
||||
|
||||
// word
|
||||
'doc' => 'far fa-file-word',
|
||||
'docx' => 'far fa-file-word',
|
||||
|
||||
// Excel
|
||||
'xls' => 'far fa-file-excel',
|
||||
'xlsx' => 'far fa-file-excel',
|
||||
'ods' => 'far fa-file-excel',
|
||||
|
||||
// Presentation
|
||||
'ppt' => 'far fa-file-powerpoint',
|
||||
'odp' => 'far fa-file-powerpoint',
|
||||
|
||||
// archive
|
||||
'zip' => 'fas fa-file-archive',
|
||||
'rar' => 'fas fa-file-archive',
|
||||
|
||||
//Text
|
||||
'odt' => 'far fa-file-alt',
|
||||
'txt' => 'far fa-file-alt',
|
||||
'rtf' => 'far fa-file-alt',
|
||||
'xml' => 'fas fa-code',
|
||||
|
||||
// Misc
|
||||
'pdf' => 'far fa-file-pdf',
|
||||
'lic' => 'far fa-save',
|
||||
@@ -1561,6 +1543,11 @@ class Helper
|
||||
|
||||
// return to previous page
|
||||
if ($redirect_option === 'back') {
|
||||
if ($backUrl === route('home')) {
|
||||
return redirect()->to($backUrl)
|
||||
->with('warning', trans('general.page_error'));
|
||||
}
|
||||
|
||||
return redirect()->to($backUrl);
|
||||
}
|
||||
|
||||
@@ -1713,5 +1700,5 @@ class Helper
|
||||
}
|
||||
}
|
||||
return $mismatched;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -16,7 +16,6 @@ class IconHelper
|
||||
case 'clone':
|
||||
return 'far fa-clone';
|
||||
case 'delete':
|
||||
case 'upload deleted':
|
||||
return 'fas fa-trash';
|
||||
case 'create':
|
||||
return 'fa-solid fa-plus';
|
||||
@@ -44,8 +43,6 @@ class IconHelper
|
||||
return 'fa-regular fa-envelope';
|
||||
case 'phone':
|
||||
return 'fa-solid fa-phone';
|
||||
case 'mobile':
|
||||
return 'fas fa-mobile-screen-button';
|
||||
case 'long-arrow-right':
|
||||
return 'fas fa-long-arrow-alt-right';
|
||||
case 'download':
|
||||
@@ -154,7 +151,6 @@ class IconHelper
|
||||
case 'location':
|
||||
return 'fas fa-map-marker-alt';
|
||||
case 'superadmin':
|
||||
case 'admin':
|
||||
return 'fas fa-crown';
|
||||
case 'print':
|
||||
return 'fa-solid fa-print';
|
||||
|
||||
@@ -27,45 +27,6 @@ class StorageHelper
|
||||
}
|
||||
}
|
||||
|
||||
public static function getMediaType($file_with_path) {
|
||||
|
||||
// Get the file extension and determine the media type
|
||||
if (Storage::exists($file_with_path)) {
|
||||
$fileinfo = pathinfo($file_with_path);
|
||||
$extension = strtolower($fileinfo['extension']);
|
||||
switch ($extension) {
|
||||
case 'avif':
|
||||
case 'jpg':
|
||||
case 'png':
|
||||
case 'gif':
|
||||
case 'svg':
|
||||
case 'webp':
|
||||
return 'image';
|
||||
case 'pdf':
|
||||
return 'pdf';
|
||||
case 'mp3':
|
||||
case 'wav':
|
||||
case 'ogg':
|
||||
return 'audio';
|
||||
case 'mp4':
|
||||
case 'webm':
|
||||
case 'mov':
|
||||
return 'video';
|
||||
case 'doc':
|
||||
case 'docx':
|
||||
return 'document';
|
||||
case 'txt':
|
||||
return 'text';
|
||||
case 'xls':
|
||||
case 'xlsx':
|
||||
case 'ods':
|
||||
return 'spreadsheet';
|
||||
default:
|
||||
return $extension; // Default for unknown types
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This determines the file types that should be allowed inline and checks their fileinfo extension
|
||||
@@ -91,6 +52,7 @@ class StorageHelper
|
||||
'pdf',
|
||||
'png',
|
||||
'svg',
|
||||
'svg',
|
||||
'wav',
|
||||
'webm',
|
||||
'webp',
|
||||
|
||||
@@ -77,25 +77,9 @@ class AccessoriesController extends Controller
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
$accessory->notes = request('notes');
|
||||
|
||||
if ($request->has('use_cloned_image')) {
|
||||
$cloned_model_img = Accessory::select('image')->find($request->input('clone_image_from_id'));
|
||||
if ($cloned_model_img) {
|
||||
$new_image_name = 'clone-'.date('U').'-'.$cloned_model_img->image;
|
||||
$new_image = 'accessories/'.$new_image_name;
|
||||
Storage::disk('public')->copy('accessories/'.$cloned_model_img->image, $new_image);
|
||||
$accessory->image = $new_image_name;
|
||||
}
|
||||
|
||||
} else {
|
||||
$accessory = $request->handleImages($accessory);
|
||||
}
|
||||
|
||||
if($request->get('redirect_option') === 'back'){
|
||||
session()->put(['redirect_option' => 'index']);
|
||||
} else {
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
}
|
||||
$accessory = $request->handleImages($accessory);
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
// Was the accessory created?
|
||||
if ($accessory->save()) {
|
||||
// Redirect to the new accessory page
|
||||
@@ -130,12 +114,11 @@ class AccessoriesController extends Controller
|
||||
|
||||
$this->authorize('create', Accessory::class);
|
||||
$cloned = clone $accessory;
|
||||
$accessory_to_clone = $accessory;
|
||||
$cloned->id = null;
|
||||
$cloned->deleted_at = '';
|
||||
$cloned->location_id = null;
|
||||
|
||||
return view('accessories/edit')
|
||||
->with('cloned_model', $accessory_to_clone)
|
||||
->with('item', $cloned);
|
||||
|
||||
}
|
||||
|
||||
132
app/Http/Controllers/Accessories/AccessoriesFilesController.php
Normal file
132
app/Http/Controllers/Accessories/AccessoriesFilesController.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Accessories;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Accessory;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use \Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
class AccessoriesFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a accessory.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $accessoryId
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $accessoryId = null) : RedirectResponse
|
||||
{
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('accessories.show', ['accessory'=>$accessoryId])->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
$accessory = Accessory::find($accessoryId);
|
||||
|
||||
if (isset($accessory->id)) {
|
||||
$this->authorize('accessories.files', $accessory);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/accessories')) {
|
||||
Storage::makeDirectory('private_uploads/accessories', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$file_name = $request->handleFile('private_uploads/accessories/', 'accessory-'.$accessory->id, $file);
|
||||
//Log the upload to the log
|
||||
$accessory->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('accessories.show', $accessory->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.show', $accessory->id)->withFragment('files')->with('error', trans('general.no_files_uploaded'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected accessory file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $accessoryId
|
||||
* @param int $fileId
|
||||
*/
|
||||
public function destroy($accessoryId = null, $fileId = null) : RedirectResponse
|
||||
{
|
||||
if ($accessory = Accessory::find($accessoryId)) {
|
||||
$this->authorize('update', $accessory);
|
||||
|
||||
if ($log = Actionlog::find($fileId)) {
|
||||
|
||||
if (Storage::exists('private_uploads/accessories/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('private_uploads/accessories/' . $log->filename);
|
||||
$log->delete();
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e);
|
||||
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return redirect()->route('accessories.show', ['accessory' => $accessory])->withFragment('files')->with('error', trans('general.log_record_not_found'));
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $accessoryId
|
||||
* @param int $fileId
|
||||
*/
|
||||
public function show($accessoryId = null, $fileId = null) : View | RedirectResponse | Response | BinaryFileResponse | StreamedResponse
|
||||
{
|
||||
|
||||
|
||||
// the accessory is valid
|
||||
if ($accessory = Accessory::find($accessoryId)) {
|
||||
$this->authorize('view', $accessory);
|
||||
$this->authorize('accessories.files', $accessory);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $accessory->id)->find($fileId)) {
|
||||
$file = 'private_uploads/accessories/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('accessories.show', ['accessory' => $accessory])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.show', ['accessory' => $accessory])->withFragment('files')->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,6 @@ class AccessoryCheckoutController extends Controller
|
||||
$this->authorize('checkout', $accessory);
|
||||
|
||||
$target = $this->determineCheckoutTarget();
|
||||
session()->put(['checkout_to_type' => $target]);
|
||||
|
||||
$accessory->checkout_qty = $request->input('checkout_qty', 1);
|
||||
|
||||
|
||||
@@ -30,12 +30,11 @@ use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Str;
|
||||
use App\Http\Controllers\SettingsController;
|
||||
use Barryvdh\DomPDF\Facade\Pdf;
|
||||
use Carbon\Carbon;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use \Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use TCPDF;
|
||||
use App\Helpers\Helper;
|
||||
|
||||
class AcceptanceController extends Controller
|
||||
{
|
||||
@@ -179,7 +178,7 @@ class AcceptanceController extends Controller
|
||||
break;
|
||||
|
||||
case 'App\Models\Component':
|
||||
$pdf_view_route = 'account.accept.accept-component-eula';
|
||||
$pdf_view_route ='account.accept.accept-component-eula';
|
||||
$component = Component::find($item->id);
|
||||
$display_model = $component->name;
|
||||
break;
|
||||
@@ -218,7 +217,7 @@ class AcceptanceController extends Controller
|
||||
} elseif (!is_null($branding_settings->logo)) {
|
||||
$path_logo = public_path() . '/uploads/' . $branding_settings->logo;
|
||||
}
|
||||
|
||||
|
||||
$data = [
|
||||
'item_tag' => $item->asset_tag,
|
||||
'item_model' => $display_model,
|
||||
@@ -226,113 +225,37 @@ class AcceptanceController extends Controller
|
||||
'item_status' => $item->assetstatus?->name,
|
||||
'eula' => $item->getEula(),
|
||||
'note' => $request->input('note'),
|
||||
'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d H:i:s'),
|
||||
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d H:i:s'),
|
||||
'assigned_to' => $assigned_user->display_name,
|
||||
'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d'),
|
||||
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d'),
|
||||
'assigned_to' => $assigned_user->present()->fullName,
|
||||
'company_name' => $branding_settings->site_name,
|
||||
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
|
||||
'logo' => $path_logo,
|
||||
'date_settings' => $branding_settings->date_display_format,
|
||||
'admin' => auth()->user()->present()?->fullName,
|
||||
];
|
||||
|
||||
|
||||
if ($pdf_view_route!='') {
|
||||
Log::debug($pdf_filename.' is the filename, and the route was specified.');
|
||||
//$pdf = new PDF;
|
||||
|
||||
// set some language dependent data:
|
||||
$lg = Array();
|
||||
$lg['a_meta_charset'] = 'UTF-8';
|
||||
$lg['w_page'] = 'page';
|
||||
|
||||
$pdf = new TCPDF('P', 'mm', 'A4', true, 'UTF-8', false);
|
||||
// $pdf->SetHeaderData(PDF_HEADER_LOGO, 5, PDF_HEADER_TITLE.' 006', PDF_HEADER_STRING);
|
||||
// $pdf->SetHeaderData('https://snipe-it.test/uploads/snipe-logo.png', '5', $data['company_name'], $item->company?->name);
|
||||
//$pdf->headerText = ('Anything you want ' . date('c'));
|
||||
$pdf->setRTL(false);
|
||||
//$pdf->SetHeaderData(PDF_HEADER_LOGO, PDF_HEADER_LOGO_WIDTH, $data['company_name'], '');
|
||||
$pdf->setLanguageArray($lg);
|
||||
$pdf->SetCreator('Snipe-IT');
|
||||
$pdf->SetAuthor($data['assigned_to']);
|
||||
$pdf->SetTitle('Asset Acceptance: '.$data['item_tag']);
|
||||
// $pdf->SetSubject('Document Subject');
|
||||
//$pdf->SetKeywords('keywords, here');
|
||||
$pdf->SetFont('dejavusans', '', 8, '', true);
|
||||
|
||||
|
||||
$pdf->SetPrintHeader(false);
|
||||
$pdf->SetPrintFooter(false);
|
||||
$pdf->setHeaderFont(Array(PDF_FONT_NAME_MAIN, '', PDF_FONT_SIZE_MAIN));
|
||||
$pdf->setFooterFont(Array(PDF_FONT_NAME_DATA, '', PDF_FONT_SIZE_DATA));
|
||||
|
||||
$pdf->AddPage();
|
||||
$pdf->writeHTML('<img src="'.$path_logo.'" height="30">', true, 0, true, 0, '');
|
||||
|
||||
// $pdf->writeHTML(trans('general.date').': '.date($data['date_settings']), true, 0, true, 0, '');
|
||||
$pdf->writeHTML("<strong>".trans('general.asset_tag').'</strong>: '.$data['item_tag'], true, 0, true, 0, '');
|
||||
$pdf->writeHTML("<strong>".trans('general.asset_model').'</strong>: '.$data['item_model'], true, 0, true, 0, '');
|
||||
$pdf->writeHTML("<strong>".trans('admin/hardware/form.serial').'</strong>: '.$data['item_serial'], true, 0, true, 0, '');
|
||||
$pdf->writeHTML("<strong>".trans('general.assigned_date').'</strong>: '.$data['check_out_date'], true, 0, true, 0, '');
|
||||
$pdf->writeHTML("<strong>".trans('general.assignee').'</strong>: '.$data['assigned_to'], true, 0, true, 0, '');
|
||||
$pdf->Ln();
|
||||
// $html = view($pdf_view_route, $data)->render();
|
||||
// $pdf->writeHTML($html, true, 0, true, 0, '');
|
||||
|
||||
// $eula_lines = explode("\n\n", $item->getEula());
|
||||
$eula_lines = preg_split("/\r\n|\n|\r/", $item->getEula());
|
||||
|
||||
foreach ($eula_lines as $eula_line) {
|
||||
if (Helper::hasRtl($eula_line)) {
|
||||
$pdf->setRTL(true);
|
||||
} else {
|
||||
$pdf->setRTL(false);
|
||||
}
|
||||
$pdf->writeHTML(Helper::parseEscapedMarkedown($eula_line), true, 0, true, 0, '');
|
||||
}
|
||||
$pdf->Ln();
|
||||
$pdf->Ln();
|
||||
$pdf->setRTL(false);
|
||||
$pdf->writeHTML('<br><br>', true, 0, true, 0, '');
|
||||
|
||||
if ($data['note'] != null) {
|
||||
$pdf->writeHTML("<strong>".trans('general.notes') . '</strong>: ' . $data['note'], true, 0, true, 0, '');
|
||||
$pdf->Ln();
|
||||
}
|
||||
|
||||
if ($data['signature'] != null) {
|
||||
|
||||
$pdf->writeHTML('<img src="'.$data['signature'].'" style="max-width: 600px;">', true, 0, true, 0, '');
|
||||
$pdf->writeHTML('<hr>', true, 0, true, 0, '');
|
||||
}
|
||||
|
||||
$pdf->writeHTML("<strong>".trans('general.accepted_date').'</strong>: '.$data['accepted_date'], true, 0, true, 0, '');
|
||||
|
||||
|
||||
$pdf_content = $pdf->Output($pdf_filename, 'S');
|
||||
|
||||
|
||||
//$html = view($pdf_view_route, $data)->render();
|
||||
//$pdf = PDF::writeHTML($html, true, false, true, false, '');
|
||||
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf_content);
|
||||
$pdf = Pdf::loadView($pdf_view_route, $data);
|
||||
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
|
||||
}
|
||||
|
||||
// $acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note'));
|
||||
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note'));
|
||||
|
||||
// Send the PDF to the signing user
|
||||
if (($request->input('send_copy') == '1') && ($assigned_user->email !='')) {
|
||||
|
||||
// Add the attachment for the signing user into the $data array
|
||||
$data['file'] = $pdf_filename;
|
||||
$locale = $assigned_user->locale;
|
||||
|
||||
try {
|
||||
$assigned_user->notify((new AcceptanceAssetAcceptedToUserNotification($data))->locale($locale));
|
||||
$assigned_user->notify(new AcceptanceAssetAcceptedToUserNotification($data));
|
||||
} catch (\Exception $e) {
|
||||
Log::warning($e);
|
||||
}
|
||||
}
|
||||
try {
|
||||
$acceptance->notify((new AcceptanceAssetAcceptedNotification($data))->locale(Setting::getSettings()->locale));
|
||||
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
|
||||
} catch (\Exception $e) {
|
||||
Log::warning($e);
|
||||
}
|
||||
@@ -424,7 +347,6 @@ class AcceptanceController extends Controller
|
||||
|
||||
$acceptance->decline($sig_filename, $request->input('note'));
|
||||
$acceptance->notify(new AcceptanceAssetDeclinedNotification($data));
|
||||
Log::debug('New event acceptance.');
|
||||
event(new CheckoutDeclined($acceptance));
|
||||
$return_msg = trans('admin/users/message.declined');
|
||||
}
|
||||
@@ -434,16 +356,13 @@ class AcceptanceController extends Controller
|
||||
$recipient = User::find($acceptance->alert_on_response_id);
|
||||
|
||||
if ($recipient) {
|
||||
Log::debug('Attempting to send email acceptance.');
|
||||
Mail::to($recipient)->send(new CheckoutAcceptanceResponseMail(
|
||||
$acceptance,
|
||||
$recipient,
|
||||
$request->input('asset_acceptance') === 'accepted',
|
||||
));
|
||||
Log::debug('Send email notification sucess on checkout acceptance response.');
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Log::error($e->getMessage());
|
||||
Log::warning($e);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -288,42 +288,32 @@ class AccessoriesController extends Controller
|
||||
'note' => $request->input('note'),
|
||||
]);
|
||||
|
||||
|
||||
$accessory_checkout->created_by = auth()->id();
|
||||
$accessory_checkout->save();
|
||||
|
||||
$payload = [
|
||||
'accessory_id' => $accessory->id,
|
||||
'assigned_to' => $target->id,
|
||||
'assigned_type' => $target::class,
|
||||
'note' => $request->input('note'),
|
||||
'created_by' => auth()->id(),
|
||||
'pivot' => $accessory_checkout->id,
|
||||
];
|
||||
}
|
||||
|
||||
// Set this value to be able to pass the qty through to the event
|
||||
event(new CheckoutableCheckedOut($accessory, $target, auth()->user(), $request->input('note')));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $payload, trans('admin/accessories/message.checkout.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkout.success')));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Check in the item so that it can be checked out again to someone else
|
||||
*
|
||||
* @uses Accessory::checkin_email() to determine if an email can and should be sent
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param Request $request
|
||||
* @param int $accessoryUserId
|
||||
* @param string $backto
|
||||
* @return JsonResponse
|
||||
* @uses Accessory::checkin_email() to determine if an email can and should be sent
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @internal param int $accessoryId
|
||||
*/
|
||||
public function checkin(Request $request, $accessoryUserId = null)
|
||||
{
|
||||
if (is_null($accessory_checkout = AccessoryCheckout::find($accessoryUserId))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.does_not_exist', ['id' => $accessoryUserId])));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.does_not_exist')));
|
||||
}
|
||||
|
||||
$accessory = Accessory::find($accessory_checkout->accessory_id);
|
||||
@@ -337,14 +327,7 @@ class AccessoriesController extends Controller
|
||||
$user = User::find($accessory_checkout->assigned_to);
|
||||
}
|
||||
|
||||
$payload = [
|
||||
'accessory_id' => $accessory->id,
|
||||
'note' => $request->input('note'),
|
||||
'created_by' => auth()->id(),
|
||||
'pivot' => $accessory_checkout->id,
|
||||
];
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $payload, trans('admin/accessories/message.checkin.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkin.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.checkin.error')));
|
||||
|
||||
@@ -4,11 +4,11 @@ namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Transformers\MaintenancesTransformer;
|
||||
use App\Http\Transformers\AssetMaintenancesTransformer;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Maintenance;
|
||||
use App\Models\AssetMaintenance;
|
||||
use App\Models\Company;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
|
||||
@@ -18,13 +18,13 @@ use Illuminate\Http\JsonResponse;
|
||||
*
|
||||
* @version v2.0
|
||||
*/
|
||||
class MaintenancesController extends Controller
|
||||
class AssetMaintenancesController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Generates the JSON response for asset maintenances listing view.
|
||||
*
|
||||
* @see MaintenancesController::getIndex() method that generates view
|
||||
* @see AssetMaintenancesController::getIndex() method that generates view
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
@@ -33,7 +33,7 @@ class MaintenancesController extends Controller
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
$maintenances = Maintenance::select('maintenances.*')
|
||||
$maintenances = AssetMaintenance::select('asset_maintenances.*')
|
||||
->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.assetstatus', 'adminuser');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
@@ -45,11 +45,11 @@ class MaintenancesController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('supplier_id')) {
|
||||
$maintenances->where('maintenances.supplier_id', '=', $request->input('supplier_id'));
|
||||
$maintenances->where('asset_maintenances.supplier_id', '=', $request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('created_by')) {
|
||||
$maintenances->where('maintenances.created_by', '=', $request->input('created_by'));
|
||||
$maintenances->where('asset_maintenances.created_by', '=', $request->input('created_by'));
|
||||
}
|
||||
|
||||
if ($request->filled('asset_maintenance_type')) {
|
||||
@@ -63,7 +63,7 @@ class MaintenancesController extends Controller
|
||||
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
'name',
|
||||
'title',
|
||||
'asset_maintenance_time',
|
||||
'asset_maintenance_type',
|
||||
'cost',
|
||||
@@ -112,7 +112,7 @@ class MaintenancesController extends Controller
|
||||
|
||||
$total = $maintenances->count();
|
||||
$maintenances = $maintenances->skip($offset)->take($limit)->get();
|
||||
return (new MaintenancesTransformer())->transformMaintenances($maintenances, $total);
|
||||
return (new AssetMaintenancesTransformer())->transformAssetMaintenances($maintenances, $total);
|
||||
|
||||
|
||||
}
|
||||
@@ -121,23 +121,22 @@ class MaintenancesController extends Controller
|
||||
/**
|
||||
* Validates and stores the new asset maintenance
|
||||
*
|
||||
* @see MaintenancesController::getCreate() method for the form
|
||||
* @see AssetMaintenancesController::getCreate() method for the form
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function store(ImageUploadRequest $request) : JsonResponse | array
|
||||
public function store(Request $request) : JsonResponse | array
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
// create a new model instance
|
||||
$maintenance = new Maintenance();
|
||||
$maintenance = new AssetMaintenance();
|
||||
$maintenance->fill($request->all());
|
||||
$maintenance->created_by = auth()->id();
|
||||
$maintenance = $request->handleImages($maintenance);
|
||||
|
||||
// Was the asset maintenance created?
|
||||
if ($maintenance->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/maintenances/message.create.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/asset_maintenances/message.create.success')));
|
||||
|
||||
}
|
||||
|
||||
@@ -158,11 +157,11 @@ class MaintenancesController extends Controller
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
if ($maintenance = Maintenance::with('asset')->find($id)) {
|
||||
if ($maintenance = AssetMaintenance::with('asset')->find($id)) {
|
||||
|
||||
// Can this user manage this asset?
|
||||
if (! Company::isCurrentUserHasAccess($maintenance->asset)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.action_permission_denied', ['item_type' => trans('admin/maintenances/general.maintenance'), 'id' => $id, 'action' => trans('general.edit')])));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.action_permission_denied', ['item_type' => trans('admin/asset_maintenances/general.maintenance'), 'id' => $id, 'action' => trans('general.edit')])));
|
||||
}
|
||||
|
||||
// The asset this miantenance is attached to is not valid or has been deleted
|
||||
@@ -173,13 +172,13 @@ class MaintenancesController extends Controller
|
||||
$maintenance->fill($request->all());
|
||||
|
||||
if ($maintenance->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/maintenances/message.edit.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/asset_maintenances/message.edit.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $maintenance->getErrors()));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.item_not_found', ['item_type' => trans('admin/maintenances/general.maintenance'), 'id' => $id])));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.item_not_found', ['item_type' => trans('admin/asset_maintenances/general.maintenance'), 'id' => $id])));
|
||||
|
||||
}
|
||||
|
||||
@@ -187,20 +186,20 @@ class MaintenancesController extends Controller
|
||||
* Delete an asset maintenance
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @param int $maintenanceId
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v4.0]
|
||||
*/
|
||||
public function destroy($maintenanceId) : JsonResponse | array
|
||||
public function destroy($assetMaintenanceId) : JsonResponse | array
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
|
||||
$maintenance = Maintenance::findOrFail($maintenanceId);
|
||||
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
|
||||
|
||||
$maintenance->delete();
|
||||
$assetMaintenance->delete();
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $maintenance, trans('admin/maintenances/message.delete.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.delete.success')));
|
||||
|
||||
|
||||
}
|
||||
@@ -209,19 +208,19 @@ class MaintenancesController extends Controller
|
||||
* View an asset maintenance
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @param int $maintenanceId
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v4.0]
|
||||
*/
|
||||
public function show($maintenanceId) : JsonResponse | array
|
||||
public function show($assetMaintenanceId) : JsonResponse | array
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
$maintenance = Maintenance::findOrFail($maintenanceId);
|
||||
if (! Company::isCurrentUserHasAccess($maintenance->asset)) {
|
||||
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
|
||||
if (! Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot view a maintenance for that asset'));
|
||||
}
|
||||
|
||||
return (new MaintenancesTransformer())->transformMaintenance($maintenance);
|
||||
return (new AssetMaintenancesTransformer())->transformAssetMaintenance($assetMaintenance);
|
||||
|
||||
}
|
||||
}
|
||||
@@ -50,7 +50,6 @@ class AssetModelsController extends Controller
|
||||
'fieldset',
|
||||
'deleted_at',
|
||||
'updated_at',
|
||||
'require_serial',
|
||||
];
|
||||
|
||||
$assetmodels = AssetModel::select([
|
||||
@@ -70,7 +69,6 @@ class AssetModelsController extends Controller
|
||||
'models.fieldset_id',
|
||||
'models.deleted_at',
|
||||
'models.updated_at',
|
||||
'models.require_serial'
|
||||
])
|
||||
->with('category', 'depreciation', 'manufacturer', 'fieldset.fields.defaultValues', 'adminuser')
|
||||
->withCount('assets as assets_count');
|
||||
@@ -156,7 +154,7 @@ class AssetModelsController extends Controller
|
||||
$assetmodel = $request->handleImages($assetmodel);
|
||||
|
||||
if ($assetmodel->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new AssetModelsTransformer)->transformAssetModel($assetmodel), trans('admin/models/message.create.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/models/message.create.success')));
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $assetmodel->getErrors()));
|
||||
|
||||
@@ -209,7 +207,7 @@ class AssetModelsController extends Controller
|
||||
$assetmodel = AssetModel::findOrFail($id);
|
||||
$assetmodel->fill($request->all());
|
||||
$assetmodel = $request->handleImages($assetmodel);
|
||||
|
||||
|
||||
/**
|
||||
* Allow custom_fieldset_id to override and populate fieldset_id.
|
||||
* This is stupid, but required for legacy API support.
|
||||
@@ -224,7 +222,7 @@ class AssetModelsController extends Controller
|
||||
|
||||
|
||||
if ($assetmodel->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new AssetModelsTransformer)->transformAssetModel($assetmodel), trans('admin/models/message.update.success')));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetmodel, trans('admin/models/message.update.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $assetmodel->getErrors()));
|
||||
|
||||
@@ -117,20 +117,15 @@ class AssetsController extends Controller
|
||||
'jobtitle',
|
||||
];
|
||||
|
||||
$all_custom_fields = CustomField::all(); //used as a 'cache' of custom fields throughout this page load
|
||||
|
||||
foreach ($all_custom_fields as $field) {
|
||||
$allowed_columns[] = $field->db_column_name();
|
||||
}
|
||||
|
||||
$filter = [];
|
||||
|
||||
if ($request->filled('filter')) {
|
||||
$filter = json_decode($request->input('filter'), true);
|
||||
}
|
||||
|
||||
$filter = array_filter($filter, function ($key) use ($allowed_columns) {
|
||||
return in_array($key, $allowed_columns);
|
||||
}, ARRAY_FILTER_USE_KEY);
|
||||
$all_custom_fields = CustomField::all(); //used as a 'cache' of custom fields throughout this page load
|
||||
foreach ($all_custom_fields as $field) {
|
||||
$allowed_columns[] = $field->db_column_name();
|
||||
}
|
||||
|
||||
$assets = Asset::select('assets.*')
|
||||
@@ -146,7 +141,6 @@ class AssetsController extends Controller
|
||||
'model.category',
|
||||
'model.manufacturer',
|
||||
'model.fieldset',
|
||||
'model.depreciation',
|
||||
'supplier'
|
||||
); // it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
|
||||
|
||||
@@ -610,7 +604,7 @@ class AssetsController extends Controller
|
||||
$asset->use_text = $asset->present()->fullName;
|
||||
|
||||
if (($asset->checkedOutToUser()) && ($asset->assigned)) {
|
||||
$asset->use_text .= ' → ' . $asset->assigned->display_name;
|
||||
$asset->use_text .= ' → ' . $asset->assigned->getFullNameAttribute();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -228,16 +228,11 @@ class ConsumablesController extends Controller
|
||||
foreach ($consumable->consumableAssignments as $consumable_assignment) {
|
||||
$rows[] = [
|
||||
'avatar' => ($consumable_assignment->user) ? e($consumable_assignment->user->present()->gravatar) : '',
|
||||
'user' => ($consumable_assignment->user) ? [
|
||||
'id' => (int) $consumable_assignment->user->id,
|
||||
'name'=> e($consumable_assignment->user->display_name),
|
||||
] : null,
|
||||
'name' => ($consumable_assignment->user) ? $consumable_assignment->user->present()->nameUrl() : 'Deleted User',
|
||||
'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'),
|
||||
'note' => ($consumable_assignment->note) ? e($consumable_assignment->note) : null,
|
||||
'created_by' => ($consumable_assignment->adminuser) ? [
|
||||
'id' => (int) $consumable_assignment->adminuser->id,
|
||||
'name'=> e($consumable_assignment->adminuser->display_name),
|
||||
] : null,
|
||||
'admin' => ($consumable_assignment->adminuser) ? $consumable_assignment->adminuser->present()->nameUrl() : null, // legacy, so we don't change the shape of the response
|
||||
'created_by' => ($consumable_assignment->adminuser) ? $consumable_assignment->adminuser->present()->nameUrl() : null,
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ class ImportController extends Controller
|
||||
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::debug("Discovered encoding: $encoding in uploaded CSV");
|
||||
\Log::warning("Discovered encoding: $encoding in uploaded CSV");
|
||||
$reader = null;
|
||||
if (strcasecmp($encoding, 'UTF-8') != 0) {
|
||||
$transliterated = false;
|
||||
@@ -103,7 +103,7 @@ class ImportController extends Controller
|
||||
$reader = Reader::createFromFileObject($file->openFile('r')); //file pointer leak?
|
||||
|
||||
try {
|
||||
$import->header_row = $reader->nth(0);
|
||||
$import->header_row = $reader->fetchOne(0);
|
||||
} catch (JsonEncodingException $e) {
|
||||
return response()->json(
|
||||
Helper::formatStandardApiResponse(
|
||||
@@ -136,7 +136,7 @@ class ImportController extends Controller
|
||||
|
||||
try {
|
||||
// Grab the first row to display via ajax as the user picks fields
|
||||
$import->first_row = $reader->nth(1);
|
||||
$import->first_row = $reader->fetchOne(1);
|
||||
} catch (JsonEncodingException $e) {
|
||||
return response()->json(
|
||||
Helper::formatStandardApiResponse(
|
||||
@@ -195,7 +195,7 @@ class ImportController extends Controller
|
||||
// Run a backup immediately before processing
|
||||
if ($request->get('run-backup')) {
|
||||
Log::debug('Backup manually requested via importer');
|
||||
Artisan::call('snipeit:backup', ['--filename' => 'pre-import-backup-'.date('Y-m-d-H-i-s')]);
|
||||
Artisan::call('snipeit:backup', ['--filename' => 'pre-import-backup-'.date('Y-m-d-H:i:s')]);
|
||||
} else {
|
||||
Log::debug('NO BACKUP requested via importer');
|
||||
}
|
||||
|
||||
@@ -128,9 +128,7 @@ class LicenseSeatsController extends Controller
|
||||
// nothing to update
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $licenseSeat, trans('admin/licenses/message.update.success')));
|
||||
}
|
||||
if( $touched && $licenseSeat->unreassignable_seat) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/licenses/message.checkout.unavailable')));
|
||||
}
|
||||
|
||||
// the logging functions expect only one "target". if both asset and user are present in the request,
|
||||
// we simply let assets take precedence over users...
|
||||
if ($licenseSeat->isDirty('assigned_to')) {
|
||||
@@ -147,11 +145,7 @@ class LicenseSeatsController extends Controller
|
||||
if ($licenseSeat->save()) {
|
||||
|
||||
if ($is_checkin) {
|
||||
if(!$licenseSeat->license->reassignable){
|
||||
$licenseSeat->unreassignable_seat = true;
|
||||
$licenseSeat->save();
|
||||
}
|
||||
$licenseSeat->logCheckin($target, $licenseSeat->notes);
|
||||
$licenseSeat->logCheckin($target, $request->input('notes'));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $licenseSeat, trans('admin/licenses/message.update.success')));
|
||||
}
|
||||
|
||||
@@ -1,95 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* This class controls all API actions related to notes for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*/
|
||||
class NotesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Retrieve a list of manual notes (action logs) for a given asset.
|
||||
*
|
||||
* Checks authorization to view assets, attempts to find the asset by ID,
|
||||
* and fetches related action log entries of type 'note added', including
|
||||
* user information for each note. Returns a JSON response with the notes or errors.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The incoming HTTP request.
|
||||
* @param Asset $asset The ID of the asset whose notes to retrieve.
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function index(Asset $asset): JsonResponse
|
||||
{
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
// Get the manual notes for the asset
|
||||
$notes = ActionLog::with('user:id,username')
|
||||
->where('item_type', Asset::class)
|
||||
->where('item_id', $asset->id)
|
||||
->where('action_type', 'note added')
|
||||
->orderBy('created_at', 'desc')
|
||||
->get(['id', 'created_at', 'note', 'created_by', 'item_id', 'item_type', 'action_type', 'target_id', 'target_type']);
|
||||
|
||||
$notesArray = $notes->map(function ($note) {
|
||||
return [
|
||||
'id' => $note->id,
|
||||
'created_at' => $note->created_at,
|
||||
'note' => $note->note,
|
||||
'created_by' => $note->created_by,
|
||||
'username' => $note->user?->username, // adding the username
|
||||
'item_id' => $note->item_id,
|
||||
'item_type' => $note->item_type,
|
||||
'action_type' => $note->action_type,
|
||||
];
|
||||
});
|
||||
|
||||
// Return a success response
|
||||
return response()->json(Helper::formatStandardApiResponse('success', ['notes' => $notesArray, 'asset_id' => $asset->id]));
|
||||
}
|
||||
|
||||
/**
|
||||
* Store a manual note on a specified asset and log the action.
|
||||
*
|
||||
* Checks authorization for updating assets, validates the presence of the 'note',
|
||||
* attempts to find the asset by ID, and creates a new ActionLog entry if successful.
|
||||
* Returns JSON responses indicating success or failure with appropriate HTTP status codes.
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request The incoming HTTP request containing the 'note'.
|
||||
* @param Asset $asset The ID of the asset to attach the note to.
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function store(Request $request, Asset $asset): JsonResponse
|
||||
{
|
||||
$this->authorize('update', $asset);
|
||||
|
||||
if ($request->input('note', '') == '') {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('validation.required', ['attribute' => 'note'])), 422);
|
||||
}
|
||||
|
||||
// Create the note
|
||||
$logaction = new ActionLog();
|
||||
$logaction->item_type = get_class($asset);
|
||||
$logaction->created_by = Auth::id();
|
||||
$logaction->item_id = $asset->id;
|
||||
$logaction->note = $request->input('note', '');
|
||||
|
||||
if ($logaction->logaction('note added')) {
|
||||
// Return a success response
|
||||
return response()->json(Helper::formatStandardApiResponse('success', ['note' => $logaction->note, 'item_id' => $asset->id], trans('general.note_added')));
|
||||
}
|
||||
|
||||
// Return an error response if something went wrong
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Something went wrong'), 500);
|
||||
}
|
||||
}
|
||||
@@ -69,7 +69,7 @@ class ProfileController extends Controller
|
||||
if ($checkoutRequest && $checkoutRequest->itemRequested()) {
|
||||
$assets = [
|
||||
'image' => e($checkoutRequest->itemRequested()->present()->getImageUrl()),
|
||||
'name' => e($checkoutRequest->itemRequested()->display_name),
|
||||
'name' => e($checkoutRequest->itemRequested()->present()->name()),
|
||||
'type' => e($checkoutRequest->itemType()),
|
||||
'qty' => (int) $checkoutRequest->quantity,
|
||||
'location' => ($checkoutRequest->location()) ? e($checkoutRequest->location()->name) : null,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Transformers\DatatablesTransformer;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
@@ -50,22 +51,10 @@ class SettingsController extends Controller
|
||||
})->slice(0, 10)->map(function ($item) use ($settings) {
|
||||
return (object) [
|
||||
'username' => $item[$settings['ldap_username_field']][0] ?? null,
|
||||
'display_name' => $item[$settings['ldap_display_name']][0] ?? null,
|
||||
'employee_number' => $item[$settings['ldap_emp_num']][0] ?? null,
|
||||
'lastname' => $item[$settings['ldap_lname_field']][0] ?? null,
|
||||
'firstname' => $item[$settings['ldap_fname_field']][0] ?? null,
|
||||
'email' => $item[$settings['ldap_email']][0] ?? null,
|
||||
'phone' => $item[$settings['ldap_phone_field']][0] ?? null,
|
||||
'mobile' => $item[$settings['ldap_mobile']][0] ?? null,
|
||||
'jobtitle' => $item[$settings['ldap_jobtitle']][0] ?? null,
|
||||
'department' => $item[$settings['ldap_department']][0] ?? null,
|
||||
'manager' => $item[$settings['ldap_manager']][0] ?? null,
|
||||
'address' => $item[$settings['ldap_address']][0] ?? null,
|
||||
'city' => $item[$settings['ldap_city']][0] ?? null,
|
||||
'state' => $item[$settings['ldap_state']][0] ?? null,
|
||||
'zip' => $item[$settings['ldap_zip']][0] ?? null,
|
||||
'country' => $item[$settings['ldap_country']][0] ?? null,
|
||||
'location' => $item[$settings['ldap_location']][0] ?? null,
|
||||
];
|
||||
});
|
||||
if ($users->count() > 0) {
|
||||
@@ -89,7 +78,7 @@ class SettingsController extends Controller
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::debug('Connection failed but we cannot debug it any further on our end.');
|
||||
return response()->json(['message' => $e->getMessage()], 400);
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
|
||||
|
||||
@@ -161,11 +150,8 @@ class SettingsController extends Controller
|
||||
if (!config('app.lock_passwords')) {
|
||||
try {
|
||||
Notification::send(Setting::first(), new MailTest());
|
||||
Log::debug('Attempting to sending to '.config('mail.reply_to.address'));
|
||||
return response()->json(['message' => 'Mail sent to '.config('mail.reply_to.address')], 200);
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Mail sent error using '.config('mail.reply_to.address') .': '. $e->getMessage());
|
||||
Log::debug($e);
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
}
|
||||
@@ -329,4 +315,4 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
@@ -194,7 +194,7 @@ class SuppliersController extends Controller
|
||||
public function destroy($id) : JsonResponse
|
||||
{
|
||||
$this->authorize('delete', Supplier::class);
|
||||
$supplier = Supplier::with('maintenances', 'assets', 'licenses')->withCount('maintenances as maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->findOrFail($id);
|
||||
$supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->findOrFail($id);
|
||||
$this->authorize('delete', $supplier);
|
||||
|
||||
|
||||
@@ -202,8 +202,8 @@ class SuppliersController extends Controller
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_assets', ['asset_count' => (int) $supplier->assets_count])));
|
||||
}
|
||||
|
||||
if ($supplier->maintenances_count > 0) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_maintenances', ['maintenances_count' => $supplier->maintenances_count])));
|
||||
if ($supplier->asset_maintenances_count > 0) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/suppliers/message.delete.assoc_maintenances', ['asset_maintenances_count' => $supplier->asset_maintenances_count])));
|
||||
}
|
||||
|
||||
if ($supplier->licenses_count > 0) {
|
||||
|
||||
@@ -7,9 +7,18 @@ use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Http\Transformers\UploadedFilesTransformer;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Component;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\License;
|
||||
use App\Models\Location;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
@@ -19,6 +28,45 @@ class UploadedFilesController extends Controller
|
||||
{
|
||||
|
||||
|
||||
static $map_object_type = [
|
||||
'accessories' => Accessory::class,
|
||||
'assets' => Asset::class,
|
||||
'components' => Component::class,
|
||||
'consumables' => Consumable::class,
|
||||
'hardware' => Asset::class,
|
||||
'licenses' => License::class,
|
||||
'locations' => Location::class,
|
||||
'models' => AssetModel::class,
|
||||
'users' => User::class,
|
||||
];
|
||||
|
||||
static $map_storage_path = [
|
||||
'accessories' => 'private_uploads/accessories/',
|
||||
'assets' => 'private_uploads/assets/',
|
||||
'components' => 'private_uploads/components/',
|
||||
'consumables' => 'private_uploads/consumables/',
|
||||
'hardware' => 'private_uploads/assets/',
|
||||
'licenses' => 'private_uploads/licenses/',
|
||||
'locations' => 'private_uploads/locations/',
|
||||
'models' => 'private_uploads/assetmodels/',
|
||||
'users' => 'private_uploads/users/',
|
||||
];
|
||||
|
||||
static $map_file_prefix= [
|
||||
'accessories' => 'accessory',
|
||||
'assets' => 'asset',
|
||||
'components' => 'component',
|
||||
'consumables' => 'consumable',
|
||||
'hardware' => 'asset',
|
||||
'licenses' => 'license',
|
||||
'locations' => 'location',
|
||||
'models' => 'model',
|
||||
'users' => 'user',
|
||||
];
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* List files for an object
|
||||
*
|
||||
@@ -32,7 +80,7 @@ class UploadedFilesController extends Controller
|
||||
{
|
||||
|
||||
// Check the permissions to make sure the user can view the object
|
||||
$object = self::$map_object_type[$object_type]::withTrashed()->find($id);
|
||||
$object = self::$map_object_type[$object_type]::find($id);
|
||||
$this->authorize('view', $object);
|
||||
|
||||
if (!$object) {
|
||||
@@ -45,23 +93,19 @@ class UploadedFilesController extends Controller
|
||||
'id',
|
||||
'filename',
|
||||
'action_type',
|
||||
'action_date',
|
||||
'note',
|
||||
'created_at',
|
||||
];
|
||||
|
||||
|
||||
$uploads = self::$map_object_type[$object_type]::withTrashed()->find($id)->uploads()
|
||||
->with('adminuser');
|
||||
|
||||
$offset = ($request->input('offset') > $uploads->count()) ? $uploads->count() : abs($request->input('offset'));
|
||||
$uploads = $object->uploads();
|
||||
$offset = ($request->input('offset') > $object->count()) ? $object->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'action_logs.created_at';
|
||||
|
||||
// Text search on action_logs fields
|
||||
// We could use the normal Actionlogs text scope, but it's a very heavy query since it's searching across all relations
|
||||
// and we generally won't need that here
|
||||
// We could use the normal Actionlogs text scope, but it's a very heavy query since it's searcghing across all relations
|
||||
// And we generally won't need that here
|
||||
if ($request->filled('search')) {
|
||||
|
||||
$uploads->where(
|
||||
@@ -72,10 +116,8 @@ class UploadedFilesController extends Controller
|
||||
);
|
||||
}
|
||||
|
||||
$total = $uploads->count();
|
||||
$uploads = $uploads->skip($offset)->take($limit)->orderBy($sort, $order)->get();
|
||||
|
||||
return (new UploadedFilesTransformer())->transformFiles($uploads, $total);
|
||||
return (new UploadedFilesTransformer())->transformFiles($uploads, $uploads->count());
|
||||
}
|
||||
|
||||
|
||||
@@ -92,7 +134,7 @@ class UploadedFilesController extends Controller
|
||||
{
|
||||
|
||||
// Check the permissions to make sure the user can view the object
|
||||
$object = self::$map_object_type[$object_type]::withTrashed()->find($id);
|
||||
$object = self::$map_object_type[$object_type]::find($id);
|
||||
$this->authorize('view', $object);
|
||||
|
||||
if (!$object) {
|
||||
@@ -140,7 +182,7 @@ class UploadedFilesController extends Controller
|
||||
public function show($object_type, $id, $file_id) : JsonResponse | StreamedResponse | Storage | StorageHelper | BinaryFileResponse
|
||||
{
|
||||
// Check the permissions to make sure the user can view the object
|
||||
$object = self::$map_object_type[$object_type]::withTrashed()->find($id);
|
||||
$object = self::$map_object_type[$object_type]::find($id);
|
||||
$this->authorize('view', $object);
|
||||
|
||||
if (!$object) {
|
||||
@@ -184,7 +226,7 @@ class UploadedFilesController extends Controller
|
||||
{
|
||||
|
||||
// Check the permissions to make sure the user can view the object
|
||||
$object = self::$map_object_type[$object_type]::withTrashed()->find($id);
|
||||
$object = self::$map_object_type[$object_type]::find($id);
|
||||
$this->authorize('update', self::$map_object_type[$object_type]);
|
||||
|
||||
if (!$object) {
|
||||
@@ -202,7 +244,7 @@ class UploadedFilesController extends Controller
|
||||
Storage::delete(self::$map_storage_path[$object_type].'/'.$log->filename);
|
||||
}
|
||||
// Delete the record of the file
|
||||
if ($log->logUploadDelete($object, $log->filename)) {
|
||||
if ($log->delete()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans_choice('general.file_upload_status.delete.success', 1)), 200);
|
||||
}
|
||||
|
||||
|
||||
@@ -20,12 +20,9 @@ use App\Models\Consumable;
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CurrentInventory;
|
||||
use App\Notifications\WelcomeNotification;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -65,14 +62,12 @@ class UsersController extends Controller
|
||||
'users.jobtitle',
|
||||
'users.last_login',
|
||||
'users.last_name',
|
||||
'users.display_name',
|
||||
'users.locale',
|
||||
'users.location_id',
|
||||
'users.manager_id',
|
||||
'users.notes',
|
||||
'users.permissions',
|
||||
'users.phone',
|
||||
'users.mobile',
|
||||
'users.state',
|
||||
'users.two_factor_enrolled',
|
||||
'users.two_factor_optin',
|
||||
@@ -86,12 +81,7 @@ class UsersController extends Controller
|
||||
'users.autoassign_licenses',
|
||||
'users.website',
|
||||
|
||||
])->with('manager')
|
||||
->with('groups')
|
||||
->with('userloc')
|
||||
->with('company')
|
||||
->with('department')
|
||||
->with('createdBy')
|
||||
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy', 'managesUsers', 'managedLocations', 'eulas')
|
||||
->withCount([
|
||||
'assets as assets_count' => function(Builder $query) {
|
||||
$query->withoutTrashed();
|
||||
@@ -112,26 +102,10 @@ class UsersController extends Controller
|
||||
$users = $users->where('users.activated', '=', $request->input('activated'));
|
||||
}
|
||||
|
||||
if ($request->input('admins') == 'true') {
|
||||
$users = $users->OnlyAdminsAndSuperAdmins();
|
||||
}
|
||||
|
||||
if ($request->input('superadmins') == 'true') {
|
||||
$users = $users->OnlySuperAdmins();
|
||||
}
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
$users = $users->where('users.company_id', '=', $request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('phone')) {
|
||||
$users = $users->where('users.phone', '=', $request->input('phone'));
|
||||
}
|
||||
|
||||
if ($request->filled('mobile')) {
|
||||
$users = $users->where('users.mobile', '=', $request->input('mobile'));
|
||||
}
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
$users = $users->where('users.location_id', '=', $request->input('location_id'));
|
||||
}
|
||||
@@ -156,10 +130,6 @@ class UsersController extends Controller
|
||||
$users = $users->where('users.last_name', '=', $request->input('last_name'));
|
||||
}
|
||||
|
||||
if ($request->filled('display_name')) {
|
||||
$users = $users->where('users.display_name', '=', $request->input('display_name'));
|
||||
}
|
||||
|
||||
if ($request->filled('employee_num')) {
|
||||
$users = $users->where('users.employee_num', '=', $request->input('employee_num'));
|
||||
}
|
||||
@@ -290,7 +260,6 @@ class UsersController extends Controller
|
||||
[
|
||||
'last_name',
|
||||
'first_name',
|
||||
'display_name',
|
||||
'email',
|
||||
'jobtitle',
|
||||
'username',
|
||||
@@ -309,7 +278,6 @@ class UsersController extends Controller
|
||||
'manages_users_count',
|
||||
'manages_locations_count',
|
||||
'phone',
|
||||
'mobile',
|
||||
'address',
|
||||
'city',
|
||||
'state',
|
||||
@@ -362,7 +330,6 @@ class UsersController extends Controller
|
||||
'users.employee_num',
|
||||
'users.first_name',
|
||||
'users.last_name',
|
||||
'users.display_name',
|
||||
'users.gravatar',
|
||||
'users.avatar',
|
||||
'users.email',
|
||||
@@ -373,17 +340,20 @@ class UsersController extends Controller
|
||||
$users = $users->where(function ($query) use ($request) {
|
||||
$query->SimpleNameSearch($request->get('search'))
|
||||
->orWhere('username', 'LIKE', '%'.$request->get('search').'%')
|
||||
->orWhere('display_name', 'LIKE', '%'.$request->get('search').'%')
|
||||
->orWhere('email', 'LIKE', '%'.$request->get('search').'%')
|
||||
->orWhere('employee_num', 'LIKE', '%'.$request->get('search').'%');
|
||||
});
|
||||
}
|
||||
|
||||
$users = $users->orderBy('display_name', 'asc')->orderBy('last_name', 'asc')->orderBy('first_name', 'asc');
|
||||
$users = $users->orderBy('last_name', 'asc')->orderBy('first_name', 'asc');
|
||||
$users = $users->paginate(50);
|
||||
|
||||
foreach ($users as $user) {
|
||||
$name_str = $user->display_name;
|
||||
$name_str = '';
|
||||
if ($user->last_name != '') {
|
||||
$name_str .= $user->last_name.', ';
|
||||
}
|
||||
$name_str .= $user->first_name;
|
||||
|
||||
if ($user->username != '') {
|
||||
$name_str .= ' ('.$user->username.')';
|
||||
@@ -435,20 +405,9 @@ class UsersController extends Controller
|
||||
$user->password = $user->noPassword();
|
||||
}
|
||||
|
||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
|
||||
|
||||
if ($user->save()) {
|
||||
|
||||
if (($user->activated == '1') && ($user->email != '') && ($request->input('send_welcome') == '1')) {
|
||||
|
||||
try {
|
||||
$user->notify(new WelcomeNotification($user));
|
||||
} catch (\Exception $e) {
|
||||
Log::warning('Could not send welcome notification for user: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($request->filled('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
} else {
|
||||
@@ -516,29 +475,8 @@ class UsersController extends Controller
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
|
||||
}
|
||||
|
||||
// check for permissions related fields and pull them out if the current user cannot edit them
|
||||
if (auth()->user()->can('canEditAuthFields', $user) && auth()->user()->can('editableOnDemo')) {
|
||||
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
if ($request->filled('username')) {
|
||||
$user->username = $request->input('username');
|
||||
}
|
||||
|
||||
if ($request->filled('display_name')) {
|
||||
$user->display_name = $request->input('display_name');
|
||||
}
|
||||
|
||||
if ($request->filled('email')) {
|
||||
$user->email = $request->input('email');
|
||||
}
|
||||
|
||||
if ($request->filled('activated')) {
|
||||
$user->activated = $request->input('activated');
|
||||
}
|
||||
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
// We need to use has() instead of filled()
|
||||
@@ -560,7 +498,7 @@ class UsersController extends Controller
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
|
||||
}
|
||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
|
||||
|
||||
if ($user->save()) {
|
||||
// Check if the request has groups passed and has a value, AND that the user us a superuser
|
||||
@@ -853,37 +791,4 @@ class UsersController extends Controller
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')), 200);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Run the LDAP sync command to import users from LDAP via API.
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since 8.2.2
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function syncLdapUsers(Request $request)
|
||||
{
|
||||
$this->authorize('update', User::class);
|
||||
// Call Artisan LDAP import command.
|
||||
|
||||
Artisan::call('snipeit:ldap-sync', ['--location_id' => $request->input('location_id'), '--json_summary' => true]);
|
||||
|
||||
// Collect and parse JSON summary.
|
||||
$ldap_results_json = Artisan::output();
|
||||
$ldap_results = json_decode($ldap_results_json, true);
|
||||
|
||||
if (!$ldap_results) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null,trans('general.no_results')), 200);
|
||||
}
|
||||
|
||||
// Direct user to appropriate status page.
|
||||
if ($ldap_results['error']) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $ldap_results['error_message']), 200);
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, $ldap_results['summary']), 200);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,9 +2,8 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Maintenance;
|
||||
use App\Models\AssetMaintenance;
|
||||
use App\Models\Company;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
@@ -18,23 +17,29 @@ use \Illuminate\Http\RedirectResponse;
|
||||
*
|
||||
* @version v2.0
|
||||
*/
|
||||
class MaintenancesController extends Controller
|
||||
class AssetMaintenancesController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the asset maintenances listing.
|
||||
* the content for the asset maintenances listing, which is generated in getDatatable.
|
||||
*
|
||||
* @todo This should be replaced with middleware and/or policies
|
||||
* @see AssetMaintenancesController::getDatatable() method that generates the JSON response
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function index() : View
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
return view('maintenances.index');
|
||||
return view('asset_maintenances/index');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a form view to create a new asset maintenance.
|
||||
*
|
||||
* @see MaintenancesController::postCreate() method that stores the data
|
||||
* @see AssetMaintenancesController::postCreate() method that stores the data
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
@@ -50,21 +55,21 @@ class MaintenancesController extends Controller
|
||||
$asset->asset_id = $asset->id;
|
||||
}
|
||||
|
||||
return view('maintenances/edit')
|
||||
->with('maintenanceType', Maintenance::getImprovementOptions())
|
||||
return view('asset_maintenances/edit')
|
||||
->with('assetMaintenanceType', AssetMaintenance::getImprovementOptions())
|
||||
->with('asset', $asset)
|
||||
->with('item', new Maintenance);
|
||||
->with('item', new AssetMaintenance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and stores the new asset maintenance
|
||||
*
|
||||
* @see MaintenancesController::getCreate() method for the form
|
||||
* @see AssetMaintenancesController::getCreate() method for the form
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function store(ImageUploadRequest $request) : RedirectResponse
|
||||
public function store(Request $request) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
@@ -73,73 +78,72 @@ class MaintenancesController extends Controller
|
||||
// Loop through the selected assets
|
||||
foreach ($assets as $asset) {
|
||||
|
||||
$maintenance = new Maintenance();
|
||||
$maintenance->supplier_id = $request->input('supplier_id');
|
||||
$maintenance->is_warranty = $request->input('is_warranty');
|
||||
$maintenance->cost = $request->input('cost');
|
||||
$maintenance->notes = $request->input('notes');
|
||||
$assetMaintenance = new AssetMaintenance();
|
||||
$assetMaintenance->supplier_id = $request->input('supplier_id');
|
||||
$assetMaintenance->is_warranty = $request->input('is_warranty');
|
||||
$assetMaintenance->cost = $request->input('cost');
|
||||
$assetMaintenance->notes = $request->input('notes');
|
||||
|
||||
// Save the asset maintenance data
|
||||
$maintenance->asset_id = $asset->id;
|
||||
$maintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
|
||||
$maintenance->name = $request->input('name');
|
||||
$maintenance->start_date = $request->input('start_date');
|
||||
$maintenance->completion_date = $request->input('completion_date');
|
||||
$maintenance->created_by = auth()->id();
|
||||
$assetMaintenance->asset_id = $asset->id;
|
||||
$assetMaintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
|
||||
$assetMaintenance->title = $request->input('title');
|
||||
$assetMaintenance->start_date = $request->input('start_date');
|
||||
$assetMaintenance->completion_date = $request->input('completion_date');
|
||||
$assetMaintenance->created_by = auth()->id();
|
||||
|
||||
if (($maintenance->completion_date !== null)
|
||||
&& ($maintenance->start_date !== '')
|
||||
&& ($maintenance->start_date !== '0000-00-00')
|
||||
if (($assetMaintenance->completion_date !== null)
|
||||
&& ($assetMaintenance->start_date !== '')
|
||||
&& ($assetMaintenance->start_date !== '0000-00-00')
|
||||
) {
|
||||
$startDate = Carbon::parse($maintenance->start_date);
|
||||
$completionDate = Carbon::parse($maintenance->completion_date);
|
||||
$maintenance->asset_maintenance_time = (int) $completionDate->diffInDays($startDate, true);
|
||||
$startDate = Carbon::parse($assetMaintenance->start_date);
|
||||
$completionDate = Carbon::parse($assetMaintenance->completion_date);
|
||||
$assetMaintenance->asset_maintenance_time = (int) $completionDate->diffInDays($startDate, true);
|
||||
}
|
||||
|
||||
$maintenance = $request->handleImages($maintenance);
|
||||
|
||||
// Was the asset maintenance created?
|
||||
if (!$maintenance->save()) {
|
||||
return redirect()->back()->withInput()->withErrors($maintenance->getErrors());
|
||||
if (!$assetMaintenance->save()) {
|
||||
return redirect()->back()->withInput()->withErrors($assetMaintenance->getErrors());
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('maintenances.index')
|
||||
->with('success', trans('admin/maintenances/message.create.success'));
|
||||
->with('success', trans('admin/asset_maintenances/message.create.success'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a form view to edit a selected asset maintenance.
|
||||
*
|
||||
* @see MaintenancesController::postEdit() method that stores the data
|
||||
* @see AssetMaintenancesController::postEdit() method that stores the data
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function edit(Maintenance $maintenance) : View | RedirectResponse
|
||||
public function edit(AssetMaintenance $maintenance) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
$this->authorize('update', $maintenance->asset);
|
||||
|
||||
return view('maintenances/edit')
|
||||
return view('asset_maintenances/edit')
|
||||
->with('selected_assets', $maintenance->asset->pluck('id')->toArray())
|
||||
->with('asset_ids', request()->input('asset_ids', []))
|
||||
->with('maintenanceType', Maintenance::getImprovementOptions())
|
||||
->with('assetMaintenanceType', AssetMaintenance::getImprovementOptions())
|
||||
->with('item', $maintenance);
|
||||
}
|
||||
|
||||
/**
|
||||
* Validates and stores an update to an asset maintenance
|
||||
*
|
||||
* @see MaintenancesController::postEdit() method that stores the data
|
||||
* @see AssetMaintenancesController::postEdit() method that stores the data
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @param Request $request
|
||||
* @param int $maintenanceId
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, Maintenance $maintenance) : View | RedirectResponse
|
||||
public function update(Request $request, AssetMaintenance $maintenance) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
$this->authorize('update', $maintenance->asset);
|
||||
@@ -149,7 +153,7 @@ class MaintenancesController extends Controller
|
||||
$maintenance->cost = $request->input('cost');
|
||||
$maintenance->notes = $request->input('notes');
|
||||
$maintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
|
||||
$maintenance->name = $request->input('name');
|
||||
$maintenance->title = $request->input('title');
|
||||
$maintenance->start_date = $request->input('start_date');
|
||||
$maintenance->completion_date = $request->input('completion_date');
|
||||
|
||||
@@ -172,11 +176,10 @@ class MaintenancesController extends Controller
|
||||
$completionDate = Carbon::parse($maintenance->completion_date);
|
||||
$maintenance->asset_maintenance_time = (int) $completionDate->diffInDays($startDate, true);
|
||||
}
|
||||
$maintenance = $request->handleImages($maintenance);
|
||||
|
||||
if ($maintenance->save()) {
|
||||
return redirect()->route('maintenances.index')
|
||||
->with('success', trans('admin/maintenances/message.edit.success'));
|
||||
->with('success', trans('admin/asset_maintenances/message.edit.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($maintenance->getErrors());
|
||||
@@ -186,11 +189,11 @@ class MaintenancesController extends Controller
|
||||
* Delete an asset maintenance
|
||||
*
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @param int $maintenanceId
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function destroy(Maintenance $maintenance) : RedirectResponse
|
||||
public function destroy(AssetMaintenance $maintenance) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
$this->authorize('update', $maintenance->asset);
|
||||
@@ -198,19 +201,19 @@ class MaintenancesController extends Controller
|
||||
$maintenance->delete();
|
||||
// Redirect to the asset_maintenance management page
|
||||
return redirect()->route('maintenances.index')
|
||||
->with('success', trans('admin/maintenances/message.delete.success'));
|
||||
->with('success', trans('admin/asset_maintenances/message.delete.success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* View an asset maintenance
|
||||
*
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @param int $maintenanceId
|
||||
* @param int $assetMaintenanceId
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function show(Maintenance $maintenance) : View | RedirectResponse
|
||||
public function show(AssetMaintenance $maintenance) : View | RedirectResponse
|
||||
{
|
||||
return view('maintenances.view')->with('maintenance', $maintenance);
|
||||
return view('asset_maintenances/view')->with('assetMaintenance', $maintenance);
|
||||
}
|
||||
}
|
||||
@@ -82,26 +82,12 @@ class AssetModelsController extends Controller
|
||||
$model->notes = $request->input('notes');
|
||||
$model->created_by = auth()->id();
|
||||
$model->requestable = $request->has('requestable');
|
||||
$model->require_serial = $request->input('require_serial', 0);
|
||||
|
||||
if ($request->input('fieldset_id') != '') {
|
||||
$model->fieldset_id = $request->input('fieldset_id');
|
||||
}
|
||||
|
||||
if ($request->has('use_cloned_image')) {
|
||||
$cloned_model_img = AssetModel::select('image')->find($request->input('clone_image_from_id'));
|
||||
if ($cloned_model_img) {
|
||||
$new_image_name = 'clone-'.date('U').'-'.$cloned_model_img->image;
|
||||
$new_image = 'models/'.$new_image_name;
|
||||
Storage::disk('public')->copy('models/'.$cloned_model_img->image, $new_image);
|
||||
$model->image = $new_image_name;
|
||||
}
|
||||
|
||||
} else {
|
||||
$model = $request->handleImages($model);
|
||||
}
|
||||
|
||||
|
||||
$model = $request->handleImages($model);
|
||||
|
||||
if ($model->save()) {
|
||||
if ($this->shouldAddDefaultValues($request->input())) {
|
||||
@@ -156,7 +142,7 @@ class AssetModelsController extends Controller
|
||||
$model->category_id = $request->input('category_id');
|
||||
$model->notes = $request->input('notes');
|
||||
$model->requestable = $request->input('requestable', '0');
|
||||
$model->require_serial = $request->input('require_serial', 0);
|
||||
|
||||
$model->fieldset_id = $request->input('fieldset_id');
|
||||
|
||||
if ($model->save()) {
|
||||
@@ -285,7 +271,7 @@ class AssetModelsController extends Controller
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('item', $model)
|
||||
->with('model_id', $model->id)
|
||||
->with('cloned_model', $cloned_model);
|
||||
->with('clone_model', $cloned_model);
|
||||
}
|
||||
|
||||
|
||||
|
||||
115
app/Http/Controllers/AssetModelsFilesController.php
Normal file
115
app/Http/Controllers/AssetModelsFilesController.php
Normal file
@@ -0,0 +1,115 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\AssetModel;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use \Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
class AssetModelsFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Upload a file to the server.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $modelId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@since [v1.0]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $modelId = null) : RedirectResponse
|
||||
{
|
||||
if (! $model = AssetModel::find($modelId)) {
|
||||
return redirect()->route('models.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $model);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/assetmodels')) {
|
||||
Storage::makeDirectory('private_uploads/assetmodels', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$file_name = $request->handleFile('private_uploads/assetmodels/','model-'.$model->id,$file);
|
||||
|
||||
$model->logUpload($file_name, $request->get('notes'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('general.file_upload_success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('error', trans('admin/hardware/message.upload.nofiles'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $modelId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show(AssetModel $model, $fileId = null) : StreamedResponse | Response | RedirectResponse | BinaryFileResponse
|
||||
{
|
||||
|
||||
$this->authorize('view', $model);
|
||||
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that model/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
$file = 'private_uploads/assetmodels/'.$log->filename;
|
||||
|
||||
if (! Storage::exists($file)) {
|
||||
return response('File '.$file.' not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the associated file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $modelId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function destroy(AssetModel $model, $fileId = null) : RedirectResponse
|
||||
{
|
||||
$rel_path = 'private_uploads/assetmodels';
|
||||
$this->authorize('update', $model);
|
||||
$log = Actionlog::find($fileId);
|
||||
if ($log) {
|
||||
if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
Storage::delete($rel_path.'/'.$log->filename);
|
||||
}
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -65,8 +65,6 @@ class AssetCheckoutController extends Controller
|
||||
*/
|
||||
public function store(AssetCheckoutRequest $request, $assetId) : RedirectResponse
|
||||
{
|
||||
|
||||
|
||||
try {
|
||||
// Check if the asset exists
|
||||
if (! $asset = Asset::find($assetId)) {
|
||||
@@ -83,7 +81,6 @@ class AssetCheckoutController extends Controller
|
||||
$admin = auth()->user();
|
||||
|
||||
$target = $this->determineCheckoutTarget();
|
||||
session()->put(['checkout_to_type' => $target]);
|
||||
|
||||
$asset = $this->updateAssetLocation($asset, $target);
|
||||
|
||||
|
||||
108
app/Http/Controllers/Assets/AssetFilesController.php
Normal file
108
app/Http/Controllers/Assets/AssetFilesController.php
Normal file
@@ -0,0 +1,108 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Assets;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use \Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use \Illuminate\Http\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
class AssetFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Upload a file to the server.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $assetId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@since [v1.0]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, Asset $asset) : RedirectResponse
|
||||
{
|
||||
|
||||
$this->authorize('update', $asset);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/assets')) {
|
||||
Storage::makeDirectory('private_uploads/assets', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
|
||||
|
||||
$asset->logUpload($file_name, $request->get('notes'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.upload.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show(Asset $asset, $fileId = null) : View | RedirectResponse | Response | StreamedResponse | BinaryFileResponse
|
||||
{
|
||||
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
|
||||
$file = 'private_uploads/assets/'.$log->filename;
|
||||
|
||||
if ($log->action_type == 'audit') {
|
||||
$file = 'private_uploads/audits/'.$log->filename;
|
||||
}
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('hardware.show', $asset)->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.show', $asset)->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the associated file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function destroy(Asset $asset, $fileId = null) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $asset);
|
||||
$rel_path = 'private_uploads/assets';
|
||||
|
||||
if ($log = Actionlog::find($fileId)) {
|
||||
if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
Storage::delete($rel_path.'/'.$log->filename);
|
||||
}
|
||||
$log->delete();
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.show', $asset)->with('error', trans('general.log_record_not_found'));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -110,35 +110,17 @@ class AssetsController extends Controller
|
||||
// This is only necessary on create, not update, since bulk editing is handled
|
||||
// differently
|
||||
$asset_tags = $request->input('asset_tags');
|
||||
$model = AssetModel::find($request->input('model_id'));
|
||||
$serial_errors = [];
|
||||
$serials = $request->input('serials');
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
//Validate required serial based on model setting
|
||||
for ($a = 1, $aMax = count($asset_tags); $a <= $aMax; $a++) {
|
||||
if ($model && $model->require_serial === 1 && empty($serials[$a])) {
|
||||
$serial_errors["serials.$a"] = trans('admin/hardware/form.serial_required', ['number' => $a]);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if (!empty($serial_errors)) {
|
||||
return redirect()->back()
|
||||
->withInput()
|
||||
->withErrors($serial_errors);
|
||||
}
|
||||
|
||||
$asset = null;
|
||||
$companyId = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$successes = [];
|
||||
$failures = [];
|
||||
$serials = $request->input('serials');
|
||||
$asset = null;
|
||||
|
||||
for ($a = 1, $aMax = count($asset_tags); $a <= $aMax; $a++) {
|
||||
for ($a = 1; $a <= count($asset_tags); $a++) {
|
||||
$asset = new Asset();
|
||||
|
||||
$asset->model()->associate($model);
|
||||
$asset->model()->associate(AssetModel::find($request->input('model_id')));
|
||||
$asset->name = $request->input('name');
|
||||
|
||||
// Check for a corresponding serial
|
||||
@@ -150,7 +132,7 @@ class AssetsController extends Controller
|
||||
$asset->asset_tag = $asset_tags[$a];
|
||||
}
|
||||
|
||||
$asset->company_id = $companyId;
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$asset->model_id = $request->input('model_id');
|
||||
$asset->order_number = $request->input('order_number');
|
||||
$asset->notes = $request->input('notes');
|
||||
@@ -175,21 +157,14 @@ class AssetsController extends Controller
|
||||
$asset->location_id = $request->input('rtd_location_id', null);
|
||||
}
|
||||
|
||||
if ($request->has('use_cloned_image')) {
|
||||
$cloned_model_img = Asset::select('image')->find($request->input('clone_image_from_id'));
|
||||
if ($cloned_model_img) {
|
||||
$new_image_name = 'clone-'.date('U').'-'.$cloned_model_img->image;
|
||||
$new_image = 'assets/'.$new_image_name;
|
||||
Storage::disk('public')->copy('assets/'.$cloned_model_img->image, $new_image);
|
||||
$asset->image = $new_image_name;
|
||||
}
|
||||
|
||||
} else {
|
||||
// Create the image (if one was chosen.)
|
||||
if ($request->has('image')) {
|
||||
$asset = $request->handleImages($asset);
|
||||
}
|
||||
|
||||
// Update custom fields in the database.
|
||||
// Validation for these fields is handled through the AssetRequest form request
|
||||
$model = AssetModel::find($request->get('model_id'));
|
||||
|
||||
if (($model) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
@@ -251,13 +226,9 @@ class AssetsController extends Controller
|
||||
$failures[] = join(",", $asset->getErrors()->all());
|
||||
}
|
||||
}
|
||||
if($request->get('redirect_option') === 'back'){
|
||||
session()->put(['redirect_option' => 'index']);
|
||||
} else {
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
}
|
||||
|
||||
session()->put(['checkout_to_type' => $request->get('checkout_to_type'),
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'),
|
||||
'checkout_to_type' => $request->get('checkout_to_type'),
|
||||
'other_redirect' => 'model' ]);
|
||||
|
||||
|
||||
@@ -441,9 +412,6 @@ class AssetsController extends Controller
|
||||
$model = AssetModel::find($request->get('model_id'));
|
||||
if (($model) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($field->element == 'checkbox' && !$request->has($field->db_column)) {
|
||||
$asset->{$field->db_column} = null;
|
||||
}
|
||||
if ($request->has($field->db_column)) {
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('assets.view.encrypted_custom_fields')) {
|
||||
@@ -470,13 +438,6 @@ class AssetsController extends Controller
|
||||
]);
|
||||
|
||||
|
||||
//Validate required serial based on model setting
|
||||
if ($model && $model->require_serial === 1 && empty($serial[1])) {
|
||||
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
|
||||
->with('warning', trans('admin/hardware/form.serial_required_post_model_update', [
|
||||
'asset_model' => $model->name
|
||||
]));
|
||||
}
|
||||
if ($asset->save()) {
|
||||
return Helper::getRedirectOption($request, $asset->id, 'Assets')
|
||||
->with('success', trans('admin/hardware/message.update.success'));
|
||||
@@ -683,9 +644,8 @@ class AssetsController extends Controller
|
||||
*/
|
||||
public function getClone(Asset $asset)
|
||||
{
|
||||
$this->authorize('create', Asset::class);
|
||||
$this->authorize('create', $asset);
|
||||
$cloned = clone $asset;
|
||||
$cloned_model = $asset;
|
||||
$cloned->id = null;
|
||||
$cloned->asset_tag = '';
|
||||
$cloned->serial = '';
|
||||
@@ -695,7 +655,6 @@ class AssetsController extends Controller
|
||||
return view('hardware/edit')
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
->with('statuslabel_types', Helper::statusTypeList())
|
||||
->with('cloned_model', $cloned_model)
|
||||
->with('item', $cloned);
|
||||
}
|
||||
|
||||
@@ -821,7 +780,7 @@ class AssetsController extends Controller
|
||||
'item_id' => $asset->id,
|
||||
'item_type' => Asset::class,
|
||||
'created_by' => auth()->id(),
|
||||
'note' => 'Checkout imported by '.auth()->user()->display_name.' from history importer',
|
||||
'note' => 'Checkout imported by '.auth()->user()->present()->fullName().' from history importer',
|
||||
'target_id' => $item[$asset_tag][$batch_counter]['user_id'],
|
||||
'target_type' => User::class,
|
||||
'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'],
|
||||
@@ -849,7 +808,7 @@ class AssetsController extends Controller
|
||||
'item_id' => $item[$asset_tag][$batch_counter]['asset_id'],
|
||||
'item_type' => Asset::class,
|
||||
'created_by' => auth()->id(),
|
||||
'note' => 'Checkin imported by '.auth()->user()->display_name.' from history importer',
|
||||
'note' => 'Checkin imported by '.auth()->user()->present()->fullName().' from history importer',
|
||||
'target_id' => null,
|
||||
'created_at' => $checkin_date,
|
||||
'action_type' => 'checkin',
|
||||
|
||||
@@ -161,7 +161,6 @@ class BulkAssetsController extends Controller
|
||||
|
||||
$models = $assets->unique('model_id');
|
||||
$modelNames = [];
|
||||
|
||||
foreach($models as $model) {
|
||||
$modelNames[] = $model->model->name;
|
||||
}
|
||||
@@ -197,6 +196,7 @@ class BulkAssetsController extends Controller
|
||||
|
||||
case 'edit':
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
return view('hardware/bulk')
|
||||
->with('assets', $asset_ids)
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
@@ -224,8 +224,11 @@ class BulkAssetsController extends Controller
|
||||
$error_array = array();
|
||||
|
||||
// Get the back url from the session and then destroy the session
|
||||
$bulk_back_url = route('hardware.index');
|
||||
|
||||
$bulk_back_url = $request->session()->pull('bulk_back_url', url()->previous());
|
||||
if ($request->session()->has('bulk_back_url')) {
|
||||
$bulk_back_url = $request->session()->pull('bulk_back_url');
|
||||
}
|
||||
|
||||
$custom_field_columns = CustomField::all()->pluck('db_column')->toArray();
|
||||
|
||||
@@ -540,13 +543,7 @@ class BulkAssetsController extends Controller
|
||||
} // end asset foreach
|
||||
|
||||
if ($has_errors > 0) {
|
||||
session()->put('bulkedit_ids', $request->input('ids'));
|
||||
session()->put('bulk_asset_errors',$error_array);
|
||||
|
||||
return redirect()
|
||||
->route('hardware.index')
|
||||
->with('bulk_asset_errors', $error_array)
|
||||
->withInput();
|
||||
return redirect($bulk_back_url)->with('bulk_asset_errors', $error_array);
|
||||
}
|
||||
|
||||
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.update.success'));
|
||||
@@ -637,7 +634,6 @@ class BulkAssetsController extends Controller
|
||||
$admin = auth()->user();
|
||||
|
||||
$target = $this->determineCheckoutTarget();
|
||||
session()->put(['checkout_to_type' => $target]);
|
||||
|
||||
if (! is_array($request->get('selected_assets'))) {
|
||||
return redirect()->route('hardware.bulkcheckout.show')->withInput()->with('error', trans('admin/hardware/message.checkout.no_assets_selected'));
|
||||
@@ -739,33 +735,4 @@ class BulkAssetsController extends Controller
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public function bulkEditForm(): View|RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
$asset_ids = session()->pull('bulkedit_ids', []);
|
||||
|
||||
if (empty($asset_ids)) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.update.no_assets_selected'));
|
||||
}
|
||||
|
||||
$assets = Asset::with('model')->withTrashed()->whereIn('id', $asset_ids)->get();
|
||||
|
||||
if ($assets->isEmpty()) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.update.assets_do_not_exist_or_are_invalid'));
|
||||
}
|
||||
|
||||
$models = $assets->unique('model_id');
|
||||
$modelNames = [];
|
||||
foreach ($models as $model) {
|
||||
$modelNames[] = $model->model->name;
|
||||
}
|
||||
|
||||
return view('hardware/bulk')
|
||||
->with('assets', $asset_ids)
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
->with('models', $models->pluck(['model']))
|
||||
->with('modelNames', $modelNames);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,9 +92,7 @@ class BulkAssetModelsController extends Controller
|
||||
$update_array['min_amt'] = $request->input('min_amt');
|
||||
}
|
||||
|
||||
if ($request->filled('require_serial')) {
|
||||
$update_array['require_serial'] = $request->input('require_serial');
|
||||
}
|
||||
|
||||
|
||||
if (count($update_array) > 0) {
|
||||
AssetModel::whereIn('id', $models_raw_array)->update($update_array);
|
||||
|
||||
@@ -88,12 +88,7 @@ class ComponentsController extends Controller
|
||||
|
||||
$component = $request->handleImages($component);
|
||||
|
||||
if($request->get('redirect_option') === 'back'){
|
||||
session()->put(['redirect_option' => 'index']);
|
||||
} else {
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
}
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($component->save()) {
|
||||
return Helper::getRedirectOption($request, $component->id, 'Components')
|
||||
|
||||
138
app/Http/Controllers/Components/ComponentsFilesController.php
Normal file
138
app/Http/Controllers/Components/ComponentsFilesController.php
Normal file
@@ -0,0 +1,138 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Components;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Component;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class ComponentsFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a component.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $componentId = null)
|
||||
{
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('components.show', ['component'=>$componentId])->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
$component = Component::find($componentId);
|
||||
|
||||
if (isset($component->id)) {
|
||||
$this->authorize('update', $component);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/components')) {
|
||||
Storage::makeDirectory('private_uploads/components', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/components/','component-'.$component->id, $file);
|
||||
|
||||
//Log the upload to the log
|
||||
$component->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('components.show', $component->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('components.show', $component->id)->with('error', trans('general.no_files_uploaded'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('components.index')
|
||||
->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected component file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $componentId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($componentId = null, $fileId = null)
|
||||
{
|
||||
$component = Component::find($componentId);
|
||||
|
||||
// the asset is valid
|
||||
if (isset($component->id)) {
|
||||
$this->authorize('update', $component);
|
||||
$log = Actionlog::find($fileId);
|
||||
|
||||
// Remove the file if one exists
|
||||
if (Storage::exists('components/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('components/'.$log->filename);
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()->withFragment('files')
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $componentId
|
||||
* @param int $fileId
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($componentId = null, $fileId = null)
|
||||
{
|
||||
Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||
|
||||
|
||||
// the component is valid
|
||||
if ($component = Component::find($componentId)) {
|
||||
$this->authorize('view', $component);
|
||||
$this->authorize('components.files', $component);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $component->id)->find($fileId)) {
|
||||
|
||||
$file = 'private_uploads/components/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('components.show', ['component' => $component])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
return redirect()->route('components.show', ['component' => $component])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,7 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Company;
|
||||
use App\Models\Consumable;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
@@ -81,29 +81,13 @@ class ConsumablesController extends Controller
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = $request->input('purchase_cost');
|
||||
$consumable->qty = $request->input('qty');
|
||||
$consumable->created_by = auth()->id();
|
||||
$consumable->created_by = auth()->id();
|
||||
$consumable->notes = $request->input('notes');
|
||||
|
||||
|
||||
if ($request->has('use_cloned_image')) {
|
||||
$cloned_model_img = Consumable::select('image')->find($request->input('clone_image_from_id'));
|
||||
if ($cloned_model_img) {
|
||||
$new_image_name = 'clone-'.date('U').'-'.$cloned_model_img->image;
|
||||
$new_image = 'consumables/'.$new_image_name;
|
||||
Storage::disk('public')->copy('consumables/'.$cloned_model_img->image, $new_image);
|
||||
$consumable->image = $new_image_name;
|
||||
}
|
||||
|
||||
} else {
|
||||
$consumable = $request->handleImages($consumable);
|
||||
}
|
||||
|
||||
if($request->get('redirect_option') === 'back'){
|
||||
session()->put(['redirect_option' => 'index']);
|
||||
} else {
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
}
|
||||
$consumable = $request->handleImages($consumable);
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($consumable->save()) {
|
||||
return Helper::getRedirectOption($request, $consumable->id, 'Consumables')
|
||||
@@ -229,10 +213,9 @@ class ConsumablesController extends Controller
|
||||
$consumable_to_close = $consumable;
|
||||
$consumable = clone $consumable_to_close;
|
||||
$consumable->id = null;
|
||||
$consumable->image = null;
|
||||
$consumable->created_by = null;
|
||||
|
||||
return view('consumables/edit')
|
||||
->with('cloned_model', $consumable_to_close)
|
||||
->with('item', $consumable);
|
||||
return view('consumables/edit')->with('item', $consumable);
|
||||
}
|
||||
}
|
||||
|
||||
134
app/Http/Controllers/Consumables/ConsumablesFilesController.php
Normal file
134
app/Http/Controllers/Consumables/ConsumablesFilesController.php
Normal file
@@ -0,0 +1,134 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Consumables;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Consumable;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Consumable\HttpFoundation\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
class ConsumablesFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a consumable.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $consumableId = null)
|
||||
{
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('consumables.show', ['consumable'=>$consumableId])->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
$consumable = Consumable::find($consumableId);
|
||||
|
||||
if (isset($consumable->id)) {
|
||||
$this->authorize('update', $consumable);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/consumables')) {
|
||||
Storage::makeDirectory('private_uploads/consumables', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/consumables/','consumable-'.$consumable->id, $file);
|
||||
|
||||
//Log the upload to the log
|
||||
$consumable->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('consumables.show', $consumable->id)->withFragment('files')->with('success', trans('general.file_upload_success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.show', $consumable->id)->with('error', trans('general.no_files_uploaded'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('consumables.index')
|
||||
->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected consumable file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($consumableId = null, $fileId = null)
|
||||
{
|
||||
$consumable = Consumable::find($consumableId);
|
||||
|
||||
// the asset is valid
|
||||
if (isset($consumable->id)) {
|
||||
$this->authorize('update', $consumable);
|
||||
$log = Actionlog::find($fileId);
|
||||
|
||||
// Remove the file if one exists
|
||||
if (Storage::exists('consumables/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('consumables/'.$log->filename);
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()->withFragment('files')
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $consumableId
|
||||
* @param int $fileId
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($consumableId = null, $fileId = null)
|
||||
{
|
||||
$consumable = Consumable::find($consumableId);
|
||||
|
||||
// the consumable is valid
|
||||
if (isset($consumable->id)) {
|
||||
$this->authorize('view', $consumable);
|
||||
$this->authorize('consumables.files', $consumable);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $consumable->id)->find($fileId)) {
|
||||
$file = 'private_uploads/consumables/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('consumables.show', ['consumable' => $consumable])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('consumables.show', ['consumable' => $consumable])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
}
|
||||
}
|
||||
@@ -22,15 +22,6 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Component;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\License;
|
||||
use App\Models\Location;
|
||||
use App\Models\Maintenance;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
use Illuminate\Foundation\Bus\DispatchesJobs;
|
||||
@@ -41,45 +32,6 @@ abstract class Controller extends BaseController
|
||||
{
|
||||
use AuthorizesRequests, DispatchesJobs, ValidatesRequests;
|
||||
|
||||
static $map_object_type = [
|
||||
'accessories' => Accessory::class,
|
||||
'maintenances' => Maintenance::class,
|
||||
'assets' => Asset::class,
|
||||
'components' => Component::class,
|
||||
'consumables' => Consumable::class,
|
||||
'hardware' => Asset::class,
|
||||
'licenses' => License::class,
|
||||
'locations' => Location::class,
|
||||
'models' => AssetModel::class,
|
||||
'users' => User::class,
|
||||
];
|
||||
|
||||
static $map_storage_path = [
|
||||
'accessories' => 'private_uploads/accessories/',
|
||||
'maintenances' => 'private_uploads/maintenances/',
|
||||
'assets' => 'private_uploads/assets/',
|
||||
'components' => 'private_uploads/components/',
|
||||
'consumables' => 'private_uploads/consumables/',
|
||||
'hardware' => 'private_uploads/assets/',
|
||||
'licenses' => 'private_uploads/licenses/',
|
||||
'locations' => 'private_uploads/locations/',
|
||||
'models' => 'private_uploads/models/',
|
||||
'users' => 'private_uploads/users/',
|
||||
];
|
||||
|
||||
static $map_file_prefix= [
|
||||
'accessories' => 'accessory',
|
||||
'maintenances' => 'maintenance',
|
||||
'assets' => 'asset',
|
||||
'components' => 'component',
|
||||
'consumables' => 'consumable',
|
||||
'hardware' => 'asset',
|
||||
'licenses' => 'license',
|
||||
'locations' => 'location',
|
||||
'models' => 'model',
|
||||
'users' => 'user',
|
||||
];
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
view()->share('signedIn', Auth::check());
|
||||
|
||||
@@ -144,9 +144,10 @@ class CustomFieldsController extends Controller
|
||||
*/
|
||||
public function deleteFieldFromFieldset($field_id, $fieldset_id) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', CustomField::class);
|
||||
$field = CustomField::find($field_id);
|
||||
|
||||
$this->authorize('update', $field);
|
||||
|
||||
// Check that the field exists - this is mostly related to the demo, where we
|
||||
// rewrite the data every x minutes, so it's possible someone might be disassociating
|
||||
// a field from a fieldset just as we're wiping the database
|
||||
@@ -156,12 +157,11 @@ class CustomFieldsController extends Controller
|
||||
return redirect()->route('fieldsets.show', ['fieldset' => $fieldset_id])
|
||||
->with('success', trans('admin/custom_fields/message.field.delete.success'));
|
||||
} else {
|
||||
return redirect()->back()->with('error', trans('admin/custom_fields/message.field.delete.error'))
|
||||
->withInput();
|
||||
return redirect()->back()->withErrors(['message' => "Field is in use and cannot be deleted."]);
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', trans('admin/custom_fields/message.field.delete.error'));
|
||||
return redirect()->back()->withErrors(['message' => "Error deleting field from fieldset"]);
|
||||
|
||||
|
||||
}
|
||||
@@ -172,16 +172,20 @@ class CustomFieldsController extends Controller
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function destroy(CustomField $field) : RedirectResponse
|
||||
public function destroy($field_id) : RedirectResponse
|
||||
{
|
||||
$this->authorize('delete', CustomField::class);
|
||||
if ($field = CustomField::find($field_id)) {
|
||||
$this->authorize('delete', $field);
|
||||
|
||||
if (($field->fieldset) && ($field->fieldset->count() > 0)) {
|
||||
return redirect()->back()->with('error', trans('admin/custom_fields/message.field.delete.in_use'));
|
||||
if (($field->fieldset) && ($field->fieldset->count() > 0)) {
|
||||
return redirect()->back()->withErrors(['message' => 'Field is in-use']);
|
||||
}
|
||||
$field->delete();
|
||||
return redirect()->route("fields.index")
|
||||
->with("success", trans('admin/custom_fields/message.field.delete.success'));
|
||||
}
|
||||
$field->delete();
|
||||
return redirect()->route("fields.index")
|
||||
->with("success", trans('admin/custom_fields/message.field.delete.success'));
|
||||
|
||||
return redirect()->back()->withErrors(['message' => 'Field does not exist']);
|
||||
}
|
||||
|
||||
|
||||
@@ -194,7 +198,7 @@ class CustomFieldsController extends Controller
|
||||
*/
|
||||
public function edit(Request $request, CustomField $field) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('update', CustomField::class);
|
||||
$this->authorize('update', $field);
|
||||
$fieldsets = CustomFieldset::get();
|
||||
$customFormat = '';
|
||||
if ((stripos($field->format, 'regex') === 0) && ($field->format !== CustomField::PREDEFINED_FORMATS['MAC'])) {
|
||||
@@ -224,7 +228,7 @@ class CustomFieldsController extends Controller
|
||||
*/
|
||||
public function update(CustomFieldRequest $request, CustomField $field) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', CustomField::class);
|
||||
$this->authorize('update', $field);
|
||||
$show_in_email = $request->get("show_in_email", 0);
|
||||
$display_in_user_view = $request->get("display_in_user_view", 0);
|
||||
|
||||
@@ -261,6 +265,7 @@ class CustomFieldsController extends Controller
|
||||
|
||||
if ($field->save()) {
|
||||
|
||||
|
||||
// Sync fields with fieldsets
|
||||
$fieldset_array = $request->input('associate_fieldsets');
|
||||
if ($request->has('associate_fieldsets') && (is_array($fieldset_array))) {
|
||||
|
||||
@@ -64,7 +64,12 @@ class LicenseCheckinController extends Controller
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
if (! $license->reassignable) {
|
||||
// Not allowed to checkin
|
||||
Session::flash('error', trans('admin/licenses/message.checkin.not_reassignable') . '.');
|
||||
|
||||
return redirect()->back()->withInput();
|
||||
}
|
||||
|
||||
// Declare the rules for the form validation
|
||||
$rules = [
|
||||
@@ -82,9 +87,7 @@ class LicenseCheckinController extends Controller
|
||||
|
||||
if($licenseSeat->assigned_to != null){
|
||||
$return_to = User::withTrashed()->find($licenseSeat->assigned_to);
|
||||
if ($return_to) {
|
||||
session()->put('checkedInFrom', $return_to->id);
|
||||
}
|
||||
session()->put('checkedInFrom', $return_to->id);
|
||||
} else {
|
||||
$return_to = Asset::find($licenseSeat->asset_id);
|
||||
}
|
||||
@@ -93,9 +96,6 @@ class LicenseCheckinController extends Controller
|
||||
$licenseSeat->assigned_to = null;
|
||||
$licenseSeat->asset_id = null;
|
||||
$licenseSeat->notes = $request->input('notes');
|
||||
if (! $licenseSeat->license->reassignable) {
|
||||
$licenseSeat->unreassignable_seat = true;
|
||||
}
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
if ($request->get('redirect_option') === 'target'){
|
||||
@@ -104,7 +104,7 @@ class LicenseCheckinController extends Controller
|
||||
|
||||
// Was the asset updated?
|
||||
if ($licenseSeat->save()) {
|
||||
event(new CheckoutableCheckedIn($licenseSeat, $return_to, auth()->user(), $licenseSeat->notes));
|
||||
event(new CheckoutableCheckedIn($licenseSeat, $return_to, auth()->user(), $request->input('notes')));
|
||||
|
||||
|
||||
return Helper::getRedirectOption($request, $license->id, 'Licenses')
|
||||
@@ -130,17 +130,21 @@ class LicenseCheckinController extends Controller
|
||||
$license = License::findOrFail($licenseId);
|
||||
$this->authorize('checkin', $license);
|
||||
|
||||
if (! $license->reassignable) {
|
||||
// Not allowed to checkin
|
||||
Session::flash('error', 'License not reassignable.');
|
||||
|
||||
return redirect()->back()->withInput();
|
||||
}
|
||||
|
||||
$licenseSeatsByUser = LicenseSeat::where('license_id', '=', $licenseId)
|
||||
->whereNotNull('assigned_to')
|
||||
->with('user', 'license')
|
||||
->with('user')
|
||||
->get();
|
||||
|
||||
$license = $licenseSeatsByUser->first()?->license;
|
||||
foreach ($licenseSeatsByUser as $user_seat) {
|
||||
$user_seat->assigned_to = null;
|
||||
if ($license && ! $license->reassignable) {
|
||||
$user_seat->unreassignable_seat = true;
|
||||
}
|
||||
|
||||
if ($user_seat->save()) {
|
||||
Log::debug('Checking in '.$license->name.' from user '.$user_seat->username);
|
||||
$user_seat->logCheckin($user_seat->user, trans('admin/licenses/general.bulk.checkin_all.log_msg'));
|
||||
@@ -153,12 +157,9 @@ class LicenseCheckinController extends Controller
|
||||
->get();
|
||||
|
||||
$count = 0;
|
||||
$license = $licenseSeatsByAsset->first()?->license;
|
||||
foreach ($licenseSeatsByAsset as $asset_seat) {
|
||||
$asset_seat->asset_id = null;
|
||||
if ($license && ! $license->reassignable) {
|
||||
$asset_seat->unreassignable_seat = true;
|
||||
}
|
||||
|
||||
if ($asset_seat->save()) {
|
||||
Log::debug('Checking in '.$license->name.' from asset '.$asset_seat->asset_tag);
|
||||
$asset_seat->logCheckin($asset_seat->asset, trans('admin/licenses/general.bulk.checkin_all.log_msg'));
|
||||
|
||||
@@ -39,11 +39,6 @@ class LicenseCheckoutController extends Controller
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.not_enough_seats'));
|
||||
}
|
||||
|
||||
// We don't currently allow checking out licenses to locations, so we'll reset that to user if needed
|
||||
if (session()->get('checkout_to_type') == 'location') {
|
||||
session()->put(['checkout_to_type' => 'user']);
|
||||
}
|
||||
|
||||
// Return the checkout view
|
||||
return view('licenses/checkout', compact('license'));
|
||||
}
|
||||
@@ -75,15 +70,17 @@ class LicenseCheckoutController extends Controller
|
||||
$licenseSeat = $this->findLicenseSeatToCheckout($license, $seatId);
|
||||
$licenseSeat->created_by = auth()->id();
|
||||
$licenseSeat->notes = $request->input('notes');
|
||||
|
||||
|
||||
$checkoutMethod = 'checkoutTo'.ucwords(request('checkout_to_type'));
|
||||
|
||||
if ($request->filled('asset_id')) {
|
||||
session()->put(['checkout_to_type' => 'asset']);
|
||||
|
||||
$checkoutTarget = $this->checkoutToAsset($licenseSeat);
|
||||
$request->request->add(['assigned_asset' => $checkoutTarget->id]);
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => 'asset']);
|
||||
|
||||
} elseif ($request->filled('assigned_to')) {
|
||||
session()->put(['checkout_to_type' => 'user']);
|
||||
$checkoutTarget = $this->checkoutToUser($licenseSeat);
|
||||
$request->request->add(['assigned_user' => $checkoutTarget->id]);
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => 'user']);
|
||||
@@ -92,7 +89,6 @@ class LicenseCheckoutController extends Controller
|
||||
|
||||
|
||||
if ($checkoutTarget) {
|
||||
|
||||
return Helper::getRedirectOption($request, $license->id, 'Licenses')
|
||||
->with('success', trans('admin/licenses/message.checkout.success'));
|
||||
}
|
||||
|
||||
132
app/Http/Controllers/Licenses/LicenseFilesController.php
Normal file
132
app/Http/Controllers/Licenses/LicenseFilesController.php
Normal file
@@ -0,0 +1,132 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Licenses;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\License;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class LicenseFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a license.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $licenseId = null)
|
||||
{
|
||||
$license = License::find($licenseId);
|
||||
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('update', $license);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/licenses')) {
|
||||
Storage::makeDirectory('private_uploads/licenses', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/licenses/','license-'.$license->id, $file);
|
||||
|
||||
//Log the upload to the log
|
||||
$license->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('licenses.show', $license->id)->with('success', trans('admin/licenses/message.upload.success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.nofiles'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('licenses.index')
|
||||
->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected license file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($licenseId = null, $fileId = null)
|
||||
{
|
||||
if ($license = License::find($licenseId)) {
|
||||
|
||||
$this->authorize('update', $license);
|
||||
|
||||
if ($log = Actionlog::find($fileId)) {
|
||||
|
||||
// Remove the file if one exists
|
||||
if (Storage::exists('licenses/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('licenses/'.$log->filename);
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('general.log_does_not_exist'));
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $licenseId
|
||||
* @param int $fileId
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($licenseId = null, $fileId = null, $download = true)
|
||||
{
|
||||
$license = License::find($licenseId);
|
||||
|
||||
// the license is valid
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('view', $license);
|
||||
$this->authorize('licenses.files', $license);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $license->id)->find($fileId)) {
|
||||
$file = 'private_uploads/licenses/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('licenses.show', ['licenses' => $license])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('licenses.show', ['licenses' => $license])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
|
||||
}
|
||||
}
|
||||
@@ -102,11 +102,7 @@ class LicensesController extends Controller
|
||||
$license->created_by = auth()->id();
|
||||
$license->min_amt = $request->input('min_amt');
|
||||
|
||||
if($request->get('redirect_option') === 'back'){
|
||||
session()->put(['redirect_option' => 'index']);
|
||||
} else {
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
}
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($license->save()) {
|
||||
return Helper::getRedirectOption($request, $license->id, 'Licenses')
|
||||
@@ -245,25 +241,16 @@ class LicensesController extends Controller
|
||||
$license = License::with('assignedusers')->find($license->id);
|
||||
|
||||
$users_count = User::where('autoassign_licenses', '1')->count();
|
||||
|
||||
$total_seats_count = (int) $license->totalSeatsByLicenseID();
|
||||
$total_seats_count = $license->totalSeatsByLicenseID();
|
||||
$available_seats_count = $license->availCount()->count();
|
||||
$unreassignable_seats_count = License::unReassignableCount($license);
|
||||
|
||||
if(!$license->reassignable){
|
||||
$checkedout_seats_count = ($total_seats_count - $available_seats_count - $unreassignable_seats_count );
|
||||
}
|
||||
else {
|
||||
$checkedout_seats_count = ($total_seats_count - $available_seats_count);
|
||||
}
|
||||
$checkedout_seats_count = ($total_seats_count - $available_seats_count);
|
||||
|
||||
$this->authorize('view', $license);
|
||||
return view('licenses.view', compact('license'))
|
||||
->with('users_count', $users_count)
|
||||
->with('total_seats_count', $total_seats_count)
|
||||
->with('available_seats_count', $available_seats_count)
|
||||
->with('checkedout_seats_count', $checkedout_seats_count)
|
||||
->with('unreassignable_seats_count', $unreassignable_seats_count);
|
||||
->with('checkedout_seats_count', $checkedout_seats_count);
|
||||
|
||||
}
|
||||
|
||||
@@ -317,16 +304,13 @@ class LicensesController extends Controller
|
||||
$response = new StreamedResponse(function () {
|
||||
// Open output stream
|
||||
$handle = fopen('php://output', 'w');
|
||||
$licenses = License::with('company',
|
||||
$licenses= License::with('company',
|
||||
'manufacturer',
|
||||
'category',
|
||||
'supplier',
|
||||
'adminuser',
|
||||
'assignedusers');
|
||||
if (request()->filled('category_id')) {
|
||||
$licenses = $licenses->where('category_id', request()->input('category_id'));
|
||||
}
|
||||
$licenses = $licenses->orderBy('created_at', 'DESC');
|
||||
'assignedusers')
|
||||
->orderBy('created_at', 'DESC');
|
||||
Company::scopeCompanyables($licenses)
|
||||
->chunk(500, function ($licenses) use ($handle) {
|
||||
$headers = [
|
||||
@@ -373,7 +357,7 @@ class LicensesController extends Controller
|
||||
$license->order_number,
|
||||
$license->free_seat_count,
|
||||
$license->seats,
|
||||
($license->adminuser ? $license->adminuser->display_name : trans('admin/reports/general.deleted_user')),
|
||||
($license->adminuser ? $license->adminuser->present()->fullName() : trans('admin/reports/general.deleted_user')),
|
||||
$license->depreciation ? $license->depreciation->name: '',
|
||||
$license->updated_at,
|
||||
$license->deleted_at,
|
||||
|
||||
@@ -96,18 +96,7 @@ class LocationsController extends Controller
|
||||
$location->company_id = $request->input('company_id');
|
||||
}
|
||||
|
||||
if ($request->has('use_cloned_image')) {
|
||||
$cloned_model_img = Location::select('image')->find($request->input('clone_image_from_id'));
|
||||
if ($cloned_model_img) {
|
||||
$new_image_name = 'clone-'.date('U').'-'.$cloned_model_img->image;
|
||||
$new_image = 'locations/'.$new_image_name;
|
||||
Storage::disk('public')->copy('locations/'.$cloned_model_img->image, $new_image);
|
||||
$location->image = $new_image_name;
|
||||
}
|
||||
|
||||
} else {
|
||||
$location = $request->handleImages($location);
|
||||
}
|
||||
$location = $request->handleImages($location);
|
||||
|
||||
if ($location->save()) {
|
||||
return redirect()->route('locations.index')->with('success', trans('admin/locations/message.create.success'));
|
||||
@@ -286,9 +275,9 @@ class LocationsController extends Controller
|
||||
|
||||
// unset these values
|
||||
$location->id = null;
|
||||
$location->image = null;
|
||||
|
||||
return view('locations/edit')
|
||||
->with('cloned_model', $location_to_clone)
|
||||
->with('item', $location);
|
||||
}
|
||||
|
||||
|
||||
111
app/Http/Controllers/LocationsFilesController.php
Normal file
111
app/Http/Controllers/LocationsFilesController.php
Normal file
@@ -0,0 +1,111 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Location;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use \Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
class LocationsFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Upload a file to the server.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $modelId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@since [v1.0]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, Location $location) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', $location);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
|
||||
if (! Storage::exists('private_uploads/locations')) {
|
||||
Storage::makeDirectory('private_uploads/locations', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/locations/','location-'.$location->id, $file);
|
||||
$location->logUpload($file_name, $request->get('notes'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('general.file_upload_success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('error', trans('admin/hardware/message.upload.nofiles'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $modelId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show(Location $location, $fileId = null) : StreamedResponse | Response | RedirectResponse | BinaryFileResponse
|
||||
{
|
||||
|
||||
$this->authorize('view', $location);
|
||||
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return redirect()->back()->withFragment('files')->with('error', 'No matching file record');
|
||||
}
|
||||
|
||||
$file = 'private_uploads/locations/'.$log->filename;
|
||||
|
||||
if (! Storage::exists($file)) {
|
||||
return redirect()->back()->withFragment('files')->with('error', 'No matching file on server');
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the associated file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $modelId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function destroy(Location $location, $fileId = null) : RedirectResponse
|
||||
{
|
||||
$rel_path = 'private_uploads/locations';
|
||||
$this->authorize('update', $location);
|
||||
$log = Actionlog::find($fileId);
|
||||
|
||||
if ($log) {
|
||||
|
||||
// This should be moved to purge
|
||||
// if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
// Storage::delete($rel_path.'/'.$log->filename);
|
||||
// }
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
|
||||
}
|
||||
}
|
||||
@@ -51,7 +51,7 @@ class ManufacturersController extends Controller
|
||||
$manufacturers_count = Manufacturer::withTrashed()->count();
|
||||
|
||||
if ($manufacturers_count == 0) {
|
||||
Artisan::call('db:seed', ['--class' => 'Database\\Seeders\\ManufacturerSeeder', '--force' => true]);
|
||||
Artisan::call('db:seed', ['--class' => 'ManufacturerSeeder']);
|
||||
return redirect()->route('manufacturers.index')->with('success', trans('general.seeding.manufacturers.success'));
|
||||
}
|
||||
|
||||
|
||||
@@ -9,7 +9,7 @@ use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
use App\Models\Maintenance;
|
||||
use App\Models\AssetMaintenance;
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\Company;
|
||||
use App\Models\CustomField;
|
||||
@@ -17,11 +17,13 @@ use App\Models\Depreciation;
|
||||
use App\Models\License;
|
||||
use App\Models\ReportTemplate;
|
||||
use App\Models\Setting;
|
||||
use App\Notifications\CheckoutAssetNotification;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Relations\MorphTo;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\Response;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use League\Csv\Reader;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
@@ -159,7 +161,7 @@ class ReportsController extends Controller
|
||||
$row[] = e($asset->serial);
|
||||
|
||||
if ($target = $asset->assignedTo) {
|
||||
$row[] = e($target->display_name);
|
||||
$row[] = e($target->present()->name());
|
||||
} else {
|
||||
$row[] = ''; // Empty string if unassigned
|
||||
}
|
||||
@@ -275,7 +277,7 @@ class ReportsController extends Controller
|
||||
|
||||
if ($actionlog->target) {
|
||||
if ($actionlog->targetType() == 'user') {
|
||||
$target_name = $actionlog->target->display_name;
|
||||
$target_name = $actionlog->target->getFullNameAttribute();
|
||||
} else {
|
||||
$target_name = $actionlog->target->getDisplayNameAttribute();
|
||||
}
|
||||
@@ -289,7 +291,7 @@ class ReportsController extends Controller
|
||||
|
||||
$row = [
|
||||
$actionlog->created_at,
|
||||
($actionlog->adminuser) ? e($actionlog->adminuser->display_name) : '',
|
||||
($actionlog->adminuser) ? e($actionlog->adminuser->getFullNameAttribute()) : '',
|
||||
$actionlog->present()->actionType(),
|
||||
e($actionlog->itemType()),
|
||||
($actionlog->itemType() == 'user') ? $actionlog->filename : $item_name,
|
||||
@@ -830,7 +832,7 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('location')) {
|
||||
$row[] = ($asset->location) ? $asset->location->display_name : '';
|
||||
$row[] = ($asset->location) ? $asset->location->present()->name() : '';
|
||||
}
|
||||
|
||||
if ($request->filled('location_address')) {
|
||||
@@ -843,7 +845,7 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('rtd_location')) {
|
||||
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->display_name : '';
|
||||
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->present()->name() : '';
|
||||
}
|
||||
|
||||
if ($request->filled('rtd_location_address')) {
|
||||
@@ -856,8 +858,8 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('assigned_to')) {
|
||||
$row[] = ($asset->assigned) ? $asset->assigned->display_name : '';
|
||||
$row[] = ($asset->assigned) ? $asset->assignedType() : '';
|
||||
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? $asset->assigned->getFullNameAttribute() : ($asset->assigned ? $asset->assigned->display_name : '');
|
||||
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? 'user' : $asset->assignedType();
|
||||
}
|
||||
|
||||
if ($request->filled('username')) {
|
||||
@@ -1036,11 +1038,11 @@ class ReportsController extends Controller
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
*/
|
||||
public function getMaintenancesReport() : View
|
||||
public function getAssetMaintenancesReport() : View
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
|
||||
return view('reports.maintenances');
|
||||
return view('reports.asset_maintenances');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1049,11 +1051,11 @@ class ReportsController extends Controller
|
||||
* @author Vincent Sposato <vincent.sposato@gmail.com>
|
||||
* @version v1.0
|
||||
*/
|
||||
public function exportMaintenancesReport() : Response
|
||||
public function exportAssetMaintenancesReport() : Response
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
// Grab all the improvements
|
||||
$Maintenances = Maintenance::with('asset', 'supplier')
|
||||
$assetMaintenances = AssetMaintenance::with('asset', 'supplier')
|
||||
->orderBy('created_at', 'DESC')
|
||||
->get();
|
||||
|
||||
@@ -1061,36 +1063,36 @@ class ReportsController extends Controller
|
||||
|
||||
$header = [
|
||||
trans('admin/hardware/table.asset_tag'),
|
||||
trans('admin/maintenances/table.asset_name'),
|
||||
trans('admin/asset_maintenances/table.asset_name'),
|
||||
trans('general.supplier'),
|
||||
trans('admin/maintenances/form.asset_maintenance_type'),
|
||||
trans('admin/maintenances/form.title'),
|
||||
trans('admin/maintenances/form.start_date'),
|
||||
trans('admin/maintenances/form.completion_date'),
|
||||
trans('admin/maintenances/form.asset_maintenance_time'),
|
||||
trans('admin/maintenances/form.cost'),
|
||||
trans('admin/asset_maintenances/form.asset_maintenance_type'),
|
||||
trans('admin/asset_maintenances/form.title'),
|
||||
trans('admin/asset_maintenances/form.start_date'),
|
||||
trans('admin/asset_maintenances/form.completion_date'),
|
||||
trans('admin/asset_maintenances/form.asset_maintenance_time'),
|
||||
trans('admin/asset_maintenances/form.cost'),
|
||||
];
|
||||
|
||||
$header = array_map('trim', $header);
|
||||
$rows[] = implode(',', $header);
|
||||
|
||||
foreach ($Maintenances as $maintenance) {
|
||||
foreach ($assetMaintenances as $assetMaintenance) {
|
||||
$row = [];
|
||||
$row[] = str_replace(',', '', e($maintenance->asset->asset_tag));
|
||||
$row[] = str_replace(',', '', e($maintenance->asset->name));
|
||||
$row[] = str_replace(',', '', e($maintenance->supplier->name));
|
||||
$row[] = e($maintenance->improvement_type);
|
||||
$row[] = e($maintenance->name);
|
||||
$row[] = e($maintenance->start_date);
|
||||
$row[] = e($maintenance->completion_date);
|
||||
if (is_null($maintenance->asset_maintenance_time)) {
|
||||
$row[] = str_replace(',', '', e($assetMaintenance->asset->asset_tag));
|
||||
$row[] = str_replace(',', '', e($assetMaintenance->asset->name));
|
||||
$row[] = str_replace(',', '', e($assetMaintenance->supplier->name));
|
||||
$row[] = e($assetMaintenance->improvement_type);
|
||||
$row[] = e($assetMaintenance->title);
|
||||
$row[] = e($assetMaintenance->start_date);
|
||||
$row[] = e($assetMaintenance->completion_date);
|
||||
if (is_null($assetMaintenance->asset_maintenance_time)) {
|
||||
$improvementTime = (int) Carbon::now()
|
||||
->diffInDays(Carbon::parse($maintenance->start_date), true);
|
||||
->diffInDays(Carbon::parse($assetMaintenance->start_date), true);
|
||||
} else {
|
||||
$improvementTime = (int) $maintenance->asset_maintenance_time;
|
||||
$improvementTime = (int) $assetMaintenance->asset_maintenance_time;
|
||||
}
|
||||
$row[] = $improvementTime;
|
||||
$row[] = trans('general.currency') . Helper::formatCurrencyOutput($maintenance->cost);
|
||||
$row[] = trans('general.currency') . Helper::formatCurrencyOutput($assetMaintenance->cost);
|
||||
$rows[] = implode(',', $row);
|
||||
}
|
||||
|
||||
@@ -1260,7 +1262,7 @@ class ReportsController extends Controller
|
||||
$row[] = str_replace(',', '', e($item['assetItem']->model->name));
|
||||
$row[] = str_replace(',', '', e($item['assetItem']->name));
|
||||
$row[] = str_replace(',', '', e($item['assetItem']->asset_tag));
|
||||
$row[] = str_replace(',', '', e(($item['acceptance']->assignedTo) ? $item['acceptance']->assignedTo->display_name : trans('admin/reports/general.deleted_user')));
|
||||
$row[] = str_replace(',', '', e(($item['acceptance']->assignedTo) ? $item['acceptance']->assignedTo->present()->name() : trans('admin/reports/general.deleted_user')));
|
||||
$rows[] = implode(',', $row);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -873,7 +873,6 @@ class SettingsController extends Controller
|
||||
$setting->ldap_default_group = $request->input('ldap_default_group');
|
||||
$setting->ldap_filter = $request->input('ldap_filter');
|
||||
$setting->ldap_username_field = $request->input('ldap_username_field');
|
||||
$setting->ldap_display_name = $request->input('ldap_display_name');
|
||||
$setting->ldap_lname_field = $request->input('ldap_lname_field');
|
||||
$setting->ldap_fname_field = $request->input('ldap_fname_field');
|
||||
$setting->ldap_auth_filter_query = $request->input('ldap_auth_filter_query');
|
||||
@@ -890,12 +889,7 @@ class SettingsController extends Controller
|
||||
$setting->ldap_pw_sync = $request->input('ldap_pw_sync', '0');
|
||||
$setting->custom_forgot_pass_url = $request->input('custom_forgot_pass_url');
|
||||
$setting->ldap_phone_field = $request->input('ldap_phone');
|
||||
$setting->ldap_mobile = $request->input('ldap_mobile');
|
||||
$setting->ldap_jobtitle = $request->input('ldap_jobtitle');
|
||||
$setting->ldap_address = $request->input('ldap_address');
|
||||
$setting->ldap_city = $request->input('ldap_city');
|
||||
$setting->ldap_state = $request->input('ldap_state');
|
||||
$setting->ldap_zip = $request->input('ldap_zip');
|
||||
$setting->ldap_country = $request->input('ldap_country');
|
||||
$setting->ldap_location = $request->input('ldap_location');
|
||||
$setting->ldap_dept = $request->input('ldap_dept');
|
||||
@@ -1090,7 +1084,6 @@ class SettingsController extends Controller
|
||||
|
||||
if (! config('app.lock_passwords')) {
|
||||
if (Storage::exists($path.'/'.$filename)) {
|
||||
Log::warning('User '.auth()->user()->username.' is attempting to download backup file: '.$filename);
|
||||
return StorageHelper::downloader($path.'/'.$filename);
|
||||
} else {
|
||||
// Redirect to the backup page
|
||||
@@ -1118,7 +1111,6 @@ class SettingsController extends Controller
|
||||
if (Storage::exists($path . '/' . $filename)) {
|
||||
|
||||
try {
|
||||
Log::warning('User '.auth()->user()->username.' is attempting to delete backup file: '.$filename);
|
||||
Storage::delete($path . '/' . $filename);
|
||||
return redirect()->route('settings.backups.index')->with('success', trans('admin/settings/message.backup.file_deleted'));
|
||||
} catch (\Exception $e) {
|
||||
@@ -1198,7 +1190,7 @@ class SettingsController extends Controller
|
||||
'--force' => true,
|
||||
]);
|
||||
|
||||
Log::warning('User '.auth()->user()->username.' is attempting to restore from: '. storage_path($path).'/'.$filename);
|
||||
Log::debug('Attempting to restore from: '. storage_path($path).'/'.$filename);
|
||||
|
||||
$restore_params = [
|
||||
'--force' => true,
|
||||
@@ -1347,11 +1339,9 @@ class SettingsController extends Controller
|
||||
'name' => config('mail.from.name'),
|
||||
'email' => config('mail.from.address'),
|
||||
])->notify(new MailTest());
|
||||
Log::debug('Attempting to send mail to '.config('mail.from.address'));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('mail_sent.mail_sent')));
|
||||
} catch (\Exception $e) {
|
||||
Log::error('Mail sent from '.config('mail.from.address') .' with errors '. $e->getMessage());
|
||||
Log::debug($e);
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, $e->getMessage()));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Supplier;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
|
||||
@@ -121,7 +122,7 @@ class SuppliersController extends Controller
|
||||
public function destroy($supplierId) : RedirectResponse
|
||||
{
|
||||
$this->authorize('delete', Supplier::class);
|
||||
if (is_null($supplier = Supplier::with('maintenances', 'assets', 'licenses')->withCount('maintenances as maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->find($supplierId))) {
|
||||
if (is_null($supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->find($supplierId))) {
|
||||
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.not_found'));
|
||||
}
|
||||
|
||||
@@ -129,8 +130,8 @@ class SuppliersController extends Controller
|
||||
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_assets', ['asset_count' => (int) $supplier->assets_count]));
|
||||
}
|
||||
|
||||
if ($supplier->maintenances_count > 0) {
|
||||
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_maintenances', ['maintenances_count' => $supplier->maintenances_count]));
|
||||
if ($supplier->asset_maintenances_count > 0) {
|
||||
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.delete.assoc_maintenances', ['asset_maintenances_count' => $supplier->asset_maintenances_count]));
|
||||
}
|
||||
|
||||
if ($supplier->licenses_count > 0) {
|
||||
|
||||
@@ -1,162 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
|
||||
/**
|
||||
* This controller provide the health route for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v1.0
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
|
||||
*/
|
||||
class UploadedFilesController extends Controller
|
||||
{
|
||||
|
||||
|
||||
/**
|
||||
* Accepts a POST to upload a file to the server.
|
||||
*
|
||||
* @param \App\Http\Requests\UploadFileRequest $request
|
||||
* @param string $object_type the type of object to upload the file to
|
||||
* @param int $id the ID of the object to store so we can check permisisons
|
||||
* @since [v8.2.2]
|
||||
* @author [A. Gianotto <snipe@snipe.net>]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $object_type, $id) : RedirectResponse
|
||||
{
|
||||
|
||||
// Check the permissions to make sure the user can view the object
|
||||
$object = self::$map_object_type[$object_type]::withTrashed()->find($id);
|
||||
$this->authorize('update', $object);
|
||||
|
||||
if (!$object) {
|
||||
return redirect()->back()->withFragment('files')->with('error',trans('general.file_upload_status.invalid_object'));
|
||||
}
|
||||
|
||||
// If the file storage directory doesn't exist, create it
|
||||
if (! Storage::exists(self::$map_storage_path[$object_type])) {
|
||||
Storage::makeDirectory(self::$map_storage_path[$object_type], 775);
|
||||
}
|
||||
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
// Loop over the attached files and add them to the object
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile(self::$map_storage_path[$object_type], self::$map_file_prefix[$object_type].'-'.$object->id, $file);
|
||||
$files[] = $file_name;
|
||||
$object->logUpload($file_name, $request->get('notes'));
|
||||
}
|
||||
|
||||
$files = Actionlog::select('action_logs.*')->where('action_type', '=', 'uploaded')
|
||||
->where('item_type', '=', self::$map_object_type[$object_type])
|
||||
->where('item_id', '=', $id)->whereIn('filename', $files)
|
||||
->get();
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans_choice('general.file_upload_status.upload.success', count($files)));
|
||||
}
|
||||
|
||||
// No files were submitted
|
||||
return redirect()->back()->withFragment('files')->with('error', trans('general.file_upload_status.nofiles'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
* This isn't currently used, but is here for future use.
|
||||
*
|
||||
* @param \App\Http\Requests\UploadFileRequest $request
|
||||
* @param string $object_type the type of object to upload the file to
|
||||
* @param int $id the ID of the object to delete from so we can check permisisons
|
||||
* @param $file_id the ID of the file to show from the action_logs table
|
||||
* @since [v8.2.2]
|
||||
* @author [A. Gianotto <snipe@snipe.net>]
|
||||
*/
|
||||
public function show($object_type, $id, $file_id) : RedirectResponse | StreamedResponse | Storage | StorageHelper | BinaryFileResponse
|
||||
{
|
||||
// Check the permissions to make sure the user can view the object
|
||||
$object = self::$map_object_type[$object_type]::withTrashed()->find($id);
|
||||
$this->authorize('view', $object);
|
||||
|
||||
if (!$object) {
|
||||
return redirect()->back()->withFragment('files')->with('error',trans('general.file_upload_status.invalid_object'));
|
||||
}
|
||||
|
||||
|
||||
// Check that the file being requested exists for the object
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_type', self::$map_object_type[$object_type])->where('item_id', $object->id)->find($file_id))
|
||||
{
|
||||
return redirect()->back()->withFragment('files')->with('error', trans('general.file_upload_status.invalid_id'));
|
||||
}
|
||||
|
||||
|
||||
if (! Storage::exists(self::$map_storage_path[$object_type].'/'.$log->filename))
|
||||
{
|
||||
return redirect()->back()->withFragment('files')->with('error', trans('general.file_upload_status.file_not_found'));
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download(self::$map_storage_path[$object_type].'/'.$log->filename, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader(self::$map_storage_path[$object_type].'/'.$log->filename);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the associated file
|
||||
*
|
||||
* @param \App\Http\Requests\UploadFileRequest $request
|
||||
* @param string $object_type the type of object to upload the file to
|
||||
* @param int $id the ID of the object to delete from so we can check permisisons
|
||||
* @param $file_id the ID of the file to delete from the action_logs table
|
||||
* @since [v8.2.2]
|
||||
* @author [A. Gianotto <snipe@snipe.net>]
|
||||
*/
|
||||
public function destroy($object_type, $id, $file_id) : RedirectResponse
|
||||
{
|
||||
|
||||
// Check the permissions to make sure the user can view the object
|
||||
$object = self::$map_object_type[$object_type]::withTrashed()->find($id);
|
||||
$this->authorize('update', self::$map_object_type[$object_type]);
|
||||
|
||||
if (!$object) {
|
||||
return redirect()->back()->withFragment('files')->with('error',trans('general.file_upload_status.invalid_object'));
|
||||
}
|
||||
|
||||
|
||||
// Check for the file
|
||||
$log = Actionlog::where('id',$file_id)->where('item_type', self::$map_object_type[$object_type])
|
||||
->where('item_id', $object->id)->first();
|
||||
|
||||
if ($log) {
|
||||
// Check the file actually exists, and delete it
|
||||
if (Storage::exists(self::$map_storage_path[$object_type].'/'.$log->filename)) {
|
||||
Storage::delete(self::$map_storage_path[$object_type].'/'.$log->filename);
|
||||
}
|
||||
// Delete the record of the file
|
||||
if ($log->logUploadDelete($object, $log->filename)) {
|
||||
return redirect()->back()->withFragment('files')->with('success', trans_choice('general.file_upload_status.delete.success', 1));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The file doesn't seem to really exist, so report an error
|
||||
return redirect()->back()->withFragment('files')->with('success', trans_choice('general.file_upload_status.delete.error', 1));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
129
app/Http/Controllers/Users/UserFilesController.php
Normal file
129
app/Http/Controllers/Users/UserFilesController.php
Normal file
@@ -0,0 +1,129 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class UserFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Return JSON response with a list of user details for the getIndex() view.
|
||||
*
|
||||
* @param UploadFileRequest $request
|
||||
* @param int $userId
|
||||
* @return string JSON
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, User $user)
|
||||
{
|
||||
$this->authorize('update', $user);
|
||||
$files = $request->file('file');
|
||||
|
||||
if (is_null($files)) {
|
||||
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/users/', 'user-'.$user->id, $file);
|
||||
|
||||
//Log the uploaded file to the log
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->note = $request->input('notes');
|
||||
$logAction->target_id = null;
|
||||
$logAction->created_at = date("Y-m-d H:i:s");
|
||||
$logAction->filename = $file_name;
|
||||
$logAction->action_type = 'uploaded';
|
||||
|
||||
if (! $logAction->save()) {
|
||||
return JsonResponse::create(['error' => 'Failed validation: '.print_r($logAction->getErrors(), true)], 500);
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.upload.success'));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
* @param int $userId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($userId = null, $fileId = null)
|
||||
{
|
||||
if ($user = User::find($userId)) {
|
||||
|
||||
$this->authorize('delete', $user);
|
||||
$rel_path = 'private_uploads/users';
|
||||
|
||||
|
||||
if ($log = Actionlog::find($fileId)) {
|
||||
$filename = $log->filename;
|
||||
$log->delete();
|
||||
|
||||
if (Storage::exists($rel_path.'/'.$filename)) {
|
||||
Storage::delete($rel_path.'/'.$filename);
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.deletefile.success'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->back()->with('success', trans('admin/users/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', ['id' => $userId]));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display/download the uploaded file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
* @param int $userId
|
||||
* @param int $fileId
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show(User $user, $fileId = null)
|
||||
{
|
||||
|
||||
|
||||
if (empty($fileId)) {
|
||||
return redirect()->route('users.show')->with('error', 'Invalid file request');
|
||||
}
|
||||
|
||||
$this->authorize('view', $user);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $user->id)->find($fileId)) {
|
||||
$file = 'private_uploads/users/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
}
|
||||
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
@@ -14,9 +14,14 @@ use App\Models\Group;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\WelcomeNotification;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Redirect;
|
||||
use Str;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use App\Notifications\CurrentInventory;
|
||||
|
||||
@@ -90,7 +95,6 @@ class UsersController extends Controller
|
||||
//Username, email, and password need to be handled specially because the need to respect config values on an edit.
|
||||
$user->email = trim($request->input('email'));
|
||||
$user->username = trim($request->input('username'));
|
||||
$user->display_name = $request->input('display_name');
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
@@ -101,7 +105,6 @@ class UsersController extends Controller
|
||||
$user->activated = $request->input('activated', 0);
|
||||
$user->jobtitle = $request->input('jobtitle');
|
||||
$user->phone = $request->input('phone');
|
||||
$user->mobile = $request->input('mobile');
|
||||
$user->location_id = $request->input('location_id', null);
|
||||
$user->department_id = $request->input('department_id', null);
|
||||
$user->company_id = Company::getIdForUser($request->input('company_id', null));
|
||||
@@ -127,35 +130,30 @@ class UsersController extends Controller
|
||||
}
|
||||
$user->permissions = json_encode($permissions_array);
|
||||
|
||||
// we have to invoke the form request here to handle image uploads
|
||||
// we have to invoke the
|
||||
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
|
||||
if ($request->get('redirect_option') === 'back'){
|
||||
session()->put(['redirect_option' => 'index']);
|
||||
} else {
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
}
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($user->save()) {
|
||||
|
||||
if (($user->activated == '1') && ($user->email != '') && ($request->input('send_welcome') == '1')) {
|
||||
|
||||
try {
|
||||
$user->notify(new WelcomeNotification($user));
|
||||
} catch (\Exception $e) {
|
||||
Log::warning('Could not send welcome notification for user: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
if ($request->filled('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
} else {
|
||||
$user->groups()->sync([]);
|
||||
}
|
||||
|
||||
if (($request->input('email_user') == 1) && ($request->filled('email'))) {
|
||||
// Send the credentials through email
|
||||
$data = [];
|
||||
$data['email'] = e($request->input('email'));
|
||||
$data['username'] = e($request->input('username'));
|
||||
$data['first_name'] = e($request->input('first_name'));
|
||||
$data['last_name'] = e($request->input('last_name'));
|
||||
$data['password'] = e($request->input('password'));
|
||||
|
||||
$user->notify(new WelcomeNotification($data));
|
||||
}
|
||||
|
||||
return Helper::getRedirectOption($request, $user->id, 'Users')
|
||||
->with('success', trans('admin/users/message.success.create'));
|
||||
}
|
||||
@@ -250,18 +248,22 @@ class UsersController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
// Only save groups if the user is a superuser
|
||||
if (auth()->user()->isSuperUser()) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
}
|
||||
|
||||
// Update the user fields
|
||||
|
||||
$user->username = trim($request->input('username'));
|
||||
$user->email = trim($request->input('email'));
|
||||
$user->first_name = $request->input('first_name');
|
||||
$user->last_name = $request->input('last_name');
|
||||
$user->display_name = $request->input('display_name');
|
||||
$user->two_factor_optin = $request->input('two_factor_optin') ?: 0;
|
||||
$user->locale = $request->input('locale');
|
||||
$user->employee_num = $request->input('employee_num');
|
||||
$user->activated = $request->input('activated', 0);
|
||||
$user->jobtitle = $request->input('jobtitle', null);
|
||||
$user->phone = $request->input('phone');
|
||||
$user->mobile = $request->input('mobile');
|
||||
$user->location_id = $request->input('location_id', null);
|
||||
$user->company_id = Company::getIdForUser($request->input('company_id', null));
|
||||
$user->manager_id = $request->input('manager_id', null);
|
||||
@@ -271,6 +273,8 @@ class UsersController extends Controller
|
||||
$user->city = $request->input('city', null);
|
||||
$user->state = $request->input('state', null);
|
||||
$user->country = $request->input('country', null);
|
||||
// if a user is editing themselves we should always keep activated true
|
||||
$user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 0);
|
||||
$user->zip = $request->input('zip', null);
|
||||
$user->remote = $request->input('remote', 0);
|
||||
$user->vip = $request->input('vip', 0);
|
||||
@@ -279,49 +283,30 @@ class UsersController extends Controller
|
||||
$user->end_date = $request->input('end_date', null);
|
||||
$user->autoassign_licenses = $request->input('autoassign_licenses', 0);
|
||||
|
||||
// Set this here so that we can overwrite it later if the user is an admin or superadmin
|
||||
$user->activated = $request->input('activated', auth()->user()->is($user) ? 1 : $user->activated);
|
||||
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)
|
||||
->update(['location_id' => $request->input('location_id', null)]);
|
||||
|
||||
// check for permissions related fields and only set them if the user has permission to edit them
|
||||
if (auth()->user()->can('canEditAuthFields', $user) && auth()->user()->can('editableOnDemo')) {
|
||||
|
||||
$user->username = trim($request->input('username'));
|
||||
$user->email = trim($request->input('email'));
|
||||
$user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 0);
|
||||
|
||||
// Do we want to update the user password?
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
$permissions_array = $request->input('permission');
|
||||
|
||||
// Strip out the superuser permission if the user isn't a superadmin
|
||||
if (! auth()->user()->isSuperUser()) {
|
||||
unset($permissions_array['superuser']);
|
||||
$permissions_array['superuser'] = $orig_superuser;
|
||||
}
|
||||
|
||||
$user->permissions = json_encode($permissions_array);
|
||||
|
||||
// Only save groups if the user is a superuser
|
||||
if (auth()->user()->isSuperUser()) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
}
|
||||
// Do we want to update the user password?
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)
|
||||
->update(['location_id' => $user->location_id]);
|
||||
|
||||
$permissions_array = $request->input('permission');
|
||||
|
||||
// Strip out the superuser permission if the user isn't a superadmin
|
||||
if (! auth()->user()->isSuperUser()) {
|
||||
unset($permissions_array['superuser']);
|
||||
$permissions_array['superuser'] = $orig_superuser;
|
||||
}
|
||||
|
||||
$user->permissions = json_encode($permissions_array);
|
||||
|
||||
// Handle uploaded avatar
|
||||
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
@@ -455,7 +440,7 @@ class UsersController extends Controller
|
||||
app('request')->request->set('permissions', $permissions);
|
||||
|
||||
|
||||
$user_to_clone = User::with('userloc')->withTrashed()->find($user->id);
|
||||
$user_to_clone = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($user->id);
|
||||
// Make sure they can view this particular user
|
||||
$this->authorize('view', $user_to_clone);
|
||||
|
||||
@@ -470,8 +455,6 @@ class UsersController extends Controller
|
||||
$user->last_name = '';
|
||||
$user->email = substr($user->email, ($pos = strpos($user->email, '@')) !== false ? $pos : 0);
|
||||
$user->id = null;
|
||||
$user->username = null;
|
||||
$user->avatar = null;
|
||||
|
||||
// Get this user's groups
|
||||
$userGroups = $user_to_clone->groups()->pluck('name', 'id');
|
||||
@@ -487,7 +470,7 @@ class UsersController extends Controller
|
||||
->with('user', $user)
|
||||
->with('groups', Group::pluck('name', 'id'))
|
||||
->with('userGroups', $userGroups)
|
||||
->with('cloned_model', $user_to_clone)
|
||||
->with('clone_user', $user_to_clone)
|
||||
->with('item', $user);
|
||||
}
|
||||
|
||||
@@ -578,10 +561,10 @@ class UsersController extends Controller
|
||||
$user->employee_num,
|
||||
$user->first_name,
|
||||
$user->last_name,
|
||||
$user->display_name,
|
||||
$user->present()->fullName(),
|
||||
$user->username,
|
||||
$user->email,
|
||||
($user->manager) ? $user->manager->display_name : '',
|
||||
($user->manager) ? $user->manager->present()->fullName() : '',
|
||||
($user->userloc) ? $user->userloc->name : '',
|
||||
($user->department) ? $user->department->name : '',
|
||||
$user->assets->count(),
|
||||
|
||||
@@ -185,7 +185,7 @@ class ViewAssetsController extends Controller
|
||||
$logaction->target_type = User::class;
|
||||
|
||||
$data['item_quantity'] = $request->has('request-quantity') ? e($request->input('request-quantity')) : 1;
|
||||
$data['requested_by'] = $user->display_name;
|
||||
$data['requested_by'] = $user->present()->fullName();
|
||||
$data['item'] = $item;
|
||||
$data['item_type'] = $itemType;
|
||||
$data['target'] = auth()->user();
|
||||
|
||||
@@ -26,6 +26,7 @@ class SecurityHeaders
|
||||
$response = $next($request);
|
||||
|
||||
$response->headers->set('X-Content-Type-Options', 'nosniff');
|
||||
$response->headers->set('X-XSS-Protection', '1; mode=block');
|
||||
|
||||
// Ugh. Feature-Policy is dumb and clumsy and mostly irrelevant for Snipe-IT,
|
||||
// since we don't provide any way to IFRAME anything in in the first place.
|
||||
|
||||
@@ -11,7 +11,6 @@ use Illuminate\Support\Facades\Storage;
|
||||
use Intervention\Image\Exception\NotReadableException;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Str;
|
||||
|
||||
class ImageUploadRequest extends Request
|
||||
{
|
||||
@@ -71,25 +70,19 @@ class ImageUploadRequest extends Request
|
||||
public function handleImages($item, $w = 600, $form_fieldname = 'image', $path = null, $db_fieldname = 'image')
|
||||
{
|
||||
|
||||
$type = class_basename(get_class($item));
|
||||
$type = strtolower(class_basename(get_class($item)));
|
||||
|
||||
if (is_null($path)) {
|
||||
|
||||
$path = strtolower(str_plural($type));
|
||||
$path = str_plural($type);
|
||||
|
||||
if ($type == 'AssetModel') {
|
||||
if ($type == 'assetmodel') {
|
||||
$path = 'models';
|
||||
}
|
||||
|
||||
if ($type == 'user') {
|
||||
$path = 'avatars';
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if (!Storage::disk('public')->exists($path)) {
|
||||
Storage::disk('public')->makeDirectory($path);
|
||||
}
|
||||
|
||||
if ($this->offsetGet($form_fieldname) instanceof UploadedFile) {
|
||||
@@ -100,9 +93,10 @@ class ImageUploadRequest extends Request
|
||||
|
||||
if (isset($image)) {
|
||||
|
||||
if (!config('app.lock_passwords')) {
|
||||
|
||||
$ext = $image->guessExtension();
|
||||
$file_name = $type.'-'.$form_fieldname.($item->id ?? '-'.$item->id).'-'.str_random(10).'.'.$ext;
|
||||
$file_name = $type.'-'.$form_fieldname.'-'.$item->id.'-'.str_random(10).'.'.$ext;
|
||||
|
||||
if (($image->getMimeType() == 'image/vnd.microsoft.icon') || ($image->getMimeType() == 'image/x-icon') || ($image->getMimeType() == 'image/avif') || ($image->getMimeType() == 'image/webp')) {
|
||||
// If the file is an icon, webp or avif, we need to just move it since gd doesn't support resizing
|
||||
@@ -144,7 +138,7 @@ class ImageUploadRequest extends Request
|
||||
// Remove Current image if exists
|
||||
$item = $this->deleteExistingImage($item, $path, $db_fieldname);
|
||||
$item->{$db_fieldname} = $file_name;
|
||||
|
||||
}
|
||||
|
||||
|
||||
// If the user isn't uploading anything new but wants to delete their old image, do so
|
||||
|
||||
@@ -109,7 +109,7 @@ class SettingsSamlRequest extends FormRequest
|
||||
];
|
||||
|
||||
$pkey = openssl_pkey_new([
|
||||
'private_key_bits' => config('app.saml_key_size'),
|
||||
'private_key_bits' => 2048,
|
||||
'private_key_type' => OPENSSL_KEYTYPE_RSA,
|
||||
]);
|
||||
|
||||
|
||||
@@ -80,20 +80,9 @@ class UploadFileRequest extends Request
|
||||
{
|
||||
$attributes = [];
|
||||
|
||||
if (($this->file) && (is_array($this->file))) {
|
||||
|
||||
if ($this->file) {
|
||||
for ($i = 0; $i < count($this->file); $i++) {
|
||||
|
||||
try {
|
||||
|
||||
if ($this->file[$i]) {
|
||||
$attributes['file.'.$i] = $this->file[$i]->getClientOriginalName();
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
$attributes['file.'.$i] = 'Invalid file';
|
||||
}
|
||||
|
||||
$attributes['file.'.$i] = $this->file[$i]->getClientOriginalName();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class AccessoriesTransformer
|
||||
'checkouts_count' => $accessory->checkouts_count,
|
||||
'created_by' => ($accessory->adminuser) ? [
|
||||
'id' => (int) $accessory->adminuser->id,
|
||||
'name'=> e($accessory->adminuser->display_name),
|
||||
'name'=> e($accessory->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'),
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CustomField;
|
||||
@@ -17,7 +16,6 @@ use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ActionlogsTransformer
|
||||
{
|
||||
@@ -50,20 +48,17 @@ class ActionlogsTransformer
|
||||
|
||||
public function transformActionlog (Actionlog $actionlog, $settings = null)
|
||||
{
|
||||
|
||||
$icon = $actionlog->present()->icon();
|
||||
|
||||
if (($actionlog->filename!='') && ($actionlog->action_type!='upload deleted')) {
|
||||
$icon = Helper::filetype_icon($actionlog->filename);
|
||||
}
|
||||
|
||||
static $custom_fields = false;
|
||||
|
||||
if ($custom_fields === false) {
|
||||
$custom_fields = CustomField::all();
|
||||
}
|
||||
|
||||
|
||||
if ($actionlog->filename!='') {
|
||||
$icon = Helper::filetype_icon($actionlog->filename);
|
||||
}
|
||||
|
||||
// This is necessary since we can't escape special characters within a JSON object
|
||||
if (($actionlog->log_meta) && ($actionlog->log_meta!='')) {
|
||||
@@ -138,6 +133,24 @@ class ActionlogsTransformer
|
||||
$clean_meta= $this->changedInfo($clean_meta);
|
||||
}
|
||||
|
||||
$file_url = '';
|
||||
if($actionlog->filename!='') {
|
||||
if ($actionlog->action_type == 'accepted') {
|
||||
$file_url = route('log.storedeula.download', ['filename' => $actionlog->filename]);
|
||||
} else {
|
||||
if ($actionlog->item) {
|
||||
if ($actionlog->itemType() == 'asset') {
|
||||
$file_url = route('show/assetfile', ['asset' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'accessory') {
|
||||
$file_url = route('show.accessoryfile', ['accessoryId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'license') {
|
||||
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'user') {
|
||||
$file_url = route('show/userfile', ['user' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$array = [
|
||||
'id' => (int) $actionlog->id,
|
||||
@@ -145,15 +158,13 @@ class ActionlogsTransformer
|
||||
'file' => ($actionlog->filename!='')
|
||||
?
|
||||
[
|
||||
'url' => $actionlog->uploads_file_url(),
|
||||
'url' => $file_url,
|
||||
'filename' => $actionlog->filename,
|
||||
'inlineable' => StorageHelper::allowSafeInline($actionlog->uploads_file_url()),
|
||||
'exists_on_disk' => Storage::exists($actionlog->uploads_file_path()) ? true : false,
|
||||
] : null,
|
||||
|
||||
'item' => ($actionlog->item) ? [
|
||||
'id' => (int) $actionlog->item->id,
|
||||
'name' => e($actionlog->item->display_name) ?? null,
|
||||
'name' => ($actionlog->itemType()=='user') ? e($actionlog->item->getFullNameAttribute()) : e($actionlog->item->getDisplayNameAttribute()),
|
||||
'type' => e($actionlog->itemType()),
|
||||
'serial' =>e($actionlog->item->serial) ? e($actionlog->item->serial) : null
|
||||
] : null,
|
||||
@@ -168,19 +179,19 @@ class ActionlogsTransformer
|
||||
'action_type' => $actionlog->present()->actionType(),
|
||||
'admin' => ($actionlog->adminuser) ? [
|
||||
'id' => (int) $actionlog->adminuser->id,
|
||||
'name' => e($actionlog->adminuser->display_name),
|
||||
'name' => e($actionlog->adminuser->getFullNameAttribute()),
|
||||
'first_name'=> e($actionlog->adminuser->first_name),
|
||||
'last_name'=> e($actionlog->adminuser->last_name)
|
||||
] : null,
|
||||
'created_by' => ($actionlog->adminuser) ? [
|
||||
'id' => (int) $actionlog->adminuser->id,
|
||||
'name' => e($actionlog->adminuser->display_name),
|
||||
'name' => e($actionlog->adminuser->getFullNameAttribute()),
|
||||
'first_name'=> e($actionlog->adminuser->first_name),
|
||||
'last_name'=> e($actionlog->adminuser->last_name)
|
||||
] : null,
|
||||
'target' => ($actionlog->target) ? [
|
||||
'id' => (int) $actionlog->target->id,
|
||||
'name' => ($actionlog->target->display_name) ?? null,
|
||||
'name' => ($actionlog->targetType()=='user') ? e($actionlog->target->getFullNameAttribute()) : e($actionlog->target->getDisplayNameAttribute()),
|
||||
'type' => e($actionlog->targetType()),
|
||||
] : null,
|
||||
|
||||
|
||||
@@ -4,24 +4,23 @@ namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Maintenance;
|
||||
use App\Models\AssetMaintenance;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class MaintenancesTransformer
|
||||
class AssetMaintenancesTransformer
|
||||
{
|
||||
public function transformMaintenances(Collection $maintenances, $total)
|
||||
public function transformAssetMaintenances(Collection $assetmaintenances, $total)
|
||||
{
|
||||
$array = [];
|
||||
foreach ($maintenances as $assetmaintenance) {
|
||||
$array[] = self::transformMaintenance($assetmaintenance);
|
||||
foreach ($assetmaintenances as $assetmaintenance) {
|
||||
$array[] = self::transformAssetMaintenance($assetmaintenance);
|
||||
}
|
||||
|
||||
return (new DatatablesTransformer)->transformDatatables($array, $total);
|
||||
}
|
||||
|
||||
public function transformMaintenance(Maintenance $assetmaintenance)
|
||||
public function transformAssetMaintenance(AssetMaintenance $assetmaintenance)
|
||||
{
|
||||
$array = [
|
||||
'id' => (int) $assetmaintenance->id,
|
||||
@@ -34,7 +33,6 @@ class MaintenancesTransformer
|
||||
'created_at' => Helper::getFormattedDateObject($assetmaintenance->asset->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($assetmaintenance->asset->updated_at, 'datetime'),
|
||||
] : null,
|
||||
'image' => ($assetmaintenance->image != '') ? Storage::disk('public')->url('maintenances/'.e($assetmaintenance->image)) : null,
|
||||
'model' => (($assetmaintenance->asset) && ($assetmaintenance->asset->model)) ? [
|
||||
'id' => (int) $assetmaintenance->asset->model->id,
|
||||
'name'=> ($assetmaintenance->asset->model->name) ? e($assetmaintenance->asset->model->name).' '.e($assetmaintenance->asset->model->model_number) : null,
|
||||
@@ -50,8 +48,7 @@ class MaintenancesTransformer
|
||||
'name'=> ($assetmaintenance->asset->company->name) ? e($assetmaintenance->asset->company->name) : null,
|
||||
|
||||
] : null,
|
||||
'name' => ($assetmaintenance->name) ? e($assetmaintenance->name) : null,
|
||||
'title' => ($assetmaintenance->name) ? e($assetmaintenance->name) : null, // legacy to not change the shape of the API
|
||||
'title' => ($assetmaintenance->title) ? e($assetmaintenance->title) : null,
|
||||
'location' => (($assetmaintenance->asset) && ($assetmaintenance->asset->location)) ? [
|
||||
'id' => (int) $assetmaintenance->asset->location->id,
|
||||
'name'=> e($assetmaintenance->asset->location->name),
|
||||
@@ -73,11 +70,11 @@ class MaintenancesTransformer
|
||||
'completion_date' => Helper::getFormattedDateObject($assetmaintenance->completion_date, 'date'),
|
||||
'user_id' => ($assetmaintenance->adminuser) ? [
|
||||
'id' => $assetmaintenance->adminuser->id,
|
||||
'name'=> e($assetmaintenance->adminuser->display_name)
|
||||
'name'=> e($assetmaintenance->adminuser->present()->fullName())
|
||||
] : null, // legacy to not change the shape of the API
|
||||
'created_by' => ($assetmaintenance->adminuser) ? [
|
||||
'id' => (int) $assetmaintenance->adminuser->id,
|
||||
'name'=> e($assetmaintenance->adminuser->display_name),
|
||||
'name'=> e($assetmaintenance->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($assetmaintenance->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($assetmaintenance->updated_at, 'datetime'),
|
||||
@@ -65,11 +65,10 @@ class AssetModelsTransformer
|
||||
'default_fieldset_values' => $default_field_values,
|
||||
'eol' => ($assetmodel->eol > 0) ? $assetmodel->eol.' months' : 'None',
|
||||
'requestable' => ($assetmodel->requestable == '1') ? true : false,
|
||||
'require_serial' => $assetmodel->require_serial,
|
||||
'notes' => Helper::parseEscapedMarkedownInline($assetmodel->notes),
|
||||
'created_by' => ($assetmodel->adminuser) ? [
|
||||
'id' => (int) $assetmodel->adminuser->id,
|
||||
'name'=> e($assetmodel->adminuser->display_name),
|
||||
'name'=> e($assetmodel->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($assetmodel->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($assetmodel->updated_at, 'datetime'),
|
||||
|
||||
@@ -40,7 +40,6 @@ class AssetsTransformer
|
||||
] : null,
|
||||
'byod' => ($asset->byod ? true : false),
|
||||
'requestable' => ($asset->requestable ? true : false),
|
||||
|
||||
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
|
||||
'eol' => (($asset->asset_eol_date != '') && ($asset->purchase_date != '')) ? (int) Carbon::parse($asset->asset_eol_date)->diffInMonths($asset->purchase_date, true) . ' months' : null,
|
||||
'asset_eol_date' => ($asset->asset_eol_date != '') ? Helper::getFormattedDateObject($asset->asset_eol_date, 'date') : null,
|
||||
@@ -58,13 +57,6 @@ class AssetsTransformer
|
||||
'id' => (int) $asset->model->manufacturer->id,
|
||||
'name'=> e($asset->model->manufacturer->name),
|
||||
] : null,
|
||||
'depreciation' => (($asset->model) && ($asset->model->depreciation)) ? [
|
||||
'id' => (int) $asset->model->depreciation->id,
|
||||
'name'=> e($asset->model->depreciation->name),
|
||||
'months'=> (int) $asset->model->depreciation->months,
|
||||
'type'=> e($asset->model->depreciation->depreciation_type),
|
||||
'minimum'=> ($asset->model->depreciation->depreciation_min) ? (int) $asset->model->depreciation->depreciation_min : null,
|
||||
] : null,
|
||||
'supplier' => ($asset->supplier) ? [
|
||||
'id' => (int) $asset->supplier->id,
|
||||
'name'=> e($asset->supplier->name),
|
||||
@@ -87,11 +79,12 @@ class AssetsTransformer
|
||||
'qr' => ($setting->qr_code=='1') ? config('app.url').'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png' : null,
|
||||
'alt_barcode' => ($setting->alt_barcode_enabled=='1') ? config('app.url').'/uploads/barcodes/'.str_slug($setting->alt_barcode).'-'.str_slug($asset->asset_tag).'.png' : null,
|
||||
'assigned_to' => $this->transformAssignedTo($asset),
|
||||
'jobtitle' => $asset->assigned ? e($asset->assigned->jobtitle) : null,
|
||||
'warranty_months' => ($asset->warranty_months > 0) ? e($asset->warranty_months.' '.trans('admin/hardware/form.months')) : null,
|
||||
'warranty_expires' => ($asset->warranty_months > 0) ? Helper::getFormattedDateObject($asset->warranty_expires, 'date') : null,
|
||||
'created_by' => ($asset->adminuser) ? [
|
||||
'id' => (int) $asset->adminuser->id,
|
||||
'name'=> e($asset->adminuser->display_name),
|
||||
'name'=> e($asset->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($asset->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($asset->updated_at, 'datetime'),
|
||||
@@ -210,7 +203,6 @@ class AssetsTransformer
|
||||
'last_name'=> ($asset->assigned->last_name) ? e($asset->assigned->last_name) : null,
|
||||
'email'=> ($asset->assigned->email) ? e($asset->assigned->email) : null,
|
||||
'employee_number' => ($asset->assigned->employee_num) ? e($asset->assigned->employee_num) : null,
|
||||
'jobtitle' => $asset->assigned->jobtitle ? e($asset->assigned->jobtitle) : null,
|
||||
'type' => 'user',
|
||||
] : null;
|
||||
}
|
||||
@@ -287,7 +279,7 @@ class AssetsTransformer
|
||||
'id' => (int) $asset->id,
|
||||
'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null,
|
||||
'type' => 'asset',
|
||||
'name' => e($asset->display_name),
|
||||
'name' => e($asset->present()->fullName()),
|
||||
'model' => ($asset->model) ? e($asset->model->name) : null,
|
||||
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
|
||||
'asset_tag' => e($asset->asset_tag),
|
||||
|
||||
@@ -64,7 +64,7 @@ class CategoriesTransformer
|
||||
'licenses_count' => (int) $category->licenses_count,
|
||||
'created_by' => ($category->adminuser) ? [
|
||||
'id' => (int) $category->adminuser->id,
|
||||
'name'=> e($category->adminuser->display_name),
|
||||
'name'=> e($category->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'notes' => Helper::parseEscapedMarkedownInline($category->notes),
|
||||
'created_at' => Helper::getFormattedDateObject($category->created_at, 'datetime'),
|
||||
|
||||
@@ -38,7 +38,7 @@ class CompaniesTransformer
|
||||
'users_count' => (int) $company->users_count,
|
||||
'created_by' => ($company->adminuser) ? [
|
||||
'id' => (int) $company->adminuser->id,
|
||||
'name'=> e($company->adminuser->display_name),
|
||||
'name'=> e($company->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'notes' => Helper::parseEscapedMarkedownInline($company->notes),
|
||||
'created_at' => Helper::getFormattedDateObject($company->created_at, 'datetime'),
|
||||
|
||||
@@ -51,7 +51,7 @@ class ComponentsTransformer
|
||||
'notes' => ($component->notes) ? Helper::parseEscapedMarkedownInline($component->notes) : null,
|
||||
'created_by' => ($component->adminuser) ? [
|
||||
'id' => (int) $component->adminuser->id,
|
||||
'name'=> e($component->adminuser->display_name),
|
||||
'name'=> e($component->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($component->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($component->updated_at, 'datetime'),
|
||||
@@ -76,7 +76,7 @@ class ComponentsTransformer
|
||||
$array[] = [
|
||||
'assigned_pivot_id' => $asset->pivot->id,
|
||||
'id' => (int) $asset->id,
|
||||
'name' => e($asset->model->display_name).' '.e($asset->display_name),
|
||||
'name' => e($asset->model->present()->name).' '.e($asset->present()->name),
|
||||
'qty' => $asset->pivot->assigned_qty,
|
||||
'note' => $asset->pivot->note,
|
||||
'type' => 'asset',
|
||||
|
||||
@@ -25,7 +25,7 @@ class ConsumablesTransformer
|
||||
$array = [
|
||||
'id' => (int) $consumable->id,
|
||||
'name' => e($consumable->name),
|
||||
'image' => ($consumable->getImageUrl()) ? ($consumable->getImageUrl()) : null,
|
||||
'image' => ($consumable->image) ? Storage::disk('public')->url('consumables/'.e($consumable->image)) : null,
|
||||
'category' => ($consumable->category) ? ['id' => $consumable->category->id, 'name' => e($consumable->category->name)] : null,
|
||||
'company' => ($consumable->company) ? ['id' => (int) $consumable->company->id, 'name' => e($consumable->company->name)] : null,
|
||||
'item_no' => e($consumable->item_no),
|
||||
@@ -42,7 +42,7 @@ class ConsumablesTransformer
|
||||
'notes' => ($consumable->notes) ? Helper::parseEscapedMarkedownInline($consumable->notes) : null,
|
||||
'created_by' => ($consumable->adminuser) ? [
|
||||
'id' => (int) $consumable->adminuser->id,
|
||||
'name'=> e($consumable->adminuser->display_name),
|
||||
'name'=> e($consumable->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($consumable->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($consumable->updated_at, 'datetime'),
|
||||
|
||||
@@ -35,7 +35,7 @@ class DepartmentsTransformer
|
||||
] : null,
|
||||
'manager' => ($department->manager) ? [
|
||||
'id' => (int) $department->manager->id,
|
||||
'name' => e($department->manager->display_name),
|
||||
'name' => e($department->manager->getFullNameAttribute()),
|
||||
'first_name'=> e($department->manager->first_name),
|
||||
'last_name'=> e($department->manager->last_name),
|
||||
] : null,
|
||||
|
||||
@@ -33,7 +33,7 @@ class DepreciationsTransformer
|
||||
'licenses_count' => ($depreciation->licenses_count > 0) ? (int) $depreciation->licenses_count : 0,
|
||||
'created_by' => ($depreciation->adminuser) ? [
|
||||
'id' => (int) $depreciation->adminuser->id,
|
||||
'name'=> e($depreciation->adminuser->display_name),
|
||||
'name'=> e($depreciation->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($depreciation->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($depreciation->updated_at, 'datetime')
|
||||
|
||||
@@ -29,7 +29,7 @@ class GroupsTransformer
|
||||
'notes' => Helper::parseEscapedMarkedownInline($group->notes),
|
||||
'created_by' => ($group->adminuser) ? [
|
||||
'id' => (int) $group->adminuser->id,
|
||||
'name'=> e($group->adminuser->display_name),
|
||||
'name'=> e($group->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($group->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($group->updated_at, 'datetime'),
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class LicenseSeatsTransformer
|
||||
{
|
||||
public function transformLicenseSeats(Collection $seats, $total)
|
||||
@@ -51,7 +52,6 @@ class LicenseSeatsTransformer
|
||||
'reassignable' => (bool) $seat->license->reassignable,
|
||||
'notes' => e($seat->notes),
|
||||
'user_can_checkout' => (($seat->assigned_to == '') && ($seat->asset_id == '')),
|
||||
'disabled' => $seat->unreassignable_seat,
|
||||
];
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
|
||||
@@ -37,7 +37,7 @@ class LicensesTransformer
|
||||
'notes' => Helper::parseEscapedMarkedownInline($license->notes),
|
||||
'expiration_date' => Helper::getFormattedDateObject($license->expiration_date, 'date'),
|
||||
'seats' => (int) $license->seats,
|
||||
'free_seats_count' => (int) $license->free_seats_count - License::unReassignableCount($license),
|
||||
'free_seats_count' => (int) $license->free_seats_count,
|
||||
'remaining' => (int) $license->free_seats_count,
|
||||
'min_amt' => ($license->min_amt) ? (int) ($license->min_amt) : null,
|
||||
'license_name' => ($license->license_name) ? e($license->license_name) : null,
|
||||
@@ -48,7 +48,7 @@ class LicensesTransformer
|
||||
'category' => ($license->category) ? ['id' => (int) $license->category->id, 'name'=> e($license->category->name)] : null,
|
||||
'created_by' => ($license->adminuser) ? [
|
||||
'id' => (int) $license->adminuser->id,
|
||||
'name'=> e($license->adminuser->display_name),
|
||||
'name'=> e($license->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($license->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($license->updated_at, 'datetime'),
|
||||
@@ -62,7 +62,7 @@ class LicensesTransformer
|
||||
'checkin' => Gate::allows('checkin', License::class),
|
||||
'clone' => Gate::allows('create', License::class),
|
||||
'update' => Gate::allows('update', License::class),
|
||||
'delete' => (Gate::allows('delete', License::class) && ($license->free_seats_count == $license->seats)) ? true : false,
|
||||
'delete' => (Gate::allows('delete', License::class) && ($license->free_seats_count > 0)) ? true : false,
|
||||
];
|
||||
|
||||
$array += $permissions_array;
|
||||
|
||||
@@ -40,7 +40,7 @@ class ManufacturersTransformer
|
||||
'notes' => Helper::parseEscapedMarkedownInline($manufacturer->notes),
|
||||
'created_by' => ($manufacturer->adminuser) ? [
|
||||
'id' => (int) $manufacturer->adminuser->id,
|
||||
'name'=> e($manufacturer->adminuser->display_name),
|
||||
'name'=> e($manufacturer->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($manufacturer->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($manufacturer->updated_at, 'datetime'),
|
||||
|
||||
@@ -34,7 +34,7 @@ class PredefinedKitsTransformer
|
||||
'name' => e($kit->name),
|
||||
'created_by' => ($kit->adminuser) ? [
|
||||
'id' => (int) $kit->adminuser->id,
|
||||
'name'=> e($kit->adminuser->display_name),
|
||||
'name'=> e($kit->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($kit->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($kit->updated_at, 'datetime'),
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
class ProfileTransformer
|
||||
@@ -25,7 +26,7 @@ class ProfileTransformer
|
||||
'id' => (int) $file->id,
|
||||
'icon' => Helper::filetype_icon($file->filename),
|
||||
'item' => ($file->item) ? [
|
||||
'name' => $file->item->display_name ? e($file->item->display_name) : null,
|
||||
'name' => ($file->itemType()=='user') ? e($file->item->getFullNameAttribute()) : e($file->item->getDisplayNameAttribute()),
|
||||
'type' => e($file->itemType()),
|
||||
] : null,
|
||||
'filename' => e($file->filename),
|
||||
|
||||
@@ -32,7 +32,7 @@ class StatuslabelsTransformer
|
||||
'notes' => e($statuslabel->notes),
|
||||
'created_by' => ($statuslabel->adminuser) ? [
|
||||
'id' => (int) $statuslabel->adminuser->id,
|
||||
'name'=> e($statuslabel->adminuser->display_name),
|
||||
'name'=> e($statuslabel->adminuser->present()->fullName()),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($statuslabel->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($statuslabel->updated_at, 'datetime'),
|
||||
|
||||
@@ -32,11 +32,10 @@ class UploadedFilesTransformer
|
||||
'name' => e($file->filename),
|
||||
'item' => ($file->item_type) ? [
|
||||
'id' => (int) $file->item_id,
|
||||
'type' => str_plural(strtolower(class_basename($file->item_type))),
|
||||
'type' => strtolower(class_basename($file->item_type)),
|
||||
] : null,
|
||||
'filename' => e($file->filename),
|
||||
'filetype' => StorageHelper::getFiletype($file->uploads_file_path()),
|
||||
'mediatype' => StorageHelper::getMediaType($file->uploads_file_path()),
|
||||
'url' => $file->uploads_file_url(),
|
||||
'note' => ($file->note) ? e($file->note) : null,
|
||||
'created_by' => ($file->adminuser) ? [
|
||||
@@ -45,7 +44,7 @@ class UploadedFilesTransformer
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($file->created_at, 'datetime'),
|
||||
'deleted_at' => Helper::getFormattedDateObject($file->deleted_at, 'datetime'),
|
||||
'inlineable' => StorageHelper::allowSafeInline($file->uploads_file_path()) ?? false,
|
||||
'inline' => StorageHelper::allowSafeInline($file->uploads_file_path()),
|
||||
'exists_on_disk' => (Storage::exists($file->uploads_file_path()) ? true : false),
|
||||
];
|
||||
|
||||
|
||||
@@ -22,31 +22,23 @@ class UsersTransformer
|
||||
public function transformUser(User $user)
|
||||
{
|
||||
|
||||
$role = null;
|
||||
if ($user->isSuperUser()) {
|
||||
$role = 'superadmin';
|
||||
} elseif ($user->isAdmin()) {
|
||||
$role = 'admin';
|
||||
}
|
||||
$array = [
|
||||
'id' => (int) $user->id,
|
||||
'avatar' => e($user->present()->gravatar) ?? null,
|
||||
'name' => e($user->getFullNameAttribute()) ?? null,
|
||||
'first_name' => e($user->first_name) ?? null,
|
||||
'last_name' => e($user->last_name) ?? null,
|
||||
'display_name' => ($user->getRawOriginal('display_name')) ? e($user->getRawOriginal('display_name')) : null,
|
||||
'username' => e($user->username) ?? null,
|
||||
'name' => e($user->getFullNameAttribute()),
|
||||
'first_name' => e($user->first_name),
|
||||
'last_name' => e($user->last_name),
|
||||
'username' => e($user->username),
|
||||
'remote' => ($user->remote == '1') ? true : false,
|
||||
'locale' => ($user->locale) ? e($user->locale) : null,
|
||||
'employee_num' => ($user->employee_num) ? e($user->employee_num) : null,
|
||||
'manager' => ($user->manager) ? [
|
||||
'id' => (int) $user->manager->id,
|
||||
'name'=> e($user->manager->display_name),
|
||||
'name'=> e($user->manager->first_name).' '.e($user->manager->last_name),
|
||||
] : null,
|
||||
'jobtitle' => ($user->jobtitle) ? e($user->jobtitle) : null,
|
||||
'vip' => ($user->vip == '1') ? true : false,
|
||||
'phone' => ($user->phone) ? e($user->phone) : null,
|
||||
'mobile' => ($user->mobile) ? e($user->mobile) : null,
|
||||
'website' => ($user->website) ? e($user->website) : null,
|
||||
'address' => ($user->address) ? e($user->address) : null,
|
||||
'city' => ($user->city) ? e($user->city) : null,
|
||||
@@ -60,14 +52,13 @@ class UsersTransformer
|
||||
] : null,
|
||||
'department_manager' => ($user->department?->manager) ? [
|
||||
'id' => (int) $user->department->manager->id,
|
||||
'name'=> e($user->department->manager->display_name),
|
||||
'name'=> e($user->department->manager->full_name),
|
||||
] : null,
|
||||
'location' => ($user->userloc) ? [
|
||||
'id' => (int) $user->userloc->id,
|
||||
'name'=> e($user->userloc->name),
|
||||
] : null,
|
||||
'notes'=> Helper::parseEscapedMarkedownInline($user->notes),
|
||||
'role' => $role,
|
||||
'permissions' => $user->decodePermissions(),
|
||||
'activated' => ($user->activated == '1') ? true : false,
|
||||
'autoassign_licenses' => ($user->autoassign_licenses == '1') ? true : false,
|
||||
@@ -83,7 +74,7 @@ class UsersTransformer
|
||||
'company' => ($user->company) ? ['id' => (int) $user->company->id, 'name'=> e($user->company->name)] : null,
|
||||
'created_by' => ($user->createdBy) ? [
|
||||
'id' => (int) $user->createdBy->id,
|
||||
'name'=> e($user->createdBy->display_name),
|
||||
'name'=> e($user->createdBy->present()->fullName),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($user->updated_at, 'datetime'),
|
||||
@@ -130,23 +121,24 @@ class UsersTransformer
|
||||
*/
|
||||
public function transformUserCompact(User $user) : array
|
||||
{
|
||||
|
||||
$array = [
|
||||
'id' => (int) $user->id,
|
||||
'image' => e($user->present()->gravatar) ?? null,
|
||||
'type' => 'user',
|
||||
'name' => e($user->getFullNameAttribute()),
|
||||
'first_name' => e($user->first_name),
|
||||
'last_name' => e($user->last_name),
|
||||
'username' => e($user->username),
|
||||
'display_name' => e($user->display_name),
|
||||
'created_by' => $user->adminuser ? [
|
||||
'id' => (int) $user->adminuser->id,
|
||||
'name'=> e($user->adminuser->present()->fullName),
|
||||
]: null,
|
||||
'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'),
|
||||
'deleted_at' => ($user->deleted_at) ? Helper::getFormattedDateObject($user->deleted_at, 'datetime') : null,
|
||||
];
|
||||
$array = [];
|
||||
if (Gate::allows('view', $user) && ($user->deleted_at == '')) {
|
||||
$array = [
|
||||
'id' => (int) $user->id,
|
||||
'image' => e($user->present()->gravatar) ?? null,
|
||||
'type' => 'user',
|
||||
'name' => e($user->getFullNameAttribute()),
|
||||
'first_name' => e($user->first_name),
|
||||
'last_name' => e($user->last_name),
|
||||
'username' => e($user->username),
|
||||
'created_by' => $user->adminuser ? [
|
||||
'id' => (int) $user->adminuser->id,
|
||||
'name'=> e($user->adminuser->present()->fullName),
|
||||
]: null,
|
||||
'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'),
|
||||
'deleted_at' => ($user->deleted_at) ? Helper::getFormattedDateObject($user->deleted_at, 'datetime') : null,
|
||||
];
|
||||
}
|
||||
|
||||
return $array;
|
||||
}
|
||||
|
||||
@@ -40,32 +40,11 @@ class AssetModelImporter extends ItemImporter
|
||||
{
|
||||
|
||||
$editingAssetModel = false;
|
||||
|
||||
/**
|
||||
* This part gets a little confusing, since folks might be importing multiple models with the same name and different model numbers for the first time
|
||||
* or they might be wanting to update existing models with new model numbers.
|
||||
*/
|
||||
|
||||
// They are not trying to update existing models, so we'll check for duplicates with model name *and* number
|
||||
if (! $this->updating) {
|
||||
$this->log('Finding model by name and model number: '.$this->findCsvMatch($row, 'name').' / '.$this->findCsvMatch($row, 'model_number'));
|
||||
$assetModel = AssetModel::where('name', '=', $this->findCsvMatch($row, 'name'))->where('model_number', '=', $this->findCsvMatch($row, 'model_number'))->first();
|
||||
} else {
|
||||
|
||||
if ($this->findCsvMatch($row, 'id')!='') {
|
||||
// Override model if an ID was given
|
||||
$this->log('Finding model by ID: '.$this->findCsvMatch($row, 'id'));
|
||||
$assetModel = AssetModel::find($this->findCsvMatch($row, 'id'));
|
||||
} else {
|
||||
$this->log('Finding model by name: '.$this->findCsvMatch($row, 'name'));
|
||||
$assetModel = AssetModel::where('name', '=', $this->findCsvMatch($row, 'name'))->first();
|
||||
}
|
||||
}
|
||||
|
||||
$assetModel = AssetModel::where('name', '=', $this->findCsvMatch($row, 'name'))->first();
|
||||
|
||||
if ($assetModel) {
|
||||
if (! $this->updating) {
|
||||
$this->log('A matching Model '.$this->item['name'].' already exists and we are not updating. Skipping.');
|
||||
$this->log('A matching Model '.$this->item['name'].' already exists');
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -87,7 +66,6 @@ class AssetModelImporter extends ItemImporter
|
||||
$this->item['fieldset'] = trim($this->findCsvMatch($row, 'fieldset'));
|
||||
$this->item['depreciation'] = trim($this->findCsvMatch($row, 'depreciation'));
|
||||
$this->item['requestable'] = trim(($this->fetchHumanBoolean($this->findCsvMatch($row, 'requestable'))) == 1) ? 1 : 0;
|
||||
$this->item['require_serial'] = trim(($this->fetchHumanBoolean($this->findCsvMatch($row, 'require_serial'))) == 1) ? 1 : 0;
|
||||
|
||||
if (!empty($this->item['category'])) {
|
||||
if ($category = $this->createOrFetchCategory($this->item['category'])) {
|
||||
|
||||
@@ -72,7 +72,6 @@ abstract class Importer
|
||||
'termination_date' => 'termination date',
|
||||
'warranty_months' => 'warranty',
|
||||
'full_name' => 'full name',
|
||||
'display_name' => 'display name',
|
||||
'email' => 'email',
|
||||
'username' => 'username',
|
||||
'address' => 'address',
|
||||
@@ -134,7 +133,7 @@ abstract class Importer
|
||||
} else {
|
||||
$this->csv = Reader::createFromString($file);
|
||||
}
|
||||
$this->tempPassword = '*** NO PASSWORD - IMPORTED VIA CSV ***';
|
||||
$this->tempPassword = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 40);
|
||||
}
|
||||
|
||||
// Cached Values for import lookups
|
||||
@@ -300,7 +299,6 @@ abstract class Importer
|
||||
'full_name' => $this->findCsvMatch($row, 'full_name'),
|
||||
'first_name' => $this->findCsvMatch($row, 'first_name'),
|
||||
'last_name' => $this->findCsvMatch($row, 'last_name'),
|
||||
'display_name' => $this->findCsvMatch($row, 'display_name'),
|
||||
'email' => $this->findCsvMatch($row, 'email'),
|
||||
'manager_id'=> '',
|
||||
'department_id' => '',
|
||||
@@ -371,7 +369,6 @@ abstract class Importer
|
||||
$user->first_name = $user_array['first_name'];
|
||||
$user->last_name = $user_array['last_name'];
|
||||
$user->username = $user_array['username'];
|
||||
$user->display_name = $user_array['display_name'] ?? null;
|
||||
$user->email = $user_array['email'];
|
||||
$user->manager_id = $user_array['manager_id'] ?? null;
|
||||
$user->department_id = $user_array['department_id'] ?? null;
|
||||
|
||||
@@ -27,7 +27,7 @@ class ManufacturerImporter extends ItemImporter
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a manufacturer if a duplicate does not exist.
|
||||
* Create a supplier if a duplicate does not exist.
|
||||
* @todo Investigate how this should interact with Importer::createManufacturerIfNotExists
|
||||
*
|
||||
* @author A. Gianotto
|
||||
@@ -39,16 +39,16 @@ class ManufacturerImporter extends ItemImporter
|
||||
|
||||
$editingManufacturer = false;
|
||||
|
||||
$manufacturer = Manufacturer::where('name', '=', $this->findCsvMatch($row, 'name'))->first();
|
||||
$supplier = Manufacturer::where('name', '=', $this->findCsvMatch($row, 'name'))->first();
|
||||
|
||||
if ($this->findCsvMatch($row, 'id')!='') {
|
||||
// Override manufacturer if an ID was given
|
||||
\Log::debug('Finding manufacturer by ID: '.$this->findCsvMatch($row, 'id'));
|
||||
$manufacturer = Manufacturer::find($this->findCsvMatch($row, 'id'));
|
||||
// Override supplier if an ID was given
|
||||
\Log::debug('Finding supplier by ID: '.$this->findCsvMatch($row, 'id'));
|
||||
$supplier = Manufacturer::find($this->findCsvMatch($row, 'id'));
|
||||
}
|
||||
|
||||
|
||||
if ($manufacturer) {
|
||||
if ($supplier) {
|
||||
if (! $this->updating) {
|
||||
$this->log('A matching Manufacturer '.$this->item['name'].' already exists');
|
||||
return;
|
||||
@@ -58,8 +58,8 @@ class ManufacturerImporter extends ItemImporter
|
||||
$editingManufacturer = true;
|
||||
} else {
|
||||
$this->log('No Matching Manufacturer, Create a new one');
|
||||
$manufacturer = new Manufacturer;
|
||||
$manufacturer->created_by = auth()->id();
|
||||
$supplier = new Manufacturer;
|
||||
$supplier->created_by = auth()->id();
|
||||
}
|
||||
|
||||
// Pull the records from the CSV to determine their values
|
||||
@@ -79,21 +79,21 @@ class ManufacturerImporter extends ItemImporter
|
||||
|
||||
|
||||
if ($editingManufacturer) {
|
||||
Log::debug('Updating existing manufacturer');
|
||||
$manufacturer->update($this->sanitizeItemForUpdating($manufacturer));
|
||||
Log::debug('Updating existing supplier');
|
||||
$supplier->update($this->sanitizeItemForUpdating($supplier));
|
||||
} else {
|
||||
Log::debug('Creating manufacturer');
|
||||
$manufacturer->fill($this->sanitizeItemForStoring($manufacturer));
|
||||
Log::debug('Creating supplier');
|
||||
$supplier->fill($this->sanitizeItemForStoring($supplier));
|
||||
}
|
||||
|
||||
if ($manufacturer->save()) {
|
||||
$this->log('Manufacturer '.$manufacturer->name.' created or updated from CSV import');
|
||||
return $manufacturer;
|
||||
if ($supplier->save()) {
|
||||
$this->log('Manufacturer '.$supplier->name.' created or updated from CSV import');
|
||||
return $supplier;
|
||||
|
||||
} else {
|
||||
Log::debug($manufacturer->getErrors());
|
||||
$this->logError($manufacturer, 'Manufacturer "'.$this->item['name'].'"');
|
||||
return $manufacturer->errors;
|
||||
Log::debug($supplier->getErrors());
|
||||
$this->logError($supplier, 'Manufacturer "'.$this->item['name'].'"');
|
||||
return $supplier->errors;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -7,9 +7,7 @@ use App\Models\Department;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\WelcomeNotification;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
|
||||
/**
|
||||
* This is ONLY used for the User Import. When we are importing users
|
||||
@@ -47,13 +45,11 @@ class UserImporter extends ItemImporter
|
||||
// Pull the records from the CSV to determine their values
|
||||
$this->item['id'] = trim($this->findCsvMatch($row, 'id'));
|
||||
$this->item['username'] = trim($this->findCsvMatch($row, 'username'));
|
||||
$this->item['display_name'] = trim($this->findCsvMatch($row, 'display_name'));
|
||||
$this->item['first_name'] = trim($this->findCsvMatch($row, 'first_name'));
|
||||
$this->item['last_name'] = trim($this->findCsvMatch($row, 'last_name'));
|
||||
$this->item['email'] = trim($this->findCsvMatch($row, 'email'));
|
||||
$this->item['gravatar'] = trim($this->findCsvMatch($row, 'gravatar'));
|
||||
$this->item['phone'] = trim($this->findCsvMatch($row, 'phone_number'));
|
||||
$this->item['mobile'] = trim($this->findCsvMatch($row, 'mobile_number'));
|
||||
$this->item['website'] = trim($this->findCsvMatch($row, 'website'));
|
||||
$this->item['jobtitle'] = trim($this->findCsvMatch($row, 'jobtitle'));
|
||||
$this->item['address'] = trim($this->findCsvMatch($row, 'address'));
|
||||
@@ -84,7 +80,6 @@ class UserImporter extends ItemImporter
|
||||
$this->item['username'] = $user_formatted_array['username'];
|
||||
}
|
||||
|
||||
|
||||
// Check if a numeric ID was passed. If it does, use that above all else.
|
||||
if ((array_key_exists('id', $this->item) && ($this->item['id'] != "") && (is_numeric($this->item['id'])))) {
|
||||
$user = User::find($this->item['id']);
|
||||
@@ -94,25 +89,12 @@ class UserImporter extends ItemImporter
|
||||
|
||||
if ($user) {
|
||||
|
||||
// If the user does not want to update existing values, only add new ones, bail out
|
||||
if (! $this->updating) {
|
||||
Log::debug('A matching User '.$this->item['name'].' already exists. ');
|
||||
return;
|
||||
}
|
||||
|
||||
$this->log('Updating User');
|
||||
|
||||
// Todo - check that this works
|
||||
if (!Gate::allows('canEditAuthFields', $user)) {
|
||||
unset($user->username);
|
||||
unset($user->email);
|
||||
unset($user->password);
|
||||
unset($user->activated);
|
||||
}
|
||||
|
||||
$user->update($this->sanitizeItemForUpdating($user));
|
||||
|
||||
// Why do we have to do this twice? Update should
|
||||
$user->save();
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
@@ -128,32 +110,28 @@ class UserImporter extends ItemImporter
|
||||
|
||||
// This needs to be applied after the update logic, otherwise we'll overwrite user passwords
|
||||
// Issue #5408
|
||||
$this->item['password'] = $this->tempPassword;
|
||||
$this->item['password'] = bcrypt($this->tempPassword);
|
||||
|
||||
$this->log('No matching user, creating one');
|
||||
$user = new User();
|
||||
$user->created_by = auth()->id();
|
||||
|
||||
$user->fill($this->sanitizeItemForStoring($user));
|
||||
|
||||
// TODO - check for gate here I guess
|
||||
|
||||
|
||||
if ($user->save()) {
|
||||
$this->log('User '.$this->item['name'].' was created');
|
||||
|
||||
if (($user->email) && ($user->activated == '1')) {
|
||||
$data = [
|
||||
'email' => $user->email,
|
||||
'username' => $user->username,
|
||||
'first_name' => $user->first_name,
|
||||
'last_name' => $user->last_name,
|
||||
'password' => $this->tempPassword,
|
||||
];
|
||||
|
||||
if ($this->send_welcome) {
|
||||
|
||||
try {
|
||||
$user->notify(new WelcomeNotification($user));
|
||||
} catch (\Exception $e) {
|
||||
Log::warning('Could not send welcome notification for user: ' . $e->getMessage());
|
||||
}
|
||||
|
||||
$user->notify(new WelcomeNotification($data));
|
||||
}
|
||||
|
||||
}
|
||||
$user = null;
|
||||
$this->item = null;
|
||||
@@ -162,9 +140,9 @@ class UserImporter extends ItemImporter
|
||||
}
|
||||
|
||||
$this->logError($user, 'User');
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Fetch an existing department, or create new if it doesn't exist
|
||||
*
|
||||
|
||||
@@ -4,12 +4,10 @@ namespace App\Listeners;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Mail\CheckinAccessoryMail;
|
||||
use App\Mail\CheckinComponentMail;
|
||||
use App\Mail\CheckinLicenseMail;
|
||||
use App\Mail\CheckoutAccessoryMail;
|
||||
use App\Mail\CheckoutAssetMail;
|
||||
use App\Mail\CheckinAssetMail;
|
||||
use App\Mail\CheckoutComponentMail;
|
||||
use App\Mail\CheckoutConsumableMail;
|
||||
use App\Mail\CheckoutLicenseMail;
|
||||
use App\Models\Accessory;
|
||||
@@ -24,11 +22,9 @@ use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CheckinAccessoryNotification;
|
||||
use App\Notifications\CheckinAssetNotification;
|
||||
use App\Notifications\CheckinComponentNotification;
|
||||
use App\Notifications\CheckinLicenseSeatNotification;
|
||||
use App\Notifications\CheckoutAccessoryNotification;
|
||||
use App\Notifications\CheckoutAssetNotification;
|
||||
use App\Notifications\CheckoutComponentNotification;
|
||||
use App\Notifications\CheckoutConsumableNotification;
|
||||
use App\Notifications\CheckoutLicenseSeatNotification;
|
||||
use GuzzleHttp\Exception\ClientException;
|
||||
@@ -43,7 +39,7 @@ use Osama\LaravelTeamsNotification\TeamsNotification;
|
||||
class CheckoutableListener
|
||||
{
|
||||
private array $skipNotificationsFor = [
|
||||
// Component::class,
|
||||
Component::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -96,8 +92,7 @@ class CheckoutableListener
|
||||
|
||||
if (!empty($to)) {
|
||||
try {
|
||||
Mail::to(array_flatten($to))->send($mailable->locale($notifiable->locale));
|
||||
Mail::to(array_flatten($cc))->send($mailable->locale(Setting::getSettings()->locale));
|
||||
Mail::to(array_flatten($to))->cc(array_flatten($cc))->send($mailable);
|
||||
Log::info('Checkout Mail sent to checkout target');
|
||||
} catch (ClientException $e) {
|
||||
Log::debug("Exception caught during checkout email: " . $e->getMessage());
|
||||
@@ -150,6 +145,7 @@ class CheckoutableListener
|
||||
$shouldSendEmailToUser = $this->checkoutableCategoryShouldSendEmail($event->checkoutable);
|
||||
$shouldSendEmailToAlertAddress = $this->shouldSendEmailToAlertAddress();
|
||||
$shouldSendWebhookNotification = $this->shouldSendWebhookNotification();
|
||||
|
||||
if (!$shouldSendEmailToUser && !$shouldSendEmailToAlertAddress && !$shouldSendWebhookNotification) {
|
||||
return;
|
||||
}
|
||||
@@ -181,8 +177,7 @@ class CheckoutableListener
|
||||
|
||||
try {
|
||||
if (!empty($to)) {
|
||||
Mail::to(array_flatten($to))->send($mailable->locale($notifiable->locale));
|
||||
Mail::to(array_flatten($cc))->send($mailable->locale(Setting::getSettings()->locale));
|
||||
Mail::to(array_flatten($to))->cc(array_flatten($cc))->send($mailable);
|
||||
Log::info('Checkin Mail sent to CC addresses');
|
||||
}
|
||||
} catch (ClientException $e) {
|
||||
@@ -274,9 +269,6 @@ class CheckoutableListener
|
||||
case LicenseSeat::class:
|
||||
$notificationClass = CheckinLicenseSeatNotification::class;
|
||||
break;
|
||||
case Component::class:
|
||||
$notificationClass = CheckinComponentNotification::class;
|
||||
break;
|
||||
}
|
||||
|
||||
Log::debug('Notification class: '.$notificationClass);
|
||||
@@ -307,9 +299,6 @@ class CheckoutableListener
|
||||
case LicenseSeat::class:
|
||||
$notificationClass = CheckoutLicenseSeatNotification::class;
|
||||
break;
|
||||
case Component::class:
|
||||
$notificationClass = CheckoutComponentNotification::class;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -321,7 +310,6 @@ class CheckoutableListener
|
||||
Asset::class => CheckoutAssetMail::class,
|
||||
LicenseSeat::class => CheckoutLicenseMail::class,
|
||||
Consumable::class => CheckoutConsumableMail::class,
|
||||
Component::class => CheckoutComponentMail::class,
|
||||
];
|
||||
$mailable= $lookup[get_class($event->checkoutable)];
|
||||
|
||||
@@ -334,8 +322,8 @@ class CheckoutableListener
|
||||
Accessory::class => CheckinAccessoryMail::class,
|
||||
Asset::class => CheckinAssetMail::class,
|
||||
LicenseSeat::class => CheckinLicenseMail::class,
|
||||
Component::class => CheckinComponentMail::class,
|
||||
];
|
||||
|
||||
$mailable= $lookup[get_class($event->checkoutable)];
|
||||
|
||||
return new $mailable($event->checkoutable, $event->checkedOutTo, $event->checkedInBy, $event->note);
|
||||
@@ -481,8 +469,7 @@ class CheckoutableListener
|
||||
return match (true) {
|
||||
$checkoutable instanceof Asset => $checkoutable->model->category,
|
||||
$checkoutable instanceof Accessory,
|
||||
$checkoutable instanceof Consumable,
|
||||
$checkoutable instanceof Component => $checkoutable->category,
|
||||
$checkoutable instanceof Consumable => $checkoutable->category,
|
||||
$checkoutable instanceof LicenseSeat => $checkoutable->license->category,
|
||||
};
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user