Compare commits
109 Commits
#17642-che
...
exit-early
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
e4f06b0ca8 | ||
|
|
2f093c0e82 | ||
|
|
5d9dc0e74d | ||
|
|
adc3a34929 | ||
|
|
cb2ffe6b3f | ||
|
|
b3e3d01672 | ||
|
|
4a6520fc78 | ||
|
|
75ab6c9b13 | ||
|
|
2f77fcb526 | ||
|
|
60604c3481 | ||
|
|
671c113cd2 | ||
|
|
8a74d21ede | ||
|
|
75995b2109 | ||
|
|
d1eefc3fea | ||
|
|
16795382fc | ||
|
|
eb17974adc | ||
|
|
22852c27f8 | ||
|
|
f4a94d975d | ||
|
|
7a36bbbd1e | ||
|
|
2b401b965b | ||
|
|
314bc5b44f | ||
|
|
76374f0d5a | ||
|
|
264efb015e | ||
|
|
e74460aefc | ||
|
|
55a5a12b30 | ||
|
|
58944a38eb | ||
|
|
469e3bd475 | ||
|
|
17650c5735 | ||
|
|
15e64155b5 | ||
|
|
39955ac760 | ||
|
|
855a176ca9 | ||
|
|
47b2b30455 | ||
|
|
b702e3e2de | ||
|
|
a6b74d56c6 | ||
|
|
a4222bcaef | ||
|
|
ecf24511cd | ||
|
|
abb097a391 | ||
|
|
dd742a2e4a | ||
|
|
73ac00bc51 | ||
|
|
3524e23e38 | ||
|
|
be0f3910bb | ||
|
|
07dbc6842c | ||
|
|
5a16b59462 | ||
|
|
13cd7071b8 | ||
|
|
40108b196c | ||
|
|
c8e79aa5ca | ||
|
|
e60f2b2332 | ||
|
|
b6d397bcca | ||
|
|
6503f9c667 | ||
|
|
4770e469b4 | ||
|
|
29a18c7c8b | ||
|
|
6db0003e3f | ||
|
|
c538c460fa | ||
|
|
822339fe42 | ||
|
|
b84d9282ca | ||
|
|
952b6f33bb | ||
|
|
c57c4b8ff2 | ||
|
|
39e6223ff2 | ||
|
|
d8dd274c08 | ||
|
|
15f97b6cb9 | ||
|
|
fc091c1174 | ||
|
|
c07ef4d87f | ||
|
|
11eee833bb | ||
|
|
fec9d716ee | ||
|
|
da5b1afd19 | ||
|
|
618106c103 | ||
|
|
312be98132 | ||
|
|
e0bb77a6d6 | ||
|
|
855922c21a | ||
|
|
bc645d2621 | ||
|
|
9c06ff3899 | ||
|
|
2a37aa3b49 | ||
|
|
bf591320af | ||
|
|
56e687bed2 | ||
|
|
07b25fe376 | ||
|
|
c2ecd20b7d | ||
|
|
1b42abcc98 | ||
|
|
9efb49d510 | ||
|
|
2d6270c697 | ||
|
|
0823c23a6e | ||
|
|
b3f0ce4b2a | ||
|
|
8b83584b67 | ||
|
|
9eb686fe08 | ||
|
|
765051ce88 | ||
|
|
ed402e0122 | ||
|
|
1488271a83 | ||
|
|
48bbf8d005 | ||
|
|
e97b969d66 | ||
|
|
cdd12df81a | ||
|
|
050a3afc74 | ||
|
|
270401c693 | ||
|
|
551822ce7d | ||
|
|
4b8c371097 | ||
|
|
90fbf6da46 | ||
|
|
0c3103e3d2 | ||
|
|
6a8e1566fe | ||
|
|
ced30082a6 | ||
|
|
f6c64abc1a | ||
|
|
7f9939a896 | ||
|
|
1c99f2dfdd | ||
|
|
1974fccac3 | ||
|
|
911552035e | ||
|
|
ff25d275ee | ||
|
|
1fcf5e03e7 | ||
|
|
ba85af11aa | ||
|
|
c94a8c42f4 | ||
|
|
16fdb16a56 | ||
|
|
822f9a6f28 | ||
|
|
b264bbf69f |
@@ -4198,6 +4198,42 @@
|
||||
"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"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -193,11 +193,17 @@ 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@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
2
.github/workflows/codacy-analysis.yml
vendored
2
.github/workflows/codacy-analysis.yml
vendored
@@ -32,7 +32,7 @@ jobs:
|
||||
steps:
|
||||
# Checkout the repository to the GitHub Actions runner
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Run Codacy Analysis CLI
|
||||
|
||||
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@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
- 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@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# 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@v4
|
||||
uses: actions/checkout@v5
|
||||
|
||||
# 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@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Docker Hub Description
|
||||
uses: grokability/dockerhub-description@7ea9d275c7cdbe2b676a093a0308c50665e3b8b4
|
||||
|
||||
2
.github/workflows/tests-mysql.yml
vendored
2
.github/workflows/tests-mysql.yml
vendored
@@ -37,7 +37,7 @@ jobs:
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
coverage: none
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
|
||||
2
.github/workflows/tests-postgres.yml
vendored
2
.github/workflows/tests-postgres.yml
vendored
@@ -34,7 +34,7 @@ jobs:
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
coverage: none
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
|
||||
2
.github/workflows/tests-sqlite.yml
vendored
2
.github/workflows/tests-sqlite.yml
vendored
@@ -25,7 +25,7 @@ jobs:
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
coverage: none
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
- uses: actions/checkout@v5
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
|
||||
@@ -68,7 +68,7 @@ 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/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!
|
||||
|
||||
@@ -55,6 +55,8 @@ 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,
|
||||
@@ -63,11 +65,17 @@ 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;
|
||||
@@ -234,9 +242,11 @@ 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] ?? '';
|
||||
@@ -244,8 +254,13 @@ 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] ?? '';
|
||||
@@ -278,6 +293,9 @@ 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'];
|
||||
}
|
||||
@@ -293,6 +311,9 @@ 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,6 +6,7 @@ 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
|
||||
@@ -160,7 +161,15 @@ class LdapTroubleshooter extends Command
|
||||
$output[] = "-x";
|
||||
$output[] = "-b ".escapeshellarg($settings->ldap_basedn);
|
||||
$output[] = "-D ".escapeshellarg($settings->ldap_uname);
|
||||
$output[] = "-w ".escapeshellarg(Crypt::Decrypt($settings->ldap_pword));
|
||||
|
||||
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[] = escapeshellarg(parenthesized_filter($settings->ldap_filter));
|
||||
if($settings->ldap_tls) {
|
||||
$this->line("# adding STARTTLS option");
|
||||
@@ -171,6 +180,23 @@ 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) {
|
||||
@@ -179,7 +205,7 @@ class LdapTroubleshooter extends Command
|
||||
}
|
||||
}
|
||||
//$this->line(print_r($settings,true));
|
||||
$this->info("STAGE 1: Checking settings");
|
||||
$this->line("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)");
|
||||
}
|
||||
@@ -210,32 +236,40 @@ 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 = [];
|
||||
|
||||
//$this->info("Host IP is: ".print_r($ips,true));
|
||||
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']);
|
||||
|
||||
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;
|
||||
//$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);
|
||||
}
|
||||
$raw_ips[]=$ip['ip'];
|
||||
if($ip['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'];
|
||||
}
|
||||
}
|
||||
foreach ($raw_ips as $ip) {
|
||||
if ($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['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')) {
|
||||
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')) {
|
||||
$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->info("STAGE 2: Checking basic network connectivity");
|
||||
$ports = [389,636];
|
||||
$this->line("STAGE 2: Checking basic network connectivity");
|
||||
$ports = [636, 389];
|
||||
if(@$parsed['port'] && !in_array($parsed['port'],$ports)) {
|
||||
$ports[] = $parsed['port'];
|
||||
}
|
||||
@@ -246,7 +280,7 @@ class LdapTroubleshooter extends Command
|
||||
$errstr = '';
|
||||
$timeout = 30.0;
|
||||
$result = '';
|
||||
$this->info("Attempting to connect to port: ".$port." - may take up to $timeout seconds");
|
||||
$this->line("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) {
|
||||
@@ -265,9 +299,9 @@ class LdapTroubleshooter extends Command
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
$this->info("STAGE 3: Determine encryption algorithm, if any");
|
||||
$this->line("STAGE 3: Determine encryption algorithm, if any");
|
||||
|
||||
$ldap_urls = [];
|
||||
$ldap_urls = []; // [url, cert-check?, start_tls?]
|
||||
$pretty_ldap_urls = [];
|
||||
foreach($open_ports as $port) {
|
||||
$this->line("Trying TLS first for port $port");
|
||||
@@ -275,35 +309,46 @@ 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, "YES", "no" ];
|
||||
$pretty_ldap_urls[] = [$ldap_url, "enabled", "n/a (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 succesful to $ldap_url with certifcate-checks disabled");
|
||||
$ldap_urls[] = [ $ldap_url, false, false ];
|
||||
$pretty_ldap_urls[] = [ $ldap_url, "no", "no" ];
|
||||
$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)"];
|
||||
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, "YES", "YES" ];
|
||||
$pretty_ldap_urls[] = [$ldap_url, "enabled", "STARTTLS ENABLED"];
|
||||
continue;
|
||||
} else {
|
||||
$this->error("WARNING: Failed to bind to $ldap_url with STARTTLS enabled. Trying without STARTTLS");
|
||||
$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");
|
||||
}
|
||||
|
||||
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, "YES", "no" ];
|
||||
$pretty_ldap_urls[] = [$ldap_url, "n/a", "starttls disabled"];
|
||||
continue;
|
||||
} else {
|
||||
$this->error("WARNING: Failed to bind to $ldap_url. Giving up on port $port");
|
||||
@@ -313,23 +358,29 @@ class LdapTroubleshooter extends Command
|
||||
$this->debugout(print_r($ldap_urls,true));
|
||||
|
||||
if(count($ldap_urls) > 0 ) {
|
||||
$this->info("Found working LDAP URL's: ");
|
||||
$this->debugout("Found working LDAP URL's: ");
|
||||
foreach($ldap_urls as $ldap_url) { // TODO maybe do this as a $this->table() instead?
|
||||
$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->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->table(["URL", "Cert Checks Enabled?", "STARTTLS Enabled?"],$pretty_ldap_urls);
|
||||
$this->table(["URL", "Cert Checks?", "STARTTLS?"], $pretty_ldap_urls);
|
||||
} else {
|
||||
$this->error("ERROR - no valid LDAP URL's available - ABORTING");
|
||||
exit(1);
|
||||
}
|
||||
|
||||
$this->info("STAGE 4: Test Administrative Bind for LDAP Sync");
|
||||
$this->line("STAGE 4: Test Administrative Bind for LDAP Sync");
|
||||
foreach($ldap_urls AS $ldap_url) {
|
||||
$this->test_authed_bind($ldap_url[0], $ldap_url[1], $ldap_url[2], $settings->ldap_uname, Crypt::decrypt($settings->ldap_pword));
|
||||
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->info("STAGE 5: Test BaseDN");
|
||||
$this->line("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 = [];
|
||||
@@ -341,16 +392,23 @@ class LdapTroubleshooter extends Command
|
||||
$this->debugout("LDAP constants are: ".print_r($ldap_constants,true));
|
||||
|
||||
foreach($ldap_urls AS $ldap_url) {
|
||||
if($this->test_informational_bind($ldap_url[0],$ldap_url[1],$ldap_url[2],$settings->ldap_uname,Crypt::decrypt($settings->ldap_pword),$settings)) {
|
||||
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)) {
|
||||
$this->info("Success getting informational bind!");
|
||||
} else {
|
||||
$this->error("Unable to get information from bind.");
|
||||
}
|
||||
}
|
||||
|
||||
$this->info("STAGE 6: Test LDAP Login to Snipe-IT");
|
||||
$this->line("STAGE 6: Test LDAP Login to Snipe-IT");
|
||||
foreach($ldap_urls AS $ldap_url) {
|
||||
$this->info("Starting auth to ".$ldap_url[0]);
|
||||
$this->line("Starting auth to " . $ldap_url[0]);
|
||||
while(true) {
|
||||
$with_tls = $ldap_url[1] ? "with": "without";
|
||||
$with_startssl = $ldap_url[2] ? "using": "not using";
|
||||
@@ -359,7 +417,12 @@ class LdapTroubleshooter extends Command
|
||||
}
|
||||
$username = $this->ask("Username");
|
||||
$password = $this->secret("Password");
|
||||
$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?
|
||||
$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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -368,14 +431,17 @@ 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');
|
||||
@@ -404,9 +470,10 @@ 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->info("gonna try to bind now, this can take a while if we mess it up");
|
||||
$this->line("Attempting to bind now, this can take a while if we mess it up");
|
||||
$bind_results = ldap_bind($lconn);
|
||||
$this->info("Bind results are: ".$bind_results." which translate into boolean: ".(bool)$bind_results);
|
||||
$this->line("Bind results are: " . $bind_results . " which translate into boolean: " . (bool)$bind_results);
|
||||
ldap_close($lconn);
|
||||
return (bool)$bind_results;
|
||||
} catch (Exception $e) {
|
||||
$this->error("WARNING: Exception caught during bind - ".$e->getMessage());
|
||||
@@ -421,6 +488,7 @@ 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;
|
||||
@@ -446,22 +514,62 @@ class LdapTroubleshooter extends Command
|
||||
return false;
|
||||
}
|
||||
$this->info("SUCCESS - Able to bind to $ldap_url as $username");
|
||||
$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.
|
||||
$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));
|
||||
}
|
||||
// I don't see why this throws an Exception for Google LDAP, but I guess we ought to try and catch it?
|
||||
$this->comment("I guess we're trying to do the ldap search here, but sometimes it takes too long?");
|
||||
$this->debugout("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: ");
|
||||
for($i=0;$i<10;$i++) {
|
||||
$this->info($search_results[$i]);
|
||||
$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;
|
||||
}
|
||||
}
|
||||
}
|
||||
$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);
|
||||
}
|
||||
});
|
||||
}
|
||||
@@ -477,7 +585,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->info('WARNING: Unable to execute POSIX fork() commands, timeout may not be respected');
|
||||
$this->line('WARNING: Unable to execute POSIX fork() commands, timeout may not be respected');
|
||||
return $function();
|
||||
} else {
|
||||
$parent_pid = posix_getpid();
|
||||
@@ -514,4 +622,6 @@ class LdapTroubleshooter extends Command
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ class SendAcceptanceReminder extends Command
|
||||
if(!$email){
|
||||
$no_email_list[] = [
|
||||
'id' => $acceptance->assignedTo?->id,
|
||||
'name' => $acceptance->assignedTo?->present()->fullName(),
|
||||
'name' => $acceptance->assignedTo?->display_name,
|
||||
];
|
||||
} else {
|
||||
$count++;
|
||||
|
||||
@@ -1197,19 +1197,30 @@ 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',
|
||||
|
||||
@@ -29,7 +29,7 @@ class StorageHelper
|
||||
|
||||
public static function getMediaType($file_with_path) {
|
||||
|
||||
// The file exists and is allowed to be displayed inline
|
||||
// Get the file extension and determine the media type
|
||||
if (Storage::exists($file_with_path)) {
|
||||
$fileinfo = pathinfo($file_with_path);
|
||||
$extension = strtolower($fileinfo['extension']);
|
||||
@@ -51,6 +51,15 @@ class StorageHelper
|
||||
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
|
||||
}
|
||||
|
||||
@@ -146,6 +146,7 @@ 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.
|
||||
|
||||
@@ -609,7 +610,7 @@ class AssetsController extends Controller
|
||||
$asset->use_text = $asset->present()->fullName;
|
||||
|
||||
if (($asset->checkedOutToUser()) && ($asset->assigned)) {
|
||||
$asset->use_text .= ' → ' . $asset->assigned->getFullNameAttribute();
|
||||
$asset->use_text .= ' → ' . $asset->assigned->display_name;
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -230,13 +230,13 @@ class ConsumablesController extends Controller
|
||||
'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->present()->fullName()),
|
||||
'name'=> e($consumable_assignment->user->display_name),
|
||||
] : null,
|
||||
'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->present()->fullName()),
|
||||
'name'=> e($consumable_assignment->adminuser->display_name),
|
||||
] : null,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -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');
|
||||
}
|
||||
|
||||
95
app/Http/Controllers/Api/NotesController.php
Normal file
95
app/Http/Controllers/Api/NotesController.php
Normal file
@@ -0,0 +1,95 @@
|
||||
<?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);
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,6 @@
|
||||
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;
|
||||
@@ -51,10 +50,22 @@ 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) {
|
||||
@@ -78,7 +89,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()], 500);
|
||||
return response()->json(['message' => $e->getMessage()], 400);
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -64,6 +64,7 @@ class UsersController extends Controller
|
||||
'users.jobtitle',
|
||||
'users.last_login',
|
||||
'users.last_name',
|
||||
'users.display_name',
|
||||
'users.locale',
|
||||
'users.location_id',
|
||||
'users.manager_id',
|
||||
@@ -154,6 +155,10 @@ 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'));
|
||||
}
|
||||
@@ -284,6 +289,7 @@ class UsersController extends Controller
|
||||
[
|
||||
'last_name',
|
||||
'first_name',
|
||||
'display_name',
|
||||
'email',
|
||||
'jobtitle',
|
||||
'username',
|
||||
@@ -355,6 +361,7 @@ class UsersController extends Controller
|
||||
'users.employee_num',
|
||||
'users.first_name',
|
||||
'users.last_name',
|
||||
'users.display_name',
|
||||
'users.gravatar',
|
||||
'users.avatar',
|
||||
'users.email',
|
||||
@@ -365,20 +372,17 @@ 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('last_name', 'asc')->orderBy('first_name', 'asc');
|
||||
$users = $users->orderBy('display_name', 'asc')->orderBy('last_name', 'asc')->orderBy('first_name', 'asc');
|
||||
$users = $users->paginate(50);
|
||||
|
||||
foreach ($users as $user) {
|
||||
$name_str = '';
|
||||
if ($user->last_name != '') {
|
||||
$name_str .= $user->last_name.', ';
|
||||
}
|
||||
$name_str .= $user->first_name;
|
||||
$name_str = $user->display_name;
|
||||
|
||||
if ($user->username != '') {
|
||||
$name_str .= ' ('.$user->username.')';
|
||||
@@ -511,6 +515,10 @@ class UsersController extends Controller
|
||||
$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');
|
||||
}
|
||||
|
||||
@@ -797,7 +797,7 @@ class AssetsController extends Controller
|
||||
'item_id' => $asset->id,
|
||||
'item_type' => Asset::class,
|
||||
'created_by' => auth()->id(),
|
||||
'note' => 'Checkout imported by '.auth()->user()->present()->fullName().' from history importer',
|
||||
'note' => 'Checkout imported by '.auth()->user()->display_name.' 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'],
|
||||
@@ -825,7 +825,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()->present()->fullName().' from history importer',
|
||||
'note' => 'Checkin imported by '.auth()->user()->display_name.' from history importer',
|
||||
'target_id' => null,
|
||||
'created_at' => $checkin_date,
|
||||
'action_type' => 'checkin',
|
||||
|
||||
@@ -364,7 +364,7 @@ class LicensesController extends Controller
|
||||
$license->order_number,
|
||||
$license->free_seat_count,
|
||||
$license->seats,
|
||||
($license->adminuser ? $license->adminuser->present()->fullName() : trans('admin/reports/general.deleted_user')),
|
||||
($license->adminuser ? $license->adminuser->display_name : trans('admin/reports/general.deleted_user')),
|
||||
$license->depreciation ? $license->depreciation->name: '',
|
||||
$license->updated_at,
|
||||
$license->deleted_at,
|
||||
|
||||
@@ -275,7 +275,7 @@ class ReportsController extends Controller
|
||||
|
||||
if ($actionlog->target) {
|
||||
if ($actionlog->targetType() == 'user') {
|
||||
$target_name = $actionlog->target->getFullNameAttribute();
|
||||
$target_name = $actionlog->target->display_name;
|
||||
} else {
|
||||
$target_name = $actionlog->target->getDisplayNameAttribute();
|
||||
}
|
||||
@@ -289,7 +289,7 @@ class ReportsController extends Controller
|
||||
|
||||
$row = [
|
||||
$actionlog->created_at,
|
||||
($actionlog->adminuser) ? e($actionlog->adminuser->getFullNameAttribute()) : '',
|
||||
($actionlog->adminuser) ? e($actionlog->adminuser->display_name) : '',
|
||||
$actionlog->present()->actionType(),
|
||||
e($actionlog->itemType()),
|
||||
($actionlog->itemType() == 'user') ? $actionlog->filename : $item_name,
|
||||
@@ -856,7 +856,7 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('assigned_to')) {
|
||||
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? $asset->assigned->getFullNameAttribute() : ($asset->assigned ? $asset->assigned->display_name : '');
|
||||
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ?? $asset->assigned->display_name;
|
||||
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? 'user' : $asset->assignedType();
|
||||
}
|
||||
|
||||
|
||||
@@ -873,6 +873,7 @@ 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');
|
||||
@@ -889,7 +890,12 @@ 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');
|
||||
|
||||
@@ -88,6 +88,7 @@ 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'));
|
||||
}
|
||||
@@ -240,6 +241,7 @@ class UsersController extends Controller
|
||||
|
||||
$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');
|
||||
@@ -562,10 +564,10 @@ class UsersController extends Controller
|
||||
$user->employee_num,
|
||||
$user->first_name,
|
||||
$user->last_name,
|
||||
$user->present()->fullName(),
|
||||
$user->display_name,
|
||||
$user->username,
|
||||
$user->email,
|
||||
($user->manager) ? $user->manager->present()->fullName() : '',
|
||||
($user->manager) ? $user->manager->display_name : '',
|
||||
($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->present()->fullName();
|
||||
$data['requested_by'] = $user->display_name;
|
||||
$data['item'] = $item;
|
||||
$data['item_type'] = $itemType;
|
||||
$data['target'] = auth()->user();
|
||||
|
||||
@@ -109,7 +109,7 @@ class SettingsSamlRequest extends FormRequest
|
||||
];
|
||||
|
||||
$pkey = openssl_pkey_new([
|
||||
'private_key_bits' => 2048,
|
||||
'private_key_bits' => config('app.saml_key_size'),
|
||||
'private_key_type' => OPENSSL_KEYTYPE_RSA,
|
||||
]);
|
||||
|
||||
|
||||
@@ -44,7 +44,7 @@ class AccessoriesTransformer
|
||||
'checkouts_count' => $accessory->checkouts_count,
|
||||
'created_by' => ($accessory->adminuser) ? [
|
||||
'id' => (int) $accessory->adminuser->id,
|
||||
'name'=> e($accessory->adminuser->present()->fullName()),
|
||||
'name'=> e($accessory->adminuser->display_name),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($accessory->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($accessory->updated_at, 'datetime'),
|
||||
|
||||
@@ -150,7 +150,7 @@ class ActionlogsTransformer
|
||||
|
||||
'item' => ($actionlog->item) ? [
|
||||
'id' => (int) $actionlog->item->id,
|
||||
'name' => ($actionlog->itemType()=='user') ? e($actionlog->item->getFullNameAttribute()) : e($actionlog->item->getDisplayNameAttribute()),
|
||||
'name' => e($actionlog->item->display_name) ?? null,
|
||||
'type' => e($actionlog->itemType()),
|
||||
'serial' =>e($actionlog->item->serial) ? e($actionlog->item->serial) : null
|
||||
] : null,
|
||||
@@ -165,19 +165,19 @@ class ActionlogsTransformer
|
||||
'action_type' => $actionlog->present()->actionType(),
|
||||
'admin' => ($actionlog->adminuser) ? [
|
||||
'id' => (int) $actionlog->adminuser->id,
|
||||
'name' => e($actionlog->adminuser->getFullNameAttribute()),
|
||||
'name' => e($actionlog->adminuser->display_name),
|
||||
'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->getFullNameAttribute()),
|
||||
'name' => e($actionlog->adminuser->display_name),
|
||||
'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->targetType()=='user') ? e($actionlog->target->getFullNameAttribute()) : e($actionlog->target->getDisplayNameAttribute()),
|
||||
'name' => ($actionlog->target->display_name) ?? null,
|
||||
'type' => e($actionlog->targetType()),
|
||||
] : null,
|
||||
|
||||
|
||||
@@ -68,7 +68,7 @@ class AssetModelsTransformer
|
||||
'notes' => Helper::parseEscapedMarkedownInline($assetmodel->notes),
|
||||
'created_by' => ($assetmodel->adminuser) ? [
|
||||
'id' => (int) $assetmodel->adminuser->id,
|
||||
'name'=> e($assetmodel->adminuser->present()->fullName()),
|
||||
'name'=> e($assetmodel->adminuser->display_name),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($assetmodel->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($assetmodel->updated_at, 'datetime'),
|
||||
|
||||
@@ -58,6 +58,13 @@ 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),
|
||||
@@ -84,7 +91,7 @@ class AssetsTransformer
|
||||
'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->present()->fullName()),
|
||||
'name'=> e($asset->adminuser->display_name),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($asset->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($asset->updated_at, 'datetime'),
|
||||
@@ -280,7 +287,7 @@ class AssetsTransformer
|
||||
'id' => (int) $asset->id,
|
||||
'image' => ($asset->getImageUrl()) ? $asset->getImageUrl() : null,
|
||||
'type' => 'asset',
|
||||
'name' => e($asset->present()->fullName()),
|
||||
'name' => e($asset->display_name),
|
||||
'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->present()->fullName()),
|
||||
'name'=> e($category->adminuser->display_name),
|
||||
] : 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->present()->fullName()),
|
||||
'name'=> e($company->adminuser->display_name),
|
||||
] : 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->present()->fullName()),
|
||||
'name'=> e($component->adminuser->display_name),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($component->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($component->updated_at, 'datetime'),
|
||||
|
||||
@@ -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->present()->fullName()),
|
||||
'name'=> e($consumable->adminuser->display_name),
|
||||
] : 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->getFullNameAttribute()),
|
||||
'name' => e($department->manager->display_name),
|
||||
'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->present()->fullName()),
|
||||
'name'=> e($depreciation->adminuser->display_name),
|
||||
] : 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->present()->fullName()),
|
||||
'name'=> e($group->adminuser->display_name),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($group->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($group->updated_at, 'datetime'),
|
||||
|
||||
@@ -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->present()->fullName()),
|
||||
'name'=> e($license->adminuser->display_name),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($license->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($license->updated_at, 'datetime'),
|
||||
|
||||
@@ -73,11 +73,11 @@ class MaintenancesTransformer
|
||||
'completion_date' => Helper::getFormattedDateObject($assetmaintenance->completion_date, 'date'),
|
||||
'user_id' => ($assetmaintenance->adminuser) ? [
|
||||
'id' => $assetmaintenance->adminuser->id,
|
||||
'name'=> e($assetmaintenance->adminuser->present()->fullName())
|
||||
'name'=> e($assetmaintenance->adminuser->display_name)
|
||||
] : null, // legacy to not change the shape of the API
|
||||
'created_by' => ($assetmaintenance->adminuser) ? [
|
||||
'id' => (int) $assetmaintenance->adminuser->id,
|
||||
'name'=> e($assetmaintenance->adminuser->present()->fullName()),
|
||||
'name'=> e($assetmaintenance->adminuser->display_name),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($assetmaintenance->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($assetmaintenance->updated_at, 'datetime'),
|
||||
|
||||
@@ -40,7 +40,7 @@ class ManufacturersTransformer
|
||||
'notes' => Helper::parseEscapedMarkedownInline($manufacturer->notes),
|
||||
'created_by' => ($manufacturer->adminuser) ? [
|
||||
'id' => (int) $manufacturer->adminuser->id,
|
||||
'name'=> e($manufacturer->adminuser->present()->fullName()),
|
||||
'name'=> e($manufacturer->adminuser->display_name),
|
||||
] : 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->present()->fullName()),
|
||||
'name'=> e($kit->adminuser->display_name),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($kit->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($kit->updated_at, 'datetime'),
|
||||
|
||||
@@ -26,7 +26,7 @@ class ProfileTransformer
|
||||
'id' => (int) $file->id,
|
||||
'icon' => Helper::filetype_icon($file->filename),
|
||||
'item' => ($file->item) ? [
|
||||
'name' => ($file->itemType()=='user') ? e($file->item->getFullNameAttribute()) : e($file->item->getDisplayNameAttribute()),
|
||||
'name' => ($file->itemType()=='user') ? e($file->item->display_name) : 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->present()->fullName()),
|
||||
'name'=> e($statuslabel->adminuser->display_name),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($statuslabel->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($statuslabel->updated_at, 'datetime'),
|
||||
|
||||
@@ -45,7 +45,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()),
|
||||
'inlineable' => StorageHelper::allowSafeInline($file->uploads_file_path()) ?? false,
|
||||
'exists_on_disk' => (Storage::exists($file->uploads_file_path()) ? true : false),
|
||||
];
|
||||
|
||||
|
||||
@@ -31,16 +31,17 @@ class UsersTransformer
|
||||
$array = [
|
||||
'id' => (int) $user->id,
|
||||
'avatar' => e($user->present()->gravatar) ?? null,
|
||||
'name' => e($user->getFullNameAttribute()),
|
||||
'first_name' => e($user->first_name),
|
||||
'last_name' => e($user->last_name),
|
||||
'username' => e($user->username),
|
||||
'name' => e($user->getFullNameAttribute()) ?? null,
|
||||
'first_name' => e($user->first_name) ?? null,
|
||||
'last_name' => e($user->last_name) ?? null,
|
||||
'display_name' => e($user->getRawOriginal('display_name')) ?? null,
|
||||
'username' => e($user->username) ?? null,
|
||||
'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->first_name).' '.e($user->manager->last_name),
|
||||
'name'=> e($user->manager->display_name),
|
||||
] : null,
|
||||
'jobtitle' => ($user->jobtitle) ? e($user->jobtitle) : null,
|
||||
'vip' => ($user->vip == '1') ? true : false,
|
||||
@@ -59,7 +60,7 @@ class UsersTransformer
|
||||
] : null,
|
||||
'department_manager' => ($user->department?->manager) ? [
|
||||
'id' => (int) $user->department->manager->id,
|
||||
'name'=> e($user->department->manager->full_name),
|
||||
'name'=> e($user->department->manager->display_name),
|
||||
] : null,
|
||||
'location' => ($user->userloc) ? [
|
||||
'id' => (int) $user->userloc->id,
|
||||
@@ -82,7 +83,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->present()->fullName),
|
||||
'name'=> e($user->createdBy->display_name),
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($user->updated_at, 'datetime'),
|
||||
@@ -138,6 +139,7 @@ class UsersTransformer
|
||||
'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),
|
||||
|
||||
@@ -72,6 +72,7 @@ abstract class Importer
|
||||
'termination_date' => 'termination date',
|
||||
'warranty_months' => 'warranty',
|
||||
'full_name' => 'full name',
|
||||
'display_name' => 'display name',
|
||||
'email' => 'email',
|
||||
'username' => 'username',
|
||||
'address' => 'address',
|
||||
@@ -299,6 +300,7 @@ 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' => '',
|
||||
@@ -369,6 +371,7 @@ 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;
|
||||
|
||||
@@ -47,6 +47,7 @@ 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'));
|
||||
|
||||
@@ -339,6 +339,7 @@ class Importer extends Component
|
||||
'start_date' => trans('general.start_date'),
|
||||
'state' => trans('general.state'),
|
||||
'username' => trans('admin/users/table.username'),
|
||||
'display_name' => trans('admin/users/table.display_name'),
|
||||
'vip' => trans('general.importer.vip'),
|
||||
'website' => trans('general.website'),
|
||||
'zip' => trans('general.zip'),
|
||||
@@ -485,6 +486,13 @@ class Importer extends Component
|
||||
'username',
|
||||
trans('general.importer.checked_out_to_username'),
|
||||
],
|
||||
'display_name' =>
|
||||
[
|
||||
'display name',
|
||||
'displayName',
|
||||
'display',
|
||||
trans('admin/users/table.display_name'),
|
||||
],
|
||||
'first_name' =>
|
||||
[
|
||||
'first name',
|
||||
|
||||
@@ -47,7 +47,7 @@ class CheckinAssetMail extends Mailable
|
||||
|
||||
return new Envelope(
|
||||
from: $from,
|
||||
subject: trans('mail.Asset_Checkin_Notification'),
|
||||
subject: trans('mail.Asset_Checkin_Notification', ['tag' => $this->item->asset_tag]),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
@@ -3,6 +3,8 @@
|
||||
namespace App\Mail;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Location;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
@@ -41,7 +43,7 @@ class CheckoutAccessoryMail extends Mailable
|
||||
|
||||
return new Envelope(
|
||||
from: $from,
|
||||
subject: (trans('mail.Accessory_Checkout_Notification')),
|
||||
subject: trans('mail.Accessory_Checkout_Notification'),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -54,6 +56,17 @@ class CheckoutAccessoryMail extends Mailable
|
||||
$eula = $this->item->getEula();
|
||||
$req_accept = $this->item->requireAcceptance();
|
||||
$accept_url = is_null($this->acceptance) ? null : route('account.accept.item', $this->acceptance);
|
||||
$name = null;
|
||||
|
||||
if($this->target instanceof User){
|
||||
$name = $this->target->display_name;
|
||||
}
|
||||
else if($this->target instanceof Asset){
|
||||
$name = $this->target->assignedto?->display_name;
|
||||
}
|
||||
else if($this->target instanceof Location){
|
||||
$name = $this->target->manager->name;
|
||||
}
|
||||
|
||||
return new Content(
|
||||
markdown: 'mail.markdown.checkout-accessory',
|
||||
@@ -61,14 +74,35 @@ class CheckoutAccessoryMail extends Mailable
|
||||
'item' => $this->item,
|
||||
'admin' => $this->admin,
|
||||
'note' => $this->note,
|
||||
'target' => $this->target,
|
||||
'target' => $name,
|
||||
'eula' => $eula,
|
||||
'req_accept' => $req_accept,
|
||||
'accept_url' => $accept_url,
|
||||
'checkout_qty' => $this->checkout_qty,
|
||||
'introduction_line' => $this->introductionLine(),
|
||||
],
|
||||
);
|
||||
}
|
||||
private function introductionLine(): string
|
||||
{
|
||||
if ($this->target instanceof Location) {
|
||||
return trans('mail.new_item_checked_location', ['location' => $this->target->name ]);
|
||||
}
|
||||
if ($this->requiresAcceptance()) {
|
||||
return trans('mail.new_item_checked_with_acceptance');
|
||||
}
|
||||
|
||||
if (!$this->requiresAcceptance()) {
|
||||
return trans('mail.new_item_checked');
|
||||
}
|
||||
|
||||
// we shouldn't get here but let's send a default message just in case
|
||||
return trans('new_item_checked');
|
||||
}
|
||||
private function requiresAcceptance(): int|bool
|
||||
{
|
||||
return method_exists($this->item, 'requireAcceptance') ? $this->item->requireAcceptance() : 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Mail;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Location;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Illuminate\Bus\Queueable;
|
||||
@@ -36,14 +37,6 @@ class CheckoutAssetMail extends Mailable
|
||||
$this->settings = Setting::getSettings();
|
||||
$this->target = $checkedOutTo;
|
||||
|
||||
// Location is a target option, but there are no emails currently associated with locations.
|
||||
if($this->target instanceof User){
|
||||
$this->target = $this->target->present()?->fullName();
|
||||
}
|
||||
else if($this->target instanceof Asset){
|
||||
$this->target = $this->target->assignedto?->present()?->fullName();
|
||||
}
|
||||
|
||||
$this->last_checkout = '';
|
||||
$this->expected_checkin = '';
|
||||
|
||||
@@ -85,6 +78,17 @@ class CheckoutAssetMail extends Mailable
|
||||
$eula = method_exists($this->item, 'getEula') ? $this->item->getEula() : '';
|
||||
$req_accept = $this->requiresAcceptance();
|
||||
$fields = [];
|
||||
$name = null;
|
||||
|
||||
if($this->target instanceof User){
|
||||
$name = $this->target->display_name;
|
||||
}
|
||||
else if($this->target instanceof Asset){
|
||||
$name = $this->target->assignedto?->display_name;
|
||||
}
|
||||
else if($this->target instanceof Location){
|
||||
$name = $this->target->manager->name;
|
||||
}
|
||||
|
||||
// Check if the item has custom fields associated with it
|
||||
if (($this->item->model) && ($this->item->model->fieldset)) {
|
||||
@@ -100,7 +104,7 @@ class CheckoutAssetMail extends Mailable
|
||||
'admin' => $this->admin,
|
||||
'status' => $this->item->assetstatus?->name,
|
||||
'note' => $this->note,
|
||||
'target' => $this->target,
|
||||
'target' => $name,
|
||||
'fields' => $fields,
|
||||
'eula' => $eula,
|
||||
'req_accept' => $req_accept,
|
||||
@@ -125,7 +129,7 @@ class CheckoutAssetMail extends Mailable
|
||||
private function getSubject(): string
|
||||
{
|
||||
if ($this->firstTimeSending) {
|
||||
return trans('mail.Asset_Checkout_Notification');
|
||||
return trans('mail.Asset_Checkout_Notification', ['tag' => $this->item->asset_tag]);
|
||||
}
|
||||
|
||||
return trans('mail.unaccepted_asset_reminder');
|
||||
@@ -133,6 +137,9 @@ class CheckoutAssetMail extends Mailable
|
||||
|
||||
private function introductionLine(): string
|
||||
{
|
||||
if ($this->firstTimeSending && $this->target instanceof Location) {
|
||||
return trans('mail.new_item_checked_location', ['location' => $this->target->name ]);
|
||||
}
|
||||
if ($this->firstTimeSending && $this->requiresAcceptance()) {
|
||||
return trans('mail.new_item_checked_with_acceptance');
|
||||
}
|
||||
|
||||
@@ -31,10 +31,10 @@ class CheckoutLicenseMail extends Mailable
|
||||
$this->target = $checkedOutTo;
|
||||
|
||||
if($this->target instanceof User){
|
||||
$this->target = $this->target->present()?->fullName();
|
||||
$this->target = $this->target->display_name;
|
||||
}
|
||||
elseif($this->target instanceof Asset){
|
||||
$this->target = $this->target->assignedto?->present()?->fullName();
|
||||
$this->target = $this->target->display_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -30,10 +30,10 @@ class FieldOption
|
||||
if ($asset->relationLoaded('assignedTo')) {
|
||||
// If the "assignedTo" relationship was eager loaded then the way to get the
|
||||
// relationship changes from $asset->assignedTo to $asset->assigned.
|
||||
return $asset->assigned ? $asset->assigned->present()->fullName() : null;
|
||||
return $asset->assigned ? $asset->assigned->display_name : null;
|
||||
}
|
||||
|
||||
return $asset->assignedTo ? $asset->assignedTo->present()->fullName() : null;
|
||||
return $asset->assignedTo ? $asset->assignedTo->display_name : null;
|
||||
}
|
||||
|
||||
// Handle Laravel's stupid Carbon datetime casting
|
||||
|
||||
110
app/Models/Labels/Sheets/Avery/L6009.php
Normal file
110
app/Models/Labels/Sheets/Avery/L6009.php
Normal file
@@ -0,0 +1,110 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Labels\Sheets\Avery;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Labels\RectangleSheet;
|
||||
|
||||
abstract class L6009 extends RectangleSheet
|
||||
{
|
||||
|
||||
private const PAPER_FORMAT = 'A4';
|
||||
private const PAPER_ORIENTATION = 'P';
|
||||
|
||||
/* Data in pt from Word Template */
|
||||
private const COLUMN1_X = 31.70;
|
||||
private const COLUMN2_X = 167.92;
|
||||
private const ROW1_Y = 53.00;
|
||||
private const ROW2_Y = 112.8;
|
||||
private const LABEL_W = 122.24;
|
||||
private const LABEL_H = 66.5;
|
||||
|
||||
private float $pageWidth;
|
||||
private float $pageHeight;
|
||||
private float $pageMarginLeft;
|
||||
private float $pageMarginTop;
|
||||
|
||||
private float $columnSpacing;
|
||||
private float $rowSpacing;
|
||||
|
||||
private float $labelWidth;
|
||||
private float $labelHeight;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$paperSize = static::fromFormat(self::PAPER_FORMAT, self::PAPER_ORIENTATION, $this->getUnit(), 0);
|
||||
$this->pageWidth = $paperSize->width;
|
||||
$this->pageHeight = $paperSize->height;
|
||||
|
||||
$this->pageMarginLeft = Helper::convertUnit(self::COLUMN1_X, 'pt', $this->getUnit());
|
||||
$this->pageMarginTop = Helper::convertUnit(self::ROW1_Y, 'pt', $this->getUnit());
|
||||
|
||||
$columnSpacingPt = self::COLUMN2_X - self::COLUMN1_X - self::LABEL_W;
|
||||
$this->columnSpacing = Helper::convertUnit($columnSpacingPt, 'pt', $this->getUnit());
|
||||
$rowSpacingPt = self::ROW2_Y - self::ROW1_Y - self::LABEL_H;
|
||||
$this->rowSpacing = Helper::convertUnit($rowSpacingPt, 'pt', $this->getUnit());
|
||||
|
||||
$this->labelWidth = Helper::convertUnit(self::LABEL_W, 'pt', $this->getUnit());
|
||||
$this->labelHeight = Helper::convertUnit(self::LABEL_H, 'pt', $this->getUnit());
|
||||
}
|
||||
|
||||
public function getPageWidth()
|
||||
{
|
||||
return $this->pageWidth;
|
||||
}
|
||||
public function getPageHeight()
|
||||
{
|
||||
return $this->pageHeight;
|
||||
}
|
||||
|
||||
public function getPageMarginTop()
|
||||
{
|
||||
return $this->pageMarginTop;
|
||||
}
|
||||
public function getPageMarginBottom()
|
||||
{
|
||||
return $this->pageMarginTop;
|
||||
}
|
||||
public function getPageMarginLeft()
|
||||
{
|
||||
return $this->pageMarginLeft;
|
||||
}
|
||||
public function getPageMarginRight()
|
||||
{
|
||||
return $this->pageMarginLeft;
|
||||
}
|
||||
|
||||
public function getColumns()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
public function getRows()
|
||||
{
|
||||
return 12;
|
||||
}
|
||||
|
||||
public function getLabelColumnSpacing()
|
||||
{
|
||||
return $this->columnSpacing;
|
||||
}
|
||||
public function getLabelRowSpacing()
|
||||
{
|
||||
return $this->rowSpacing;
|
||||
}
|
||||
|
||||
public function getLabelWidth()
|
||||
{
|
||||
return $this->labelWidth;
|
||||
}
|
||||
public function getLabelHeight()
|
||||
{
|
||||
return $this->labelHeight;
|
||||
}
|
||||
|
||||
public function getLabelBorder()
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
?>
|
||||
121
app/Models/Labels/Sheets/Avery/L6009_A.php
Normal file
121
app/Models/Labels/Sheets/Avery/L6009_A.php
Normal file
@@ -0,0 +1,121 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Labels\Sheets\Avery;
|
||||
|
||||
|
||||
class L6009_A extends L6009
|
||||
{
|
||||
private const BARCODE_MARGIN = 1.80;
|
||||
private const TAG_SIZE = 4.80;
|
||||
private const TITLE_SIZE = 3.00;
|
||||
private const TITLE_MARGIN = 1.80;
|
||||
private const LABEL_SIZE = 2.8;
|
||||
private const LABEL_MARGIN = - 0.45;
|
||||
private const FIELD_SIZE = 3.80;
|
||||
private const FIELD_MARGIN = 0.20;
|
||||
|
||||
public function getUnit()
|
||||
{
|
||||
return 'mm';
|
||||
}
|
||||
|
||||
public function getLabelMarginTop()
|
||||
{
|
||||
return 0.06;
|
||||
}
|
||||
public function getLabelMarginBottom()
|
||||
{
|
||||
return 0.06;
|
||||
}
|
||||
public function getLabelMarginLeft()
|
||||
{
|
||||
return 0.06;
|
||||
}
|
||||
public function getLabelMarginRight()
|
||||
{
|
||||
return 0.06;
|
||||
}
|
||||
|
||||
public function getSupportAssetTag()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public function getSupport1DBarcode()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public function getSupport2DBarcode()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public function getSupportFields()
|
||||
{
|
||||
return 4;
|
||||
}
|
||||
public function getSupportLogo()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public function getSupportTitle()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
public function preparePDF($pdf)
|
||||
{
|
||||
}
|
||||
|
||||
public function write($pdf, $record)
|
||||
{
|
||||
$pa = $this->getLabelPrintableArea();
|
||||
|
||||
$currentX = $pa->x1;
|
||||
$currentY = $pa->y1;
|
||||
$usableWidth = $pa->w;
|
||||
$usableHeight = $pa->h;
|
||||
|
||||
if ($record->has('title')) {
|
||||
static::writeText(
|
||||
$pdf, $record->get('title'),
|
||||
$pa->x1, $pa->y1,
|
||||
'freesans', '', self::TITLE_SIZE, 'C',
|
||||
$pa->w, self::TITLE_SIZE, true, 0
|
||||
);
|
||||
|
||||
}
|
||||
$currentY += self::TITLE_SIZE + self::TITLE_MARGIN;
|
||||
$usableHeight -= self::TITLE_SIZE + self::TITLE_MARGIN;
|
||||
$barcodeSize = $usableHeight;
|
||||
if ($record->has('barcode2d')) {
|
||||
static::write2DBarcode(
|
||||
$pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type,
|
||||
$currentX, $currentY,
|
||||
$barcodeSize, $barcodeSize
|
||||
);
|
||||
$currentX += $barcodeSize + self::BARCODE_MARGIN;
|
||||
$usableWidth -= $barcodeSize + self::BARCODE_MARGIN;
|
||||
}
|
||||
|
||||
foreach ($record->get('fields') as $field) {
|
||||
static::writeText(
|
||||
$pdf, $field['label'],
|
||||
$currentX, $currentY,
|
||||
'freesans', '', self::LABEL_SIZE, 'L',
|
||||
$usableWidth, self::LABEL_SIZE, true, 0
|
||||
);
|
||||
$currentY += self::LABEL_SIZE + self::LABEL_MARGIN;
|
||||
|
||||
static::writeText(
|
||||
$pdf, $field['value'],
|
||||
$currentX, $currentY,
|
||||
'freemono', 'B', self::FIELD_SIZE, 'L',
|
||||
$usableWidth, self::FIELD_SIZE, true, 0, 0.01
|
||||
);
|
||||
$currentY += self::FIELD_SIZE + self::FIELD_MARGIN;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
?>
|
||||
116
app/Models/Labels/Tapes/Dymo/LabelWriter_11354.php
Normal file
116
app/Models/Labels/Tapes/Dymo/LabelWriter_11354.php
Normal file
@@ -0,0 +1,116 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Labels\Tapes\Dymo;
|
||||
|
||||
|
||||
class LabelWriter_11354 extends LabelWriter
|
||||
{
|
||||
private const BARCODE1D_HEIGHT = 3.00;
|
||||
private const BARCODE_MARGIN = 1.80;
|
||||
private const TAG_SIZE = 2.80;
|
||||
private const TITLE_SIZE = 2.80;
|
||||
private const TITLE_MARGIN = 0.50;
|
||||
private const FIELD_SIZE = 2.80;
|
||||
private const FIELD_MARGIN = 0.15;
|
||||
|
||||
public function getUnit()
|
||||
{
|
||||
return 'mm';
|
||||
}
|
||||
public function getWidth()
|
||||
{
|
||||
return 57;
|
||||
}
|
||||
public function getHeight()
|
||||
{
|
||||
return 32;
|
||||
}
|
||||
public function getSupportAssetTag()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public function getSupport1DBarcode()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public function getSupport2DBarcode()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public function getSupportFields()
|
||||
{
|
||||
return 5;
|
||||
}
|
||||
public function getSupportLogo()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
public function getSupportTitle()
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public function preparePDF($pdf)
|
||||
{
|
||||
}
|
||||
|
||||
public function write($pdf, $record)
|
||||
{
|
||||
$pa = $this->getPrintableArea();
|
||||
|
||||
$currentX = $pa->x1;
|
||||
$currentY = $pa->y1;
|
||||
$usableWidth = $pa->w;
|
||||
$usableHeight = $pa->h;
|
||||
|
||||
// Wide 1D barcode on top
|
||||
if ($record->has('barcode1d')) {
|
||||
static::write1DBarcode(
|
||||
$pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type,
|
||||
$currentX, $currentY, $usableWidth, self::BARCODE1D_HEIGHT
|
||||
);
|
||||
$currentY += self::BARCODE1D_HEIGHT + self::BARCODE_MARGIN;
|
||||
$usableHeight -= self::BARCODE1D_HEIGHT + self::BARCODE_MARGIN;
|
||||
}
|
||||
|
||||
// 2D Barcode in left column
|
||||
if ($record->has('barcode2d')) {
|
||||
$barcodeSize = $usableHeight - self::TAG_SIZE;
|
||||
|
||||
static::writeText(
|
||||
$pdf, $record->get('tag'),
|
||||
$currentX, $pa->y2 - self::TAG_SIZE,
|
||||
'freesans', 'b', self::TAG_SIZE, 'C',
|
||||
$barcodeSize, self::TAG_SIZE, true, 0
|
||||
);
|
||||
static::write2DBarcode(
|
||||
$pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type,
|
||||
$currentX, $currentY,
|
||||
$barcodeSize, $barcodeSize
|
||||
);
|
||||
$currentX += $barcodeSize + self::BARCODE_MARGIN;
|
||||
$usableWidth -= $barcodeSize + self::BARCODE_MARGIN;
|
||||
}
|
||||
|
||||
// Right column
|
||||
if ($record->has('title')) {
|
||||
static::writeText(
|
||||
$pdf, $record->get('title'),
|
||||
$currentX, $currentY,
|
||||
'freesans', 'b', self::TITLE_SIZE, 'L',
|
||||
$usableWidth, self::TITLE_SIZE, true, 0
|
||||
);
|
||||
$currentY += self::TITLE_SIZE + self::TITLE_MARGIN;
|
||||
}
|
||||
|
||||
foreach ($record->get('fields') as $field) {
|
||||
static::writeText(
|
||||
$pdf, (($field['label']) ? $field['label'].' ' : '') . $field['value'],
|
||||
$currentX, $currentY,
|
||||
'freesans', '', self::FIELD_SIZE, 'L',
|
||||
$usableWidth, self::FIELD_SIZE, true, 0, 0.3
|
||||
);
|
||||
$currentY += self::FIELD_SIZE + self::FIELD_MARGIN;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
@@ -27,6 +27,35 @@ use Illuminate\Support\Facades\Crypt;
|
||||
|
||||
class Ldap extends Model
|
||||
{
|
||||
public static function ignoreCertificates(bool $ignore_cert = true)
|
||||
{
|
||||
if (defined('LDAP_OPT_X_TLS_REQUIRE_CERT') && defined('LDAP_OPT_X_TLS_NEVER')) {
|
||||
// TODO - we are currently, as a 'safety', doing *both* the following 'new-style' ldap_set_option calls,
|
||||
// as well as "falling-through" to the 'old-style' putenv() calls.
|
||||
//
|
||||
// I *suspect* we can eventually remove the putenv() calls, but I'm just a little nervous about that.
|
||||
// According to the PHP docs, the LDAP_OPT_X_TLS_REQUIRE_CERT constant has been available since PHP 7.0.
|
||||
// We're currently using PHP versions way, way later than that (v8.2-v8.4 as of this writing). So it's
|
||||
// unlikely that these constants wouldn't be defined - unless you didn't have LDAP support in the first
|
||||
// place. But if that were to happen, I would hope we would've detected that long, long ago, rather than at
|
||||
// this point.
|
||||
if ($ignore_cert) {
|
||||
if (ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_NEVER)) {
|
||||
//return true;
|
||||
}
|
||||
} else {
|
||||
if (ldap_set_option(null, LDAP_OPT_X_TLS_REQUIRE_CERT, LDAP_OPT_X_TLS_DEMAND)) {
|
||||
//return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($ignore_cert) {
|
||||
return putenv('LDAPTLS_REQCERT=never');
|
||||
} else {
|
||||
return putenv('LDAPTLS_REQCERT');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a connection to LDAP using the settings in Admin > Settings.
|
||||
*
|
||||
@@ -43,15 +72,12 @@ class Ldap extends Model
|
||||
|
||||
// If we are ignoring the SSL cert we need to setup the environment variable
|
||||
// before we create the connection
|
||||
if ($ldap_server_cert_ignore == '1') {
|
||||
putenv('LDAPTLS_REQCERT=never');
|
||||
}
|
||||
self::ignoreCertificates((bool)$ldap_server_cert_ignore);
|
||||
|
||||
// If the user specifies where CA Certs are, make sure to use them
|
||||
if (env('LDAPTLS_CACERT')) {
|
||||
putenv('LDAPTLS_CACERT='.env('LDAPTLS_CACERT'));
|
||||
}
|
||||
|
||||
$connection = @ldap_connect($ldap_host);
|
||||
|
||||
if (! $connection) {
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Models;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
class SnipeModel extends Model
|
||||
@@ -21,7 +22,7 @@ class SnipeModel extends Model
|
||||
*/
|
||||
public function setPurchaseCostAttribute($value)
|
||||
{
|
||||
if (is_float($value)) {
|
||||
if (is_numeric($value)) {
|
||||
//value is *already* a floating-point number. Just assign it directly
|
||||
$this->attributes['purchase_cost'] = $value;
|
||||
return;
|
||||
@@ -155,9 +156,13 @@ class SnipeModel extends Model
|
||||
$this->attributes['status_id'] = $value;
|
||||
}
|
||||
|
||||
//
|
||||
public function getDisplayNameAttribute()
|
||||
|
||||
protected function displayName(): Attribute
|
||||
{
|
||||
return $this->name;
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value) => $this->name,
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -34,6 +34,7 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
|
||||
|
||||
'validations' => [
|
||||
$user_prefix . 'userName' => 'required',
|
||||
$user_prefix . 'displayName' => 'nullable|string',
|
||||
$user_prefix . 'name.givenName' => 'required',
|
||||
$user_prefix . 'name.familyName' => 'nullable|string',
|
||||
$user_prefix . 'externalId' => 'nullable|string',
|
||||
@@ -121,7 +122,7 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
|
||||
'honorificSuffix' => null
|
||||
],
|
||||
|
||||
'displayName' => null,
|
||||
'displayName' => AttributeMapping::eloquent("display_name"),
|
||||
'nickName' => null,
|
||||
'profileUrl' => null,
|
||||
'title' => AttributeMapping::eloquent('jobtitle'),
|
||||
|
||||
@@ -64,6 +64,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
'first_name',
|
||||
'jobtitle',
|
||||
'last_name',
|
||||
'display_name',
|
||||
'ldap_import',
|
||||
'locale',
|
||||
'location_id',
|
||||
@@ -103,6 +104,8 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
|
||||
protected $rules = [
|
||||
'first_name' => 'required|string|min:1|max:191',
|
||||
'last_name' => 'nullable|string|max:191',
|
||||
'display_name' => 'nullable|string|max:191',
|
||||
'username' => 'required|string|min:1|unique_undeleted|max:191',
|
||||
'email' => 'email|nullable|max:191',
|
||||
'password' => 'required|min:8',
|
||||
@@ -113,9 +116,9 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
'start_date' => 'nullable|date_format:Y-m-d',
|
||||
'end_date' => 'nullable|date_format:Y-m-d|after_or_equal:start_date',
|
||||
'autoassign_licenses' => 'boolean',
|
||||
'address' => 'max:191|nullable',
|
||||
'city' => 'max:191|nullable',
|
||||
'state' => 'min:2|max:191|nullable',
|
||||
'address' => 'nullable|string|max:191',
|
||||
'city' => 'nullable|string|max:191',
|
||||
'state' => 'nullable|string|max:191',
|
||||
'country' => 'min:2|max:191|nullable',
|
||||
'zip' => 'max:10|nullable',
|
||||
'vip' => 'boolean',
|
||||
@@ -132,15 +135,16 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
'address',
|
||||
'city',
|
||||
'country',
|
||||
'display_name',
|
||||
'email',
|
||||
'employee_num',
|
||||
'first_name',
|
||||
'jobtitle',
|
||||
'last_name',
|
||||
'locale',
|
||||
'mobile',
|
||||
'notes',
|
||||
'phone',
|
||||
'mobile',
|
||||
'state',
|
||||
'username',
|
||||
'website',
|
||||
@@ -157,7 +161,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
'department' => ['name'],
|
||||
'groups' => ['name'],
|
||||
'company' => ['name'],
|
||||
'manager' => ['first_name', 'last_name', 'username'],
|
||||
'manager' => ['first_name', 'last_name', 'username', 'display_name'],
|
||||
];
|
||||
|
||||
|
||||
@@ -196,8 +200,20 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This overrides the SnipeModel displayName accessor to return the full name if display_name is not set
|
||||
* @see SnipeModel::displayName()
|
||||
* @return Attribute
|
||||
*/
|
||||
|
||||
public function isAvatarExternal()
|
||||
protected function displayName(): Attribute
|
||||
{
|
||||
return Attribute:: make(
|
||||
get: fn(mixed $value) => $value ?? $this->getFullNameAttribute(),
|
||||
);
|
||||
}
|
||||
|
||||
public function isAvatarExternal() : bool
|
||||
{
|
||||
// Check if it's a google avatar or some external avatar
|
||||
if (Str::startsWith($this->avatar, ['http://', 'https://'])) {
|
||||
@@ -859,6 +875,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
{
|
||||
return $query->where('first_name', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('last_name', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('display_name', 'LIKE', '%' . $search . '%')
|
||||
->orWhereMultipleColumns(
|
||||
[
|
||||
'users.first_name',
|
||||
@@ -1068,6 +1085,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
->orWhere('users.jobtitle', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.employee_num', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.username', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.display_name', 'LIKE', '%' . $search . '%')
|
||||
->orwhereRaw('CONCAT(users.first_name," ",users.last_name) LIKE \''.$search.'%\'');
|
||||
|
||||
}
|
||||
|
||||
@@ -57,14 +57,14 @@ use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
return (new SlackMessage)
|
||||
->success()
|
||||
->content(class_basename(get_class($this->params['item'])).' Audited')
|
||||
->content(class_basename(get_class($this->params['item'])).' '.trans('general.audited'))
|
||||
->from(($this->settings->webhook_botname) ? $this->settings->webhook_botname : 'Snipe-Bot')
|
||||
->to($channel)
|
||||
->attachment(function ($attachment) {
|
||||
$item = $this->params['item'];
|
||||
$admin_user = $this->params['admin'];
|
||||
$fields = [
|
||||
'By' => '<'.$admin_user->present()->viewUrl().'|'.$admin_user->present()->fullName().'>',
|
||||
'By' => '<'.$admin_user->present()->viewUrl().'|'.$admin_user->display_name.'>',
|
||||
];
|
||||
array_key_exists('note', $this->params) && $fields['Notes'] = $this->params['note'];
|
||||
array_key_exists('location', $this->params) && $fields['Location'] = $this->params['location'];
|
||||
@@ -76,22 +76,22 @@ use NotificationChannels\MicrosoftTeams\MicrosoftTeamsMessage;
|
||||
|
||||
public static function toMicrosoftTeams($params)
|
||||
{
|
||||
$item = $params['item'];
|
||||
$admin_user = $params['admin'];
|
||||
$note = $params['note'];
|
||||
$location = $params['location'];
|
||||
$item = $params['item'] ?? null;
|
||||
$admin_user = $params['admin'] ?? null;
|
||||
$note = $params['note'] ?? '';
|
||||
$location = $params['location'] ?? '';
|
||||
$setting = Setting::getSettings();
|
||||
|
||||
if(!Str::contains($setting->webhook_endpoint, 'workflows')) {
|
||||
return MicrosoftTeamsMessage::create()
|
||||
->to($setting->webhook_endpoint)
|
||||
->type('success')
|
||||
->title(class_basename(get_class($params['item'])) . ' Audited')
|
||||
->title(class_basename(get_class($params['item'])) .' '.trans('general.audited'))
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(trans('mail.asset'), $item)
|
||||
->fact(trans('general.administrator'), $admin_user->present()->viewUrl() . '|' . $admin_user->present()->fullName());
|
||||
->fact(trans('general.administrator'), $admin_user->present()->viewUrl() . '|' . $admin_user->display_name);
|
||||
}
|
||||
$message = class_basename(get_class($params['item'])) . ' Audited By '.$admin_user->present()->fullName();
|
||||
$message = class_basename(get_class($params['item'])) . ' Audited By '.$admin_user->display_name;
|
||||
$details = [
|
||||
trans('mail.asset') => htmlspecialchars_decode($item->present()->name),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
|
||||
@@ -73,8 +73,8 @@ class CheckinAccessoryNotification extends Notification
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
|
||||
$fields = [
|
||||
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
@@ -109,7 +109,7 @@ class CheckinAccessoryNotification extends Notification
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle')
|
||||
->fact(trans('mail.checked_into'), $item->location->name ? $item->location->name : '')
|
||||
->fact(trans('mail.Accessory_Checkin_Notification')." by ", $admin->present()->fullName())
|
||||
->fact(trans('mail.Accessory_Checkin_Notification')." by ", $admin->display_name)
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
@@ -118,7 +118,7 @@ class CheckinAccessoryNotification extends Notification
|
||||
$details = [
|
||||
trans('mail.accessory_name') => htmlspecialchars_decode($item->present()->name),
|
||||
trans('mail.checked_into') => $item->location->name ? $item->location->name : '',
|
||||
trans('mail.Accessory_Checkin_Notification'). ' by' => $admin->present()->fullName(),
|
||||
trans('mail.Accessory_Checkin_Notification'). ' by' => $admin->display_name,
|
||||
trans('admin/consumables/general.remaining')=> $item->numRemaining(),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
|
||||
@@ -78,7 +78,7 @@ class CheckinAssetNotification extends Notification
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
|
||||
$fields = [
|
||||
trans('general.administrator') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
trans('general.administrator') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
|
||||
trans('general.status') => $item->assetstatus?->name,
|
||||
trans('general.location') => ($item->location) ? $item->location->name : '',
|
||||
];
|
||||
@@ -116,7 +116,7 @@ class CheckinAssetNotification extends Notification
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityText')
|
||||
->fact(trans('mail.checked_into'), ($item->location) ? $item->location->name : '')
|
||||
->fact(trans('mail.Asset_Checkin_Notification') . " by ", $admin->present()->fullName())
|
||||
->fact(trans('mail.Asset_Checkin_Notification') . " by ", $admin->display_name)
|
||||
->fact(trans('admin/hardware/form.status'), $item->assetstatus?->name)
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
@@ -126,7 +126,7 @@ class CheckinAssetNotification extends Notification
|
||||
$details = [
|
||||
trans('mail.asset') => htmlspecialchars_decode($item->present()->name),
|
||||
trans('mail.checked_into') => ($item->location) ? $item->location->name : '',
|
||||
trans('mail.Asset_Checkin_Notification')." by " => $admin->present()->fullName(),
|
||||
trans('mail.Asset_Checkin_Notification')." by " => $admin->display_name,
|
||||
trans('admin/hardware/form.status') => $item->assetstatus?->name,
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
|
||||
@@ -76,8 +76,8 @@ class CheckinComponentNotification extends Notification
|
||||
|
||||
if ($admin) {
|
||||
$fields = [
|
||||
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
@@ -90,7 +90,7 @@ class CheckinComponentNotification extends Notification
|
||||
|
||||
} else {
|
||||
$fields = [
|
||||
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
'To' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
'By' => 'CLI tool',
|
||||
];
|
||||
}
|
||||
@@ -119,16 +119,16 @@ class CheckinComponentNotification extends Notification
|
||||
->title(trans('mail.Component_checkin_notification'))
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'header')
|
||||
->fact(trans('mail.Component_checkin_notification')." by ", $admin->present()->fullName() ?: 'CLI tool')
|
||||
->fact(trans('mail.checkedin_from'), $target->present()->fullName())
|
||||
->fact(trans('mail.Component_checkin_notification')." by ", $admin->display_name ?: 'CLI tool')
|
||||
->fact(trans('mail.checkedin_from'), $target->display_name)
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
|
||||
$message = trans('mail.Component_checkin_notification');
|
||||
$details = [
|
||||
trans('mail.checkedin_from')=> $target->present()->fullName(),
|
||||
trans('mail.Component_checkin_notification')." by " => $admin->present()->fullName() ?: 'CLI tool',
|
||||
trans('mail.checkedin_from')=> $target->display_name,
|
||||
trans('mail.Component_checkin_notification')." by " => $admin->display_name ?: 'CLI tool',
|
||||
trans('admin/consumables/general.remaining') => $item->numRemaining(),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
@@ -153,7 +153,7 @@ class CheckinComponentNotification extends Notification
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.checkedin_from') ?: '',
|
||||
$target->present()->fullName() ?: '',
|
||||
$target->display_name ?: '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
|
||||
)
|
||||
->onClick(route('components.show', $item->id))
|
||||
|
||||
@@ -77,8 +77,8 @@ class CheckinLicenseSeatNotification extends Notification
|
||||
|
||||
if ($admin) {
|
||||
$fields = [
|
||||
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
trans('general.from') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
@@ -91,7 +91,7 @@ class CheckinLicenseSeatNotification extends Notification
|
||||
|
||||
} else {
|
||||
$fields = [
|
||||
'To' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
'To' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
'By' => 'CLI tool',
|
||||
];
|
||||
}
|
||||
@@ -120,17 +120,17 @@ class CheckinLicenseSeatNotification extends Notification
|
||||
->title(trans('mail.License_Checkin_Notification'))
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'header')
|
||||
->fact(trans('mail.License_Checkin_Notification')." by ", $admin->present()->fullName() ?: 'CLI tool')
|
||||
->fact(trans('mail.checkedin_from'), $target->present()->fullName())
|
||||
->fact(trans('mail.License_Checkin_Notification')." by ", $admin->display_name ?: 'CLI tool')
|
||||
->fact(trans('mail.checkedin_from'), $target->display_name)
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->availCount()->count())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
|
||||
$message = trans('mail.License_Checkin_Notification');
|
||||
$details = [
|
||||
trans('mail.checkedin_from')=> $target->present()->fullName(),
|
||||
trans('mail.checkedin_from')=> $target->display_name,
|
||||
trans('mail.license_for') => htmlspecialchars_decode($item->present()->name),
|
||||
trans('mail.License_Checkin_Notification')." by " => $admin->present()->fullName() ?: 'CLI tool',
|
||||
trans('mail.License_Checkin_Notification')." by " => $admin->display_name ?: 'CLI tool',
|
||||
trans('admin/consumables/general.remaining') => $item->availCount()->count(),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
@@ -155,7 +155,7 @@ class CheckinLicenseSeatNotification extends Notification
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.checkedin_from') ?: '',
|
||||
$target->present()->fullName() ?: '',
|
||||
$target->display_name ?: '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->availCount()->count(),
|
||||
)
|
||||
->onClick(route('licenses.show', $item->id))
|
||||
|
||||
@@ -100,8 +100,8 @@ class CheckoutAccessoryNotification extends Notification
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
|
||||
$fields = [
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
@@ -140,7 +140,7 @@ class CheckoutAccessoryNotification extends Notification
|
||||
->fact(trans('mail.assigned_to'), $target->present()->name)
|
||||
->fact(trans('general.qty'), $this->checkout_qty)
|
||||
->fact(trans('mail.checkedout_from'), $item->location->name ? $item->location->name : '')
|
||||
->fact(trans('mail.Accessory_Checkout_Notification') . " by ", $admin->present()->fullName())
|
||||
->fact(trans('mail.Accessory_Checkout_Notification') . " by ", $admin->display_name)
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
@@ -151,7 +151,7 @@ class CheckoutAccessoryNotification extends Notification
|
||||
trans('mail.accessory_name') => htmlspecialchars_decode($item->present()->name),
|
||||
trans('general.qty') => $this->checkout_qty,
|
||||
trans('mail.checkedout_from') => $item->location->name ? $item->location->name : '',
|
||||
trans('mail.Accessory_Checkout_Notification'). ' by' => $admin->present()->fullName(),
|
||||
trans('mail.Accessory_Checkout_Notification'). ' by' => $admin->display_name,
|
||||
trans('admin/consumables/general.remaining')=> $item->numRemaining(),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
|
||||
@@ -93,8 +93,8 @@ class CheckoutAssetNotification extends Notification
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
|
||||
$fields = [
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
@@ -135,7 +135,7 @@ class CheckoutAssetNotification extends Notification
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(trans('mail.assigned_to'), $target->present()->name)
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityText')
|
||||
->fact(trans('mail.Asset_Checkout_Notification') . " by ", $admin->present()->fullName())
|
||||
->fact(trans('mail.Asset_Checkout_Notification') . " by ", $admin->display_name)
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
|
||||
@@ -143,7 +143,7 @@ class CheckoutAssetNotification extends Notification
|
||||
$details = [
|
||||
trans('mail.assigned_to') => $target->present()->name,
|
||||
trans('mail.asset') => htmlspecialchars_decode($item->present()->name),
|
||||
trans('mail.Asset_Checkout_Notification'). ' by' => $admin->present()->fullName(),
|
||||
trans('mail.Asset_Checkout_Notification'). ' by' => $admin->display_name,
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
return array($message, $details);
|
||||
|
||||
@@ -80,8 +80,8 @@ class CheckoutComponentNotification extends Notification
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
|
||||
$fields = [
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
@@ -117,17 +117,17 @@ class CheckoutComponentNotification extends Notification
|
||||
->title(trans('mail.Component_checkout_notification'))
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle')
|
||||
->fact(trans('mail.Component_checkout_notification')." by ", $admin->present()->fullName())
|
||||
->fact(trans('mail.assigned_to'), $target->present()->fullName())
|
||||
->fact(trans('mail.Component_checkout_notification')." by ", $admin->display_name)
|
||||
->fact(trans('mail.assigned_to'), $target->display_name)
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
|
||||
$message = trans('mail.Component_checkout_notification');
|
||||
$details = [
|
||||
trans('mail.assigned_to') => $target->present()->fullName(),
|
||||
trans('mail.assigned_to') => $target->display_name,
|
||||
trans('mail.item') => htmlspecialchars_decode($item->present()->name),
|
||||
trans('mail.Component_checkout_notification').' by' => $admin->present()->fullName(),
|
||||
trans('mail.Component_checkout_notification').' by' => $admin->display_name,
|
||||
trans('admin/consumables/general.remaining') => $item->numRemaining(),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
@@ -152,7 +152,7 @@ class CheckoutComponentNotification extends Notification
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.assigned_to') ?: '',
|
||||
$target->present()->fullName() ?: '',
|
||||
$target->display_name ?: '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
|
||||
)
|
||||
->onClick(route('api.assets.show', $target->id))
|
||||
|
||||
@@ -80,8 +80,8 @@ class CheckoutConsumableNotification extends Notification
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
|
||||
$fields = [
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
@@ -117,17 +117,17 @@ class CheckoutConsumableNotification extends Notification
|
||||
->title(trans('mail.Consumable_checkout_notification'))
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle')
|
||||
->fact(trans('mail.Consumable_checkout_notification')." by ", $admin->present()->fullName())
|
||||
->fact(trans('mail.assigned_to'), $target->present()->fullName())
|
||||
->fact(trans('mail.Consumable_checkout_notification')." by ", $admin->display_name)
|
||||
->fact(trans('mail.assigned_to'), $target->display_name)
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->numRemaining())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
|
||||
$message = trans('mail.Consumable_checkout_notification');
|
||||
$details = [
|
||||
trans('mail.assigned_to') => $target->present()->fullName(),
|
||||
trans('mail.assigned_to') => $target->display_name,
|
||||
trans('mail.item') => htmlspecialchars_decode($item->present()->name),
|
||||
trans('mail.Consumable_checkout_notification').' by' => $admin->present()->fullName(),
|
||||
trans('mail.Consumable_checkout_notification').' by' => $admin->display_name,
|
||||
trans('admin/consumables/general.remaining') => $item->numRemaining(),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
@@ -152,7 +152,7 @@ class CheckoutConsumableNotification extends Notification
|
||||
Section::create(
|
||||
KeyValue::create(
|
||||
trans('mail.assigned_to') ?: '',
|
||||
$target->present()->fullName() ?: '',
|
||||
$target->display_name ?: '',
|
||||
trans('admin/consumables/general.remaining').': '.$item->numRemaining(),
|
||||
)
|
||||
->onClick(route('users.show', $target->id))
|
||||
|
||||
@@ -78,8 +78,8 @@ class CheckoutLicenseSeatNotification extends Notification
|
||||
$channel = ($this->settings->webhook_channel) ? $this->settings->webhook_channel : '';
|
||||
|
||||
$fields = [
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->present()->fullName().'>',
|
||||
trans('general.to') => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
trans('general.by') => '<'.$admin->present()->viewUrl().'|'.$admin->display_name.'>',
|
||||
];
|
||||
|
||||
if ($item->location) {
|
||||
@@ -115,17 +115,17 @@ class CheckoutLicenseSeatNotification extends Notification
|
||||
->title(trans('mail.License_Checkout_Notification'))
|
||||
->addStartGroupToSection('activityText')
|
||||
->fact(htmlspecialchars_decode($item->present()->name), '', 'activityTitle')
|
||||
->fact(trans('mail.License_Checkout_Notification')." by ", $admin->present()->fullName())
|
||||
->fact(trans('mail.assigned_to'), $target->present()->fullName())
|
||||
->fact(trans('mail.License_Checkout_Notification')." by ", $admin->display_name)
|
||||
->fact(trans('mail.assigned_to'), $target->display_name)
|
||||
->fact(trans('admin/consumables/general.remaining'), $item->availCount()->count())
|
||||
->fact(trans('mail.notes'), $note ?: '');
|
||||
}
|
||||
|
||||
$message = trans('mail.License_Checkout_Notification');
|
||||
$details = [
|
||||
trans('mail.assigned_to') => $target->present()->fullName(),
|
||||
trans('mail.assigned_to') => $target->display_name,
|
||||
trans('mail.license_for') => htmlspecialchars_decode($item->present()->name),
|
||||
trans('mail.License_Checkout_Notification').' by' => $admin->present()->fullName(),
|
||||
trans('mail.License_Checkout_Notification').' by' => $admin->display_name,
|
||||
trans('admin/consumables/general.remaining') => $item->availCount()->count(),
|
||||
trans('mail.notes') => $note ?: '',
|
||||
];
|
||||
|
||||
@@ -79,7 +79,7 @@ class RequestAssetCancelation extends Notification
|
||||
|
||||
$fields = [
|
||||
'QTY' => $qty,
|
||||
'Canceled By' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
'Canceled By' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
];
|
||||
|
||||
if (($this->expected_checkin) && ($this->expected_checkin != '')) {
|
||||
|
||||
@@ -78,7 +78,7 @@ class RequestAssetNotification extends Notification
|
||||
|
||||
$fields = [
|
||||
'QTY' => $qty,
|
||||
'Requested By' => '<'.$target->present()->viewUrl().'|'.$target->present()->fullName().'>',
|
||||
'Requested By' => '<'.$target->present()->viewUrl().'|'.$target->display_name.'>',
|
||||
];
|
||||
|
||||
return (new SlackMessage)
|
||||
|
||||
@@ -53,6 +53,7 @@ class LicensePresenter extends Presenter
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/licenses/form.to_email'),
|
||||
'formatter' => 'emailFormatter',
|
||||
], [
|
||||
'field' => 'license_name',
|
||||
'searchable' => true,
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Presenters;
|
||||
|
||||
use App\Models\SnipeModel;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
|
||||
abstract class Presenter
|
||||
{
|
||||
@@ -69,10 +70,30 @@ abstract class Presenter
|
||||
return '';
|
||||
}
|
||||
|
||||
public function name()
|
||||
{
|
||||
return $this->model->name;
|
||||
}
|
||||
// public function name()
|
||||
// {
|
||||
// return $this->model->name;
|
||||
// }
|
||||
//
|
||||
// public function display_name()
|
||||
// {
|
||||
// return $this->model->display_name;
|
||||
// }
|
||||
|
||||
|
||||
// protected function displayName(): Attribute
|
||||
// {
|
||||
// // This override should only kick in if the model has a display_name prope
|
||||
// if ($this->getRawOriginal('display_name')) {
|
||||
// return Attribute:: make (
|
||||
// get: fn(mixed $value) => 'Poop:'.$this->display_name
|
||||
// );
|
||||
// }
|
||||
//
|
||||
// return Attribute:: make(
|
||||
// get: fn(mixed $value) => 'Fart: '.$this->name,
|
||||
// );
|
||||
// }
|
||||
|
||||
public function __get($property)
|
||||
{
|
||||
@@ -80,7 +101,7 @@ abstract class Presenter
|
||||
return $this->{$property}();
|
||||
}
|
||||
|
||||
return e($this->model->{$property});
|
||||
return $this->model->{$property};
|
||||
}
|
||||
|
||||
public function __call($method, $args)
|
||||
|
||||
@@ -79,6 +79,14 @@ class UserPresenter extends Presenter
|
||||
'visible' => false,
|
||||
'formatter' => 'usersLinkFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'display_name',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('admin/users/table.display_name'),
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
'field' => 'jobtitle',
|
||||
'searchable' => true,
|
||||
@@ -191,6 +199,7 @@ class UserPresenter extends Presenter
|
||||
'visible' => true,
|
||||
'formatter' => 'usernameRoleLinkFormatter',
|
||||
],
|
||||
|
||||
[
|
||||
'field' => 'employee_num',
|
||||
'searchable' => true,
|
||||
@@ -447,20 +456,23 @@ class UserPresenter extends Presenter
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public function fullName()
|
||||
{
|
||||
return html_entity_decode($this->first_name.' '.$this->last_name, ENT_QUOTES | ENT_XML1, 'UTF-8');
|
||||
}
|
||||
// public function fullName()
|
||||
// {
|
||||
// if ($this->display_name) {
|
||||
// return 'kjdfh'.html_entity_decode($this->display_name, ENT_QUOTES | ENT_XML1, 'UTF-8');
|
||||
// }
|
||||
// return 'roieuoe'.html_entity_decode($this->first_name.' '.$this->last_name, ENT_QUOTES | ENT_XML1, 'UTF-8');
|
||||
// }
|
||||
|
||||
/**
|
||||
* Standard accessor.
|
||||
* @TODO Remove presenter::fullName() entirely?
|
||||
* @return string
|
||||
*/
|
||||
public function name()
|
||||
{
|
||||
return $this->fullName();
|
||||
}
|
||||
// /**
|
||||
// * Standard accessor.
|
||||
// * @TODO Remove presenter::fullName() entirely?
|
||||
// * @return string
|
||||
// */
|
||||
// public function name()
|
||||
// {
|
||||
// return $this->fullName();
|
||||
// }
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -74,12 +74,12 @@ class BreadcrumbsServiceProvider extends ServiceProvider
|
||||
|
||||
Breadcrumbs::for('hardware.show', fn (Trail $trail, Asset $asset) =>
|
||||
$trail->parent('hardware.index', route('hardware.index'))
|
||||
->push($asset->present()->fullName(), route('hardware.show', $asset))
|
||||
->push($asset->display_name, route('hardware.show', $asset))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('hardware.edit', fn (Trail $trail, Asset $asset) =>
|
||||
$trail->parent('hardware.index', route('hardware.index'))
|
||||
->push($asset->present()->fullName(), route('hardware.show', $asset))
|
||||
->push($asset->display_name, route('hardware.show', $asset))
|
||||
->push(trans('admin/hardware/general.edit'))
|
||||
);
|
||||
|
||||
@@ -579,7 +579,7 @@ class BreadcrumbsServiceProvider extends ServiceProvider
|
||||
|
||||
Breadcrumbs::for('users.show', fn (Trail $trail, User $user) =>
|
||||
$trail->parent('users.index', route('users.index'))
|
||||
->push($user->getFullNameAttribute() ?? 'Missing Username!', route('users.show', $user))
|
||||
->push($user->display_name ?? 'Missing Username!', route('users.show', $user))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('users.edit', fn (Trail $trail, User $user) =>
|
||||
|
||||
@@ -207,7 +207,7 @@ return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Require SAML Login
|
||||
| Require SAML Login
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| Disable the ability to login via form login, and disables the 'nosaml'
|
||||
@@ -220,6 +220,23 @@ return [
|
||||
|
||||
'require_saml' => env('REQUIRE_SAML', false),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| SAML KEYS
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This is the size of the keys used by openssl_pkey_new for SAML authentication.
|
||||
| The default is 2048 bits, but this can be changed to 3072 or 4096 bits
|
||||
| for higher security. Note that this will increase the time it takes to
|
||||
| generate the keys, so it is not recommended to set this to a very high value
|
||||
| unless you have a specific need for it.
|
||||
|
|
||||
| The European Commission now requires at least 3072-bit keys for new SAML certificates
|
||||
| @link https://github.com/grokability/snipe-it/issues/17386
|
||||
*/
|
||||
|
||||
'saml_key_size' => env('SAML_KEY_SIZE', 2048),
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
@@ -123,6 +123,9 @@ $config['allowed_upload_extensions_array'] = [
|
||||
'mov',
|
||||
'mp3',
|
||||
'mp4',
|
||||
'odp',
|
||||
'ods',
|
||||
'odt',
|
||||
'ogg',
|
||||
'pdf',
|
||||
'png',
|
||||
@@ -140,12 +143,15 @@ $config['allowed_upload_extensions_array'] = [
|
||||
];
|
||||
|
||||
|
||||
|
||||
// https://developer.mozilla.org/en-US/docs/Web/HTTP/Guides/MIME_types/Common_types
|
||||
$config['allowed_upload_mimetypes_array'] = [
|
||||
'application/json',
|
||||
'application/msword',
|
||||
'application/pdf',
|
||||
'application/vnd.ms-excel',
|
||||
'application/vnd.oasis.opendocument.presentation',
|
||||
'application/vnd.oasis.opendocument.spreadsheet',
|
||||
'application/vnd.oasis.opendocument.text',
|
||||
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
|
||||
'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
|
||||
'application/x-rar-compressed',
|
||||
|
||||
@@ -84,6 +84,28 @@ class ActionlogFactory extends Factory
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* This sets up an ActionLog representing a manually added note tied to an Asset,
|
||||
* with an optional User as the creator. If no User is provided, one is generated.
|
||||
*
|
||||
* @param User|null $user Optional user to associate as the creator of the note.
|
||||
* @return \Illuminate\Database\Eloquent\Factories\Factory<ActionLog>
|
||||
*/
|
||||
public function assetNote(?User $user=null)
|
||||
{
|
||||
return $this
|
||||
->state(function () use ($user) {
|
||||
return [
|
||||
'action_type' => 'note added',
|
||||
'item_type' => Asset::class,
|
||||
'target_type' => 'asset',
|
||||
'note' => 'Factory-generated manual note',
|
||||
'created_by' => $user?->id ?? User::factory(),
|
||||
];
|
||||
})
|
||||
->for($user ?? User::factory(), 'user');
|
||||
}
|
||||
|
||||
public function licenseCheckoutToUser()
|
||||
{
|
||||
return $this->state(function () {
|
||||
|
||||
@@ -28,8 +28,9 @@ class UserFactory extends Factory
|
||||
'email' => $this->faker->safeEmail(),
|
||||
'employee_num' => $this->faker->numberBetween(3500, 35050),
|
||||
'first_name' => $this->faker->firstName(),
|
||||
'jobtitle' => $this->faker->jobTitle(),
|
||||
'last_name' => $this->faker->lastName(),
|
||||
'display_name' => null,
|
||||
'jobtitle' => $this->faker->jobTitle(),
|
||||
'locale' => 'en-US',
|
||||
'notes' => 'Created by DB seeder',
|
||||
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
if (!Schema::hasColumn('users', 'display_name')) {
|
||||
$table->text('display_name')->after('last_name')->nullable()->default(null);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('users', 'display_name')) {
|
||||
$table->dropColumn('display_name');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,59 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('categories', function (Blueprint $table) {
|
||||
$table->index(['deleted_at']);
|
||||
});
|
||||
Schema::table('accessories', function (Blueprint $table) {
|
||||
$table->index(['deleted_at','category_id']);
|
||||
});
|
||||
Schema::table('consumables', function (Blueprint $table) {
|
||||
$table->index(['deleted_at','category_id']);
|
||||
});
|
||||
Schema::table('components', function (Blueprint $table) {
|
||||
$table->index(['deleted_at','category_id']);
|
||||
});
|
||||
Schema::table('licenses', function (Blueprint $table) {
|
||||
$table->index(['deleted_at','category_id']);
|
||||
});
|
||||
Schema::table('models', function (Blueprint $table) {
|
||||
$table->index(['deleted_at','category_id']);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('categories', function (Blueprint $table) {
|
||||
$table->dropIndex(['deleted_at']);
|
||||
});
|
||||
Schema::table('accessories', function (Blueprint $table) {
|
||||
$table->dropIndex(['deleted_at','category_id']);
|
||||
});
|
||||
Schema::table('consumables', function (Blueprint $table) {
|
||||
$table->dropIndex(['deleted_at','category_id']);
|
||||
});
|
||||
Schema::table('components', function (Blueprint $table) {
|
||||
$table->dropIndex(['deleted_at','category_id']);
|
||||
});
|
||||
Schema::table('licenses', function (Blueprint $table) {
|
||||
$table->dropIndex(['deleted_at','category_id']);
|
||||
});
|
||||
Schema::table('models', function (Blueprint $table) {
|
||||
$table->dropIndex(['deleted_at','category_id']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,82 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
|
||||
if (!Schema::hasColumn('settings', 'ldap_display_name')) {
|
||||
$table->string('ldap_display_name', 191)->after('ldap_fname_field')->nullable()->default(null);
|
||||
}
|
||||
|
||||
if (!Schema::hasColumn('settings', 'ldap_zip')) {
|
||||
$table->string('ldap_zip', 191)->after('ldap_manager')->nullable()->default(null);
|
||||
}
|
||||
|
||||
if (!Schema::hasColumn('settings', 'ldap_state')) {
|
||||
$table->string('ldap_state', 191)->after('ldap_manager')->nullable()->default(null);
|
||||
}
|
||||
|
||||
if (!Schema::hasColumn('settings', 'ldap_city')) {
|
||||
$table->string('ldap_city', 191)->after('ldap_manager')->nullable()->default(null);
|
||||
}
|
||||
|
||||
if (!Schema::hasColumn('settings', 'ldap_address')) {
|
||||
$table->string('ldap_address', 191)->after('ldap_manager')->nullable()->default(null);
|
||||
}
|
||||
|
||||
if (!Schema::hasColumn('settings', 'ldap_mobile')) {
|
||||
$table->string('ldap_mobile', 191)->after('ldap_phone_field')->nullable()->default(null);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('settings', 'ldap_display_name')) {
|
||||
$table->dropColumn('ldap_display_name');
|
||||
}
|
||||
});
|
||||
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('settings', 'ldap_zip')) {
|
||||
$table->dropColumn('ldap_zip');
|
||||
}
|
||||
});
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('settings', 'ldap_address')) {
|
||||
$table->dropColumn('ldap_address');
|
||||
}
|
||||
});
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('settings', 'ldap_city')) {
|
||||
$table->dropColumn('ldap_city');
|
||||
}
|
||||
});
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('settings', 'ldap_state')) {
|
||||
$table->dropColumn('ldap_state');
|
||||
}
|
||||
});
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('settings', 'ldap_mobile')) {
|
||||
$table->dropColumn('ldap_mobile');
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('models', function (Blueprint $table) {
|
||||
$table->index(['created_at']);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('models', function (Blueprint $table) {
|
||||
$table->dropIndex(['created_at']);
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -1487,6 +1487,15 @@ caption.tableCaption {
|
||||
.popover.help-popover .popover-header {
|
||||
color: #000;
|
||||
}
|
||||
.visually-hidden {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: preserve;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=app.css.map*/
|
||||
File diff suppressed because one or more lines are too long
@@ -1108,6 +1108,15 @@ caption.tableCaption {
|
||||
.popover.help-popover .popover-header {
|
||||
color: #000;
|
||||
}
|
||||
.visually-hidden {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: preserve;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=overrides.css.map*/
|
||||
File diff suppressed because one or more lines are too long
18
public/css/dist/all.css
vendored
18
public/css/dist/all.css
vendored
@@ -22823,6 +22823,15 @@ caption.tableCaption {
|
||||
.popover.help-popover .popover-header {
|
||||
color: #000;
|
||||
}
|
||||
.visually-hidden {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: preserve;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=app.css.map*/
|
||||
@@ -24418,6 +24427,15 @@ caption.tableCaption {
|
||||
.popover.help-popover .popover-header {
|
||||
color: #000;
|
||||
}
|
||||
.visually-hidden {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
white-space: preserve;
|
||||
display: inline-block;
|
||||
}
|
||||
|
||||
|
||||
/*# sourceMappingURL=overrides.css.map*/
|
||||
18819
public/js/dist/all.js
vendored
18819
public/js/dist/all.js
vendored
File diff suppressed because it is too large
Load Diff
2
public/js/dist/all.js.map
vendored
2
public/js/dist/all.js.map
vendored
File diff suppressed because one or more lines are too long
@@ -1,9 +1,9 @@
|
||||
{
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=b4f9d0394ed0703585d495cf5995a169",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=76d88f0f91b852f7eecbce357ab5858b",
|
||||
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=42f97cd5b9ee7521b04a448e7fc16ac9",
|
||||
"/css/dist/skins/_all-skins.css": "/css/dist/skins/_all-skins.css?id=d81a7ed323f68a7c5e3e9115f7fb5404",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=81e3e83b8d669c69d443a21241184f2e",
|
||||
"/css/build/app.css": "/css/build/app.css?id=b34e2d41a3a0d0c949d813eabdc0204b",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=257e65d85ce9cf5a413065df1b131c03",
|
||||
"/css/build/app.css": "/css/build/app.css?id=a1136819126f6c7c3cd37861d69abb84",
|
||||
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=ee0ed88465dd878588ed044eefb67723",
|
||||
"/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=3d8a3d2035ea28aaad4a703c2646f515",
|
||||
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=3979929a3423ff35b96b1fc84299fdf3",
|
||||
@@ -19,7 +19,7 @@
|
||||
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=b2cd9f59d7e8587939ce27b2d3363d82",
|
||||
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=7277edd636cf46aa7786a4449ce0ead7",
|
||||
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=cbd06cc1d58197ccc81d4376bbaf0d28",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=ddd108d2798f64c3a47dc2e61760af12",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=4130f13eb82937aa7147bd89f93aaca5",
|
||||
"/css/dist/signature-pad.css": "/css/dist/signature-pad.css?id=6a89d3cd901305e66ced1cf5f13147f7",
|
||||
"/css/dist/signature-pad.min.css": "/css/dist/signature-pad.min.css?id=6a89d3cd901305e66ced1cf5f13147f7",
|
||||
"/js/select2/i18n/af.js": "/js/select2/i18n/af.js?id=4f6fcd73488ce79fae1b7a90aceaecde",
|
||||
|
||||
@@ -11,7 +11,7 @@ window.$ = jQuery
|
||||
itself
|
||||
*****************************************/
|
||||
|
||||
require('jquery-ui'); //should we export this to the window?
|
||||
require("jquery-ui/dist/jquery-ui")
|
||||
jQuery.fn.uitooltip = jQuery.fn.tooltip;
|
||||
require('bootstrap-less');
|
||||
require('select2');
|
||||
|
||||
@@ -1243,3 +1243,12 @@ caption.tableCaption {
|
||||
color: #000;
|
||||
}
|
||||
|
||||
.visually-hidden {
|
||||
width: 1px;
|
||||
height: 1px;
|
||||
margin: -1px;
|
||||
overflow: hidden;
|
||||
clip: rect(0,0,0,0);
|
||||
white-space: preserve;
|
||||
display: inline-block;
|
||||
}
|
||||
15
resources/lang/aa-ER/admin/asset_maintenances/form.php
Normal file
15
resources/lang/aa-ER/admin/asset_maintenances/form.php
Normal file
@@ -0,0 +1,15 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'select_type' => 'crwdns13392:0crwdne13392:0',
|
||||
'asset_maintenance_type' => 'crwdns11333:0crwdne11333:0',
|
||||
'title' => 'crwdns1354:0crwdne1354:0',
|
||||
'start_date' => 'crwdns11335:0crwdne11335:0',
|
||||
'completion_date' => 'crwdns11337:0crwdne11337:0',
|
||||
'cost' => 'crwdns1357:0crwdne1357:0',
|
||||
'is_warranty' => 'crwdns1358:0crwdne1358:0',
|
||||
'asset_maintenance_time' => 'crwdns11339:0crwdne11339:0',
|
||||
'notes' => 'crwdns1360:0crwdne1360:0',
|
||||
'update' => 'crwdns11341:0crwdne11341:0',
|
||||
'create' => 'crwdns11343:0crwdne11343:0'
|
||||
];
|
||||
16
resources/lang/aa-ER/admin/asset_maintenances/general.php
Normal file
16
resources/lang/aa-ER/admin/asset_maintenances/general.php
Normal file
@@ -0,0 +1,16 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
'asset_maintenances' => 'crwdns1363:0crwdne1363:0',
|
||||
'edit' => 'crwdns1364:0crwdne1364:0',
|
||||
'delete' => 'crwdns1365:0crwdne1365:0',
|
||||
'view' => 'crwdns1366:0crwdne1366:0',
|
||||
'repair' => 'crwdns1367:0crwdne1367:0',
|
||||
'maintenance' => 'crwdns1368:0crwdne1368:0',
|
||||
'upgrade' => 'crwdns1369:0crwdne1369:0',
|
||||
'calibration' => 'crwdns5812:0crwdne5812:0',
|
||||
'software_support' => 'crwdns5814:0crwdne5814:0',
|
||||
'hardware_support' => 'crwdns5816:0crwdne5816:0',
|
||||
'configuration_change' => 'crwdns10530:0crwdne10530:0',
|
||||
'pat_test' => 'crwdns10532:0crwdne10532:0',
|
||||
];
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user