Compare commits
309 Commits
v8
...
fix_s3_bac
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
93014d7f34 | ||
|
|
759e3794df | ||
|
|
c50b14763f | ||
|
|
369a68fe57 | ||
|
|
83855d44d0 | ||
|
|
6f847294ed | ||
|
|
d556d1c6e7 | ||
|
|
3bb94e98f0 | ||
|
|
8f5f6f3502 | ||
|
|
b3792bfa00 | ||
|
|
40f7257723 | ||
|
|
8486256142 | ||
|
|
7f36750e33 | ||
|
|
de046db106 | ||
|
|
eb1d27a5bc | ||
|
|
cc0b9f404a | ||
|
|
70332696c6 | ||
|
|
7a9b5d61b0 | ||
|
|
5876259893 | ||
|
|
8755c54edc | ||
|
|
014f3b7652 | ||
|
|
3a2579b205 | ||
|
|
149474bfe3 | ||
|
|
b2b768dede | ||
|
|
a9ed9e2a7f | ||
|
|
ce8523b00a | ||
|
|
7076a68d35 | ||
|
|
112112d258 | ||
|
|
3928c8afe9 | ||
|
|
23ce54e80c | ||
|
|
646e3e8df5 | ||
|
|
30c4e9dbf7 | ||
|
|
27fc30a881 | ||
|
|
8ac7cda4ee | ||
|
|
6f04d314a8 | ||
|
|
1051b1d16d | ||
|
|
115bb94704 | ||
|
|
25807cc62f | ||
|
|
cd1d1b2d3e | ||
|
|
6dcd3bfd30 | ||
|
|
b8799f8038 | ||
|
|
a0dc056da8 | ||
|
|
27aeb518ff | ||
|
|
dc619bb0dc | ||
|
|
245a16c377 | ||
|
|
de3c1d159f | ||
|
|
af6d9e4a00 | ||
|
|
8c8af3062e | ||
|
|
2ff47edb94 | ||
|
|
d923d29bad | ||
|
|
899119ae2d | ||
|
|
e031de8e49 | ||
|
|
a81c520d93 | ||
|
|
8352e81228 | ||
|
|
fd0174ff32 | ||
|
|
cc26aa02b2 | ||
|
|
616f3558dd | ||
|
|
d6e266cec1 | ||
|
|
31516d7f24 | ||
|
|
e79af255aa | ||
|
|
5b0d7f4064 | ||
|
|
2f6af10c5d | ||
|
|
afabda9235 | ||
|
|
1618c9ae8e | ||
|
|
5344ef4a1a | ||
|
|
16420b1e00 | ||
|
|
62f66e724e | ||
|
|
9b0ea51d35 | ||
|
|
992214fc66 | ||
|
|
93dab12461 | ||
|
|
ea0f105180 | ||
|
|
5b6da0c1e8 | ||
|
|
4d7655bbe1 | ||
|
|
5e3855ee5b | ||
|
|
e01226a174 | ||
|
|
f9ccf32af4 | ||
|
|
2c5170a218 | ||
|
|
15f842e2dc | ||
|
|
46b31dfe14 | ||
|
|
d88c79366c | ||
|
|
de330a47cd | ||
|
|
ecd7dc2094 | ||
|
|
510946e0eb | ||
|
|
37e4a13979 | ||
|
|
c73d64cdbc | ||
|
|
4a0410d969 | ||
|
|
668b9f8fb9 | ||
|
|
037d2d9e84 | ||
|
|
bce2007b97 | ||
|
|
09a5e5b1bd | ||
|
|
7b4f4b6b7f | ||
|
|
5c66334017 | ||
|
|
ae82051b73 | ||
|
|
c3a2e81afd | ||
|
|
18c7cbbbbb | ||
|
|
3718f08c72 | ||
|
|
b7821a69b6 | ||
|
|
8049f21068 | ||
|
|
8140110bf9 | ||
|
|
a4587f6322 | ||
|
|
163e19f1e9 | ||
|
|
8a40c3ecb4 | ||
|
|
d949a9689f | ||
|
|
27a7c6fd10 | ||
|
|
4d55a67628 | ||
|
|
9d453226bd | ||
|
|
cd26694767 | ||
|
|
a26cc2ced1 | ||
|
|
1fd81d17a3 | ||
|
|
134045f1ec | ||
|
|
b6b6a3eec7 | ||
|
|
b62714d702 | ||
|
|
271bcc66bf | ||
|
|
ced560daa9 | ||
|
|
b395c9130a | ||
|
|
ed46a757fa | ||
|
|
6a8a41b389 | ||
|
|
4800f4c853 | ||
|
|
c79ff49c85 | ||
|
|
e88bba51bb | ||
|
|
f97211f6cd | ||
|
|
027c2b3627 | ||
|
|
ee85a392e7 | ||
|
|
6c2d367124 | ||
|
|
982cfeca32 | ||
|
|
5fa4f85c20 | ||
|
|
43b8c0bf7b | ||
|
|
54b664d679 | ||
|
|
bf2355a297 | ||
|
|
2bf4ec0ae8 | ||
|
|
9555825a67 | ||
|
|
0bea07e2f9 | ||
|
|
22f7a9ddd4 | ||
|
|
77b417bcea | ||
|
|
76e3c00d2d | ||
|
|
77add8abbc | ||
|
|
b53957268a | ||
|
|
ba49fc554d | ||
|
|
e60462b751 | ||
|
|
a5009aa7df | ||
|
|
e589adbe80 | ||
|
|
0501c5f53c | ||
|
|
6a9247ba8a | ||
|
|
fcf84bf63f | ||
|
|
cebb9d034c | ||
|
|
dd2b570db5 | ||
|
|
2bee4532ec | ||
|
|
96248e0023 | ||
|
|
157801242d | ||
|
|
7b151cf692 | ||
|
|
50c88df4cc | ||
|
|
d87a6868cc | ||
|
|
201f487853 | ||
|
|
069860d65f | ||
|
|
afa7391080 | ||
|
|
07cf203018 | ||
|
|
5f561452d2 | ||
|
|
cbe04e8514 | ||
|
|
9b44dfd9b6 | ||
|
|
9abf3029ef | ||
|
|
19fb45f488 | ||
|
|
e983ee4d0f | ||
|
|
40acd48eff | ||
|
|
f5eedb8d23 | ||
|
|
172df0d220 | ||
|
|
c611cb5612 | ||
|
|
da77ddd447 | ||
|
|
c727633e6b | ||
|
|
10834cf638 | ||
|
|
42eda089e2 | ||
|
|
2434c82a75 | ||
|
|
1b9d046f5f | ||
|
|
a0a0727b5c | ||
|
|
917b9f0293 | ||
|
|
bb70250007 | ||
|
|
346aeeda71 | ||
|
|
84a29378cd | ||
|
|
0cd0abe8bb | ||
|
|
7db11dc12b | ||
|
|
e0221301ff | ||
|
|
b0fa059a28 | ||
|
|
3fb00a9fa9 | ||
|
|
3ef8b047ba | ||
|
|
7a77de6ffe | ||
|
|
5e85891b10 | ||
|
|
934da0f630 | ||
|
|
cca46ea9e0 | ||
|
|
bde034593b | ||
|
|
7e1295bac7 | ||
|
|
d1cc0fcfac | ||
|
|
056fbefb16 | ||
|
|
83a848980f | ||
|
|
7b930357e4 | ||
|
|
bdab052f40 | ||
|
|
2d1e9b237f | ||
|
|
1cff49116e | ||
|
|
38c5f23a52 | ||
|
|
c6bee0c47a | ||
|
|
ae7d7f7d22 | ||
|
|
96ab828cec | ||
|
|
43f679a554 | ||
|
|
f1bf9fcf5c | ||
|
|
992b4c7d86 | ||
|
|
39bb2c2adb | ||
|
|
41129829e6 | ||
|
|
44503fc423 | ||
|
|
0190ccea27 | ||
|
|
5b63eb5a15 | ||
|
|
54cc427ef5 | ||
|
|
e0beed0fa3 | ||
|
|
d4b24e5e57 | ||
|
|
671b64bc6b | ||
|
|
75db0d9e66 | ||
|
|
b891992351 | ||
|
|
ddb72bf4d0 | ||
|
|
6f071722a2 | ||
|
|
be9bd93588 | ||
|
|
44a7bdbfb5 | ||
|
|
0341335d14 | ||
|
|
76f038d142 | ||
|
|
3150ad50c9 | ||
|
|
80394ef788 | ||
|
|
8a70f09dd3 | ||
|
|
a275391557 | ||
|
|
eaacf29d57 | ||
|
|
441fdaa54a | ||
|
|
759c8c8f5c | ||
|
|
6242296930 | ||
|
|
d330ef9919 | ||
|
|
0708af7d07 | ||
|
|
a534b488b2 | ||
|
|
3171c1b1c9 | ||
|
|
2f2b879d98 | ||
|
|
039f483ec8 | ||
|
|
7f665e0005 | ||
|
|
292819afa5 | ||
|
|
7a94b09017 | ||
|
|
6b46d12d67 | ||
|
|
e264907157 | ||
|
|
32b89e937c | ||
|
|
0e1dc8745c | ||
|
|
129d44cc70 | ||
|
|
11b746d801 | ||
|
|
545445d584 | ||
|
|
4d72fd8667 | ||
|
|
fca62a14f9 | ||
|
|
c8f2d9806a | ||
|
|
1ee5f28fca | ||
|
|
24a17b09a5 | ||
|
|
a617c0545e | ||
|
|
eb7e24eeb0 | ||
|
|
22c58678c4 | ||
|
|
4beaf6b3ec | ||
|
|
4c1856b91f | ||
|
|
9d299340da | ||
|
|
457228d033 | ||
|
|
63f4e3cc89 | ||
|
|
cd7135ea77 | ||
|
|
347eb2bdee | ||
|
|
ecc0e76e7b | ||
|
|
35a89de6dd | ||
|
|
82d8e1b0a9 | ||
|
|
5a7ffa5664 | ||
|
|
55abd242f2 | ||
|
|
217d65f64c | ||
|
|
fa20eb4965 | ||
|
|
560311b883 | ||
|
|
3954ff20b4 | ||
|
|
989082d719 | ||
|
|
644527c5a6 | ||
|
|
f7d213052a | ||
|
|
972bd1ef83 | ||
|
|
cf0ce1c5ea | ||
|
|
3d69721af0 | ||
|
|
1995e1399e | ||
|
|
79d1147f20 | ||
|
|
53c084c6c0 | ||
|
|
c165e6f400 | ||
|
|
25215fd3c9 | ||
|
|
4c43a06eee | ||
|
|
25c8449e86 | ||
|
|
13e1f4a127 | ||
|
|
ed96fd766c | ||
|
|
77635c3737 | ||
|
|
b937b7e767 | ||
|
|
7cbb3f7e07 | ||
|
|
7e9c564d0b | ||
|
|
fc88b2487f | ||
|
|
e94ee48f74 | ||
|
|
6a4a5d1380 | ||
|
|
ab9e9b66d2 | ||
|
|
c15c338ffd | ||
|
|
d1197d015c | ||
|
|
ce31ce477e | ||
|
|
78f9292555 | ||
|
|
4e7c6bd2cf | ||
|
|
70aed45bfe | ||
|
|
e2805f4033 | ||
|
|
d254a40e0a | ||
|
|
fdcb891cbb | ||
|
|
16d322d70e | ||
|
|
2163312997 | ||
|
|
0dfb71cfe5 | ||
|
|
31097bdc37 | ||
|
|
e733d2a5d0 | ||
|
|
6a35fa7ba3 | ||
|
|
370666b5bd | ||
|
|
99526cfc2c | ||
|
|
bdb0e6c2a3 |
@@ -3271,6 +3271,33 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "addex12",
|
||||
"name": "Adugna Gizaw",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/18550946?v=4",
|
||||
"profile": "https://orbalia.pythonanywhere.com/",
|
||||
"contributions": [
|
||||
"translation"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jostrander",
|
||||
"name": "Jesse Ostrander",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/760989?v=4",
|
||||
"profile": "https://github.com/jostrander",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "azmcnutt",
|
||||
"name": "James M",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/31522486?v=4",
|
||||
"profile": "https://github.com/azmcnutt",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -16,7 +16,7 @@ APP_DEBUG=true
|
||||
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
|
||||
APP_URL=http://localhost:8000
|
||||
APP_TIMEZONE='UTC'
|
||||
APP_LOCALE=en
|
||||
APP_LOCALE=en-US
|
||||
MAX_RESULTS=500
|
||||
|
||||
# --------------------------------------------
|
||||
|
||||
@@ -99,7 +99,7 @@ PASSPORT_COOKIE_NAME='snipeit_passport_token'
|
||||
COOKIE_DOMAIN=null
|
||||
SECURE_COOKIES=false
|
||||
API_TOKEN_EXPIRATION_YEARS=15
|
||||
BS_TABLE_STORAGE=cookieStorage
|
||||
BS_TABLE_STORAGE=localStorage
|
||||
BS_TABLE_DEEPLINK=true
|
||||
|
||||
# --------------------------------------------
|
||||
|
||||
4
.github/workflows/tests-mysql.yml
vendored
4
.github/workflows/tests-mysql.yml
vendored
@@ -25,9 +25,9 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-version:
|
||||
- "8.1"
|
||||
- "8.2"
|
||||
- "8.3"
|
||||
- "8.4"
|
||||
|
||||
name: PHP ${{ matrix.php-version }}
|
||||
|
||||
@@ -67,7 +67,7 @@ jobs:
|
||||
run: |
|
||||
php artisan key:generate
|
||||
php artisan migrate --force
|
||||
php artisan passport:install
|
||||
php artisan passport:install --no-interaction
|
||||
chmod -R 777 storage bootstrap/cache
|
||||
|
||||
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
||||
|
||||
5
.github/workflows/tests-postgres.yml
vendored
5
.github/workflows/tests-postgres.yml
vendored
@@ -21,9 +21,10 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-version:
|
||||
- "8.1"
|
||||
- "8.2"
|
||||
- "8.3"
|
||||
- "8.4"
|
||||
|
||||
|
||||
name: PHP ${{ matrix.php-version }}
|
||||
|
||||
@@ -64,7 +65,7 @@ jobs:
|
||||
run: |
|
||||
php artisan key:generate
|
||||
php artisan migrate --force
|
||||
php artisan passport:install
|
||||
php artisan passport:install --no-interaction
|
||||
chmod -R 777 storage bootstrap/cache
|
||||
|
||||
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
||||
|
||||
2
.github/workflows/tests-sqlite.yml
vendored
2
.github/workflows/tests-sqlite.yml
vendored
@@ -15,7 +15,7 @@ jobs:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-version:
|
||||
- "8.1.1"
|
||||
- "8.3"
|
||||
|
||||
name: PHP ${{ matrix.php-version }}
|
||||
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
"DOC2": "In other words, what you see locally are the requirements for your _current_ install",
|
||||
"DOC3": "Please don't rely on these versions for planning upgrades unless you've fetched the most recent version",
|
||||
"DOC4": "You should really just ignore it and run upgrade.php. Really",
|
||||
"php_min_version": "8.1.0",
|
||||
"php_max_major_minor": "8.3",
|
||||
"php_max_wontwork": "8.4.0",
|
||||
"current_snipeit_version": "7.0"
|
||||
"php_min_version": "8.2.0",
|
||||
"php_max_major_minor": "8.4",
|
||||
"php_max_wontwork": "8.5.0",
|
||||
"current_snipeit_version": "8.0"
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
| [<img src="https://avatars.githubusercontent.com/u/55590532?v=4" width="110px;"/><br /><sub>squintfox</sub>](https://github.com/squintfox)<br />[💻](https://github.com/snipe/snipe-it/commits?author=squintfox "Code") | [<img src="https://avatars.githubusercontent.com/u/1380084?v=4" width="110px;"/><br /><sub>Jeff Clay</sub>](https://github.com/jeffclay)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jeffclay "Code") | [<img src="https://avatars.githubusercontent.com/u/52716446?v=4" width="110px;"/><br /><sub>Phil J R</sub>](https://github.com/PP-JN-RL)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PP-JN-RL "Code") | [<img src="https://avatars.githubusercontent.com/u/1496725?v=4" width="110px;"/><br /><sub>i_virus</sub>](https://www.corelight.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chandanchowdhury "Code") | [<img src="https://avatars.githubusercontent.com/u/1020541?v=4" width="110px;"/><br /><sub>Paul Grime</sub>](https://github.com/gitgrimbo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=gitgrimbo "Code") | [<img src="https://avatars.githubusercontent.com/u/922815?v=4" width="110px;"/><br /><sub>Lee Porte</sub>](https://leeporte.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=LeePorte "Code") | [<img src="https://avatars.githubusercontent.com/u/23613427?v=4" width="110px;"/><br /><sub>BRYAN </sub>](https://github.com/bryanlopezinc)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Code") [⚠️](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Tests") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/64061710?v=4" width="110px;"/><br /><sub>U-H-T</sub>](https://github.com/U-H-T)<br />[💻](https://github.com/snipe/snipe-it/commits?author=U-H-T "Code") | [<img src="https://avatars.githubusercontent.com/u/5395363?v=4" width="110px;"/><br /><sub>Matt Tyree</sub>](https://github.com/Tyree)<br />[📖](https://github.com/snipe/snipe-it/commits?author=Tyree "Documentation") | [<img src="https://avatars.githubusercontent.com/u/292081?v=4" width="110px;"/><br /><sub>Florent Bervas</sub>](http://spoontux.net)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FlorentDotMe "Code") | [<img src="https://avatars.githubusercontent.com/u/4498077?v=4" width="110px;"/><br /><sub>Daniel Albertsen</sub>](https://ditscheri.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dbakan "Code") | [<img src="https://avatars.githubusercontent.com/u/100710244?v=4" width="110px;"/><br /><sub>r-xyz</sub>](https://github.com/r-xyz)<br />[💻](https://github.com/snipe/snipe-it/commits?author=r-xyz "Code") | [<img src="https://avatars.githubusercontent.com/u/47491036?v=4" width="110px;"/><br /><sub>Steven Mainor</sub>](https://github.com/DrekiDegga)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DrekiDegga "Code") | [<img src="https://avatars.githubusercontent.com/u/65785975?v=4" width="110px;"/><br /><sub>arne-kroeger</sub>](https://github.com/arne-kroeger)<br />[💻](https://github.com/snipe/snipe-it/commits?author=arne-kroeger "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/167117705?v=4" width="110px;"/><br /><sub>Glukose1</sub>](https://github.com/Glukose1)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Glukose1 "Code") | [<img src="https://avatars.githubusercontent.com/u/1197791?v=4" width="110px;"/><br /><sub>Scarzy</sub>](https://github.com/Scarzy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Scarzy "Code") | [<img src="https://avatars.githubusercontent.com/u/37372069?v=4" width="110px;"/><br /><sub>setpill</sub>](https://github.com/setpill)<br />[💻](https://github.com/snipe/snipe-it/commits?author=setpill "Code") | [<img src="https://avatars.githubusercontent.com/u/3755203?v=4" width="110px;"/><br /><sub>swift2512</sub>](https://github.com/swift2512)<br />[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aswift2512 "Bug reports") | [<img src="https://avatars.githubusercontent.com/u/6136439?v=4" width="110px;"/><br /><sub>Darren Rainey</sub>](https://darrenraineys.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=DarrenRainey "Code") | [<img src="https://avatars.githubusercontent.com/u/133033121?v=4" width="110px;"/><br /><sub>maciej-poleszczyk</sub>](https://github.com/maciej-poleszczyk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=maciej-poleszczyk "Code") | [<img src="https://avatars.githubusercontent.com/u/143394709?v=4" width="110px;"/><br /><sub>Sebastian Groß</sub>](https://github.com/sgross-emlix)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sgross-emlix "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/41107778?v=4" width="110px;"/><br /><sub>Anouar Touati</sub>](https://github.com/AnouarTouati)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AnouarTouati "Code") | [<img src="https://avatars.githubusercontent.com/u/25596663?v=4" width="110px;"/><br /><sub>aHVzY2g</sub>](https://github.com/aHVzY2g)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aHVzY2g "Code") | [<img src="https://avatars.githubusercontent.com/u/13408130?v=4" width="110px;"/><br /><sub>林博仁 Buo-ren Lin</sub>](https://brlin.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=brlin-tw "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/41107778?v=4" width="110px;"/><br /><sub>Anouar Touati</sub>](https://github.com/AnouarTouati)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AnouarTouati "Code") | [<img src="https://avatars.githubusercontent.com/u/25596663?v=4" width="110px;"/><br /><sub>aHVzY2g</sub>](https://github.com/aHVzY2g)<br />[💻](https://github.com/snipe/snipe-it/commits?author=aHVzY2g "Code") | [<img src="https://avatars.githubusercontent.com/u/13408130?v=4" width="110px;"/><br /><sub>林博仁 Buo-ren Lin</sub>](https://brlin.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=brlin-tw "Code") | [<img src="https://avatars.githubusercontent.com/u/18550946?v=4" width="110px;"/><br /><sub>Adugna Gizaw</sub>](https://orbalia.pythonanywhere.com/)<br />[🌍](#translation-addex12 "Translation") | [<img src="https://avatars.githubusercontent.com/u/760989?v=4" width="110px;"/><br /><sub>Jesse Ostrander</sub>](https://github.com/jostrander)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jostrander "Code") | [<img src="https://avatars.githubusercontent.com/u/31522486?v=4" width="110px;"/><br /><sub>James M</sub>](https://github.com/azmcnutt)<br />[💻](https://github.com/snipe/snipe-it/commits?author=azmcnutt "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
36
Dockerfile
36
Dockerfile
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:22.04
|
||||
FROM ubuntu:24.04
|
||||
LABEL maintainer="Brady Wetherington <bwetherington@grokability.com>"
|
||||
|
||||
# No need to add `apt-get clean` here, reference:
|
||||
@@ -14,16 +14,16 @@ RUN export DEBIAN_FRONTEND=noninteractive; \
|
||||
apt-utils \
|
||||
apache2 \
|
||||
apache2-bin \
|
||||
libapache2-mod-php8.1 \
|
||||
php8.1-curl \
|
||||
php8.1-ldap \
|
||||
php8.1-mysql \
|
||||
php8.1-gd \
|
||||
php8.1-xml \
|
||||
php8.1-mbstring \
|
||||
php8.1-zip \
|
||||
php8.1-bcmath \
|
||||
php8.1-redis \
|
||||
libapache2-mod-php8.3 \
|
||||
php8.3-curl \
|
||||
php8.3-ldap \
|
||||
php8.3-mysql \
|
||||
php8.3-gd \
|
||||
php8.3-xml \
|
||||
php8.3-mbstring \
|
||||
php8.3-zip \
|
||||
php8.3-bcmath \
|
||||
php8.3-redis \
|
||||
php-memcached \
|
||||
patch \
|
||||
curl \
|
||||
@@ -40,8 +40,7 @@ autoconf \
|
||||
libc-dev \
|
||||
libldap-common \
|
||||
pkg-config \
|
||||
libmcrypt-dev \
|
||||
php8.1-dev \
|
||||
php8.3-dev \
|
||||
ca-certificates \
|
||||
unzip \
|
||||
dnsutils \
|
||||
@@ -51,18 +50,13 @@ dnsutils \
|
||||
RUN curl -L -O https://github.com/pear/pearweb_phars/raw/master/go-pear.phar
|
||||
RUN php go-pear.phar
|
||||
|
||||
RUN pecl install mcrypt
|
||||
|
||||
RUN bash -c "echo extension=/usr/lib/php/20210902/mcrypt.so > /etc/php/8.1/mods-available/mcrypt.ini"
|
||||
|
||||
RUN phpenmod mcrypt
|
||||
RUN phpenmod gd
|
||||
RUN phpenmod bcmath
|
||||
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/8.1/apache2/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/8.1/cli/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/8.3/apache2/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/8.3/cli/php.ini
|
||||
|
||||
RUN useradd -m --uid 1000 --gid 50 docker
|
||||
RUN useradd -m --uid 10000 --gid 50 docker
|
||||
|
||||
RUN echo export APACHE_RUN_USER=docker >> /etc/apache2/envvars
|
||||
RUN echo export APACHE_RUN_GROUP=staff >> /etc/apache2/envvars
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
This is a FOSS project for asset management in IT Operations. Knowing who has which laptop, when it was purchased in order to depreciate it correctly, handling software licenses, etc.
|
||||
|
||||
It is built on [Laravel 10](http://laravel.com).
|
||||
It is built on [Laravel 11](http://laravel.com).
|
||||
|
||||
Snipe-IT is actively developed and we [release quite frequently](https://github.com/snipe/snipe-it/releases). ([Check out the live demo here](https://snipeitapp.com/demo/).)
|
||||
|
||||
@@ -94,6 +94,8 @@ Since the release of the JSON REST API, several third-party developers have been
|
||||
- [SnipeAgent](https://github.com/ReticentRobot/SnipeAgent) by [@ReticentRobot](https://github.com/ReticentRobot) - Windows agent for Snipe-IT.
|
||||
- [Gate Pass Generator](https://github.com/cha7uraAE/snipe-it-gate-pass-system) by [@cha7uraAE](https://github.com/cha7uraAE) - A Streamlit application for generating gate passes based on hardware data from a Snipe-IT API.
|
||||
|
||||
We also have a handful of [Google Apps scripts](https://github.com/grokability/google-apps-scripts-for-snipe-it) to help with various tasks.
|
||||
|
||||
-----
|
||||
|
||||
### Join the Community!
|
||||
|
||||
@@ -125,6 +125,10 @@ class LdapSync extends Command
|
||||
*/
|
||||
$attributes = array_values(array_filter($ldap_map));
|
||||
|
||||
if (Setting::getSettings()->is_ad === 1 && is_null($ldap_map['active_flag'])) {
|
||||
$attributes[] = 'useraccountcontrol';
|
||||
}
|
||||
|
||||
$results = Ldap::findLdapUsers($search_base, -1, $filter, $attributes);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
@@ -357,9 +361,15 @@ class LdapSync extends Command
|
||||
// (Specifically, we don't handle a value of '0.0' correctly)
|
||||
$raw_value = @$results[$i][$ldap_map["active_flag"]][0];
|
||||
$filter_var = filter_var($raw_value, FILTER_VALIDATE_BOOLEAN, FILTER_NULL_ON_FAILURE);
|
||||
|
||||
$boolean_cast = (bool) $raw_value;
|
||||
|
||||
$user->activated = $filter_var ?? $boolean_cast; // if filter_var() was true or false, use that. If it's null, use the $boolean_cast
|
||||
|
||||
if (Setting::getSettings()->ldap_invert_active_flag === 1) {
|
||||
// Because ldap_active_flag is set, if filter_var is true or boolean_cast is true, then user is suspended
|
||||
$user->activated = !($filter_var ?? $boolean_cast);
|
||||
}else{
|
||||
$user->activated = $filter_var ?? $boolean_cast; // if filter_var() was true or false, use that. If it's null, use the $boolean_cast
|
||||
}
|
||||
|
||||
} elseif (array_key_exists('useraccountcontrol', $results[$i])) {
|
||||
// ....otherwise, (ie if no 'active' LDAP flag is defined), IF the UAC setting exists,
|
||||
@@ -424,8 +434,12 @@ class LdapSync extends Command
|
||||
$item['note'] = $item['createorupdate'];
|
||||
$item['status'] = 'success';
|
||||
if ($item['createorupdate'] === 'created' && $ldap_default_group) {
|
||||
$user->groups()->attach($ldap_default_group);
|
||||
// Check if the relationship already exists
|
||||
if (!$user->groups()->where('group_id', $ldap_default_group)->exists()) {
|
||||
$user->groups()->attach($ldap_default_group);
|
||||
}
|
||||
}
|
||||
|
||||
//updates assets location based on user's location
|
||||
if ($user->wasChanged('location_id')) {
|
||||
foreach ($user->assets as $asset) {
|
||||
|
||||
@@ -1,157 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\LegacyEncrypter\McryptEncrypter;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class RecryptFromMcrypt extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:legacy-recrypt
|
||||
{--force : Force a re-crypt of encrypted data from MCRYPT.}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'This command allows upgrading users to de-encrypt their deprecated mcrypt encrypted fields and re-encrypt them using the current OpenSSL encryption.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
// Check and see if they have a legacy app key listed in their .env
|
||||
// If not, we can try to use the current APP_KEY if looks like it's old
|
||||
$legacy_key = env('LEGACY_APP_KEY');
|
||||
$key_parts = explode(':', $legacy_key);
|
||||
$legacy_cipher = env('LEGACY_CIPHER', 'rijndael-256');
|
||||
$errors = [];
|
||||
|
||||
if (! $legacy_key) {
|
||||
$this->error('ERROR: You do not have a LEGACY_APP_KEY set in your .env file. Please locate your old APP_KEY and ADD a line to your .env file like: LEGACY_APP_KEY=YOUR_OLD_APP_KEY');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
// Do some basic legacy app key length checks
|
||||
if (strlen($legacy_key) == 32) {
|
||||
$legacy_length_check = true;
|
||||
} elseif (array_key_exists('1', $key_parts) && (strlen($key_parts[1]) == 44)) {
|
||||
$legacy_key = base64_decode($key_parts[1], true);
|
||||
$legacy_length_check = true;
|
||||
} else {
|
||||
$legacy_length_check = false;
|
||||
}
|
||||
|
||||
// Check that the app key is 32 characters
|
||||
if ($legacy_length_check === true) {
|
||||
$this->comment('INFO: Your LEGACY_APP_KEY looks correct. Okay to continue.');
|
||||
} else {
|
||||
$this->error('ERROR: Your LEGACY_APP_KEY is not the correct length (32 characters or base64 followed by 44 characters for later versions). Please locate your old APP_KEY and use that as your LEGACY_APP_KEY in your .env file to continue.');
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
$this->error('================================!!!! WARNING !!!!================================');
|
||||
$this->error('================================!!!! WARNING !!!!================================');
|
||||
$this->comment("This tool will attempt to decrypt your old Snipe-IT (mcrypt, now deprecated) encrypted data and re-encrypt it using OpenSSL. \n\nYou should only continue if you have backed up any and all old APP_KEYs and have backed up your data.");
|
||||
|
||||
$force = ($this->option('force')) ? true : false;
|
||||
|
||||
if ($force || ($this->confirm('Are you SURE you wish to continue?'))) {
|
||||
$backup_file = 'backups/env-backups/'.'app_key-'.date('Y-m-d-gis');
|
||||
|
||||
try {
|
||||
Storage::disk('local')->put($backup_file, 'APP_KEY: '.config('app.key'));
|
||||
Storage::disk('local')->append($backup_file, 'LEGACY_APP_KEY: '.$legacy_key);
|
||||
} catch (\Exception $e) {
|
||||
$this->info('WARNING: Could not backup app keys');
|
||||
}
|
||||
|
||||
if ($legacy_cipher) {
|
||||
$mcrypter = new McryptEncrypter($legacy_key, $legacy_cipher);
|
||||
} else {
|
||||
$mcrypter = new McryptEncrypter($legacy_key);
|
||||
}
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
if ($settings->ldap_pword == '') {
|
||||
$this->comment('INFO: No LDAP password found. Skipping... ');
|
||||
} else {
|
||||
$decrypted_ldap_pword = $mcrypter->decrypt($settings->ldap_pword);
|
||||
$settings->ldap_pword = Crypt::encrypt($decrypted_ldap_pword);
|
||||
$settings->save();
|
||||
}
|
||||
/** @var CustomField[] $custom_fields */
|
||||
$custom_fields = CustomField::where('field_encrypted', '=', 1)->get();
|
||||
$this->comment('INFO: Retrieving encrypted custom fields...');
|
||||
|
||||
$query = Asset::withTrashed();
|
||||
|
||||
foreach ($custom_fields as $custom_field) {
|
||||
$this->comment('FIELD TO RECRYPT: '.$custom_field->name.' ('.$custom_field->db_column.')');
|
||||
$query->orWhereNotNull($custom_field->db_column);
|
||||
}
|
||||
|
||||
// Get all assets with a value in any of the fields that were encrypted
|
||||
/** @var Asset[] $assets */
|
||||
$assets = $query->get();
|
||||
|
||||
$bar = $this->output->createProgressBar(count($assets));
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
foreach ($custom_fields as $encrypted_field) {
|
||||
$columnName = $encrypted_field->db_column;
|
||||
|
||||
// Make sure the value isn't null
|
||||
if ($asset->{$columnName} != '') {
|
||||
// Try to decrypt the payload using the legacy app key
|
||||
try {
|
||||
$decrypted_field = $mcrypter->decrypt($asset->{$columnName});
|
||||
$asset->{$columnName} = Crypt::encrypt($decrypted_field);
|
||||
$this->comment($decrypted_field);
|
||||
} catch (\Exception $e) {
|
||||
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
|
||||
}
|
||||
}
|
||||
}
|
||||
$asset->save();
|
||||
$bar->advance();
|
||||
}
|
||||
|
||||
$bar->finish();
|
||||
|
||||
if (count($errors) > 0) {
|
||||
$this->comment("\n\n");
|
||||
$this->error("The decrypter encountered some errors: \n");
|
||||
foreach ($errors as $error) {
|
||||
$this->error($error);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -64,28 +64,43 @@ class SendAcceptanceReminder extends Command
|
||||
->groupBy(function($item) {
|
||||
return $item['acceptance']->assignedTo ? $item['acceptance']->assignedTo->id : '';
|
||||
});
|
||||
$no_email_list= [];
|
||||
|
||||
foreach($unacceptedAssetGroups as $unacceptedAssetGroup) {
|
||||
// The [0] is weird, but it allows for the item_count to work and grabs the appropriate info for each user.
|
||||
// Collapsing and flattening the collection doesn't work above.
|
||||
$acceptance = $unacceptedAssetGroup[0]['acceptance'];
|
||||
|
||||
$locale = $acceptance->assignedTo?->locale;
|
||||
$email = $acceptance->assignedTo?->email;
|
||||
|
||||
if(!$email){
|
||||
$this->info($acceptance->assignedTo?->present()->fullName().' has no email address.');
|
||||
$no_email_list[] = [
|
||||
'id' => $acceptance->assignedTo?->id,
|
||||
'name' => $acceptance->assignedTo?->present()->fullName(),
|
||||
];
|
||||
} else {
|
||||
$count++;
|
||||
}
|
||||
$item_count = $unacceptedAssetGroup->count();
|
||||
|
||||
if ($locale && $email) {
|
||||
Mail::to($email)->send((new UnacceptedAssetReminderMail($acceptance, $item_count))->locale($locale));
|
||||
|
||||
} elseif ($email) {
|
||||
Mail::to($email)->send((new UnacceptedAssetReminderMail($acceptance, $item_count)));
|
||||
}
|
||||
$count++;
|
||||
|
||||
}
|
||||
|
||||
$this->info($count.' users notified.');
|
||||
$headers = ['ID', 'Name'];
|
||||
$rows = [];
|
||||
|
||||
foreach ($no_email_list as $user) {
|
||||
$rows[] = [$user['id'], $user['name']];
|
||||
}
|
||||
$this->info("The following users do not have an email address:");
|
||||
$this->table($headers, $rows);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -2,13 +2,12 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Mail\SendUpcomingAuditMail;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Recipients\AlertRecipient;
|
||||
use App\Models\Setting;
|
||||
use App\Notifications\SendUpcomingAuditNotification;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Mail;
|
||||
|
||||
class SendUpcomingAuditReport extends Command
|
||||
{
|
||||
@@ -48,19 +47,19 @@ class SendUpcomingAuditReport extends Command
|
||||
$today = Carbon::now();
|
||||
$interval_date = $today->copy()->addDays($interval);
|
||||
|
||||
$assets = Asset::whereNull('deleted_at')->DueOrOverdueForAudit($settings)->orderBy('assets.next_audit_date', 'desc')->get();
|
||||
$this->info($assets->count().' assets must be audited in on or before '.$interval_date.' is deadline');
|
||||
$assets = Asset::whereNull('deleted_at')->dueOrOverdueForAudit($settings)->orderBy('assets.next_audit_date', 'desc')->get();
|
||||
$this->info($assets->count() . ' assets must be audited in on or before ' . $interval_date . ' is deadline');
|
||||
|
||||
|
||||
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
||||
if ((count($assets) !== 0) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
||||
// Send a rollup to the admin, if settings dictate
|
||||
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item) {
|
||||
return new AlertRecipient($item);
|
||||
});
|
||||
$recipients = collect(explode(',', $settings->alert_email))
|
||||
->map(fn($item) => trim($item))
|
||||
->all();
|
||||
|
||||
$this->info('Sending Admin SendUpcomingAuditNotification to: '.$settings->alert_email);
|
||||
\Notification::send($recipients, new SendUpcomingAuditNotification($assets, $settings->audit_warning_days));
|
||||
|
||||
$this->info('Sending Admin SendUpcomingAuditNotification to: ' . $settings->alert_email);
|
||||
Mail::to($recipients)->send(new SendUpcomingAuditMail($assets, $settings->audit_warning_days));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Console;
|
||||
use App\Console\Commands\ImportLocations;
|
||||
use App\Console\Commands\ReEncodeCustomFieldNames;
|
||||
use App\Console\Commands\RestoreDeletedUsers;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Console\Scheduling\Schedule;
|
||||
use Illuminate\Foundation\Console\Kernel as ConsoleKernel;
|
||||
|
||||
@@ -18,12 +19,14 @@ class Kernel extends ConsoleKernel
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
$schedule->command('snipeit:inventory-alerts')->daily();
|
||||
$schedule->command('snipeit:expiring-alerts')->daily();
|
||||
$schedule->command('snipeit:expected-checkin')->daily();
|
||||
if(Setting::getSettings()->alerts_enabled === 1) {
|
||||
$schedule->command('snipeit:inventory-alerts')->daily();
|
||||
$schedule->command('snipeit:expiring-alerts')->daily();
|
||||
$schedule->command('snipeit:expected-checkin')->daily();
|
||||
$schedule->command('snipeit:upcoming-audits')->daily();
|
||||
}
|
||||
$schedule->command('snipeit:backup')->weekly();
|
||||
$schedule->command('backup:clean')->daily();
|
||||
$schedule->command('snipeit:upcoming-audits')->daily();
|
||||
$schedule->command('auth:clear-resets')->everyFifteenMinutes();
|
||||
$schedule->command('saml:clear_expired_nonces')->weekly();
|
||||
}
|
||||
|
||||
@@ -1,28 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class NoteAdded
|
||||
{
|
||||
use Dispatchable, SerializesModels;
|
||||
public $itemNoteAddedOn;
|
||||
public $note;
|
||||
public $noteAddedBy;
|
||||
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($itemNoteAddedOn, User $noteAddedBy, $note)
|
||||
{
|
||||
$this->itemNoteAddedOn = $itemNoteAddedOn;
|
||||
$this->note = $note;
|
||||
$this->noteAddedBy = $noteAddedBy;
|
||||
}
|
||||
}
|
||||
@@ -122,6 +122,27 @@ class Handler extends ExceptionHandler
|
||||
}
|
||||
|
||||
|
||||
// This is traaaaash but it handles models that are not found while using route model binding :(
|
||||
// The only alternative is to set that at *each* route, which is crazypants
|
||||
if ($e instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
|
||||
$model_name = last(explode('\\', $e->getModel()));
|
||||
$route = str_plural(strtolower(last(explode('\\', $e->getModel())))).'.index';
|
||||
|
||||
// Sigh.
|
||||
if ($route == 'assets.index') {
|
||||
$route = 'hardware.index';
|
||||
} elseif ($route == 'reporttemplates.index') {
|
||||
$route = 'reports/custom';
|
||||
} elseif ($route == 'assetmodels.index') {
|
||||
$route = 'models.index';
|
||||
} elseif ($route == 'predefinedkits.index') {
|
||||
$route = 'kits.index';
|
||||
}
|
||||
|
||||
return redirect()
|
||||
->route($route)
|
||||
->withError(trans('general.generic_model_not_found', ['model' => $model_name]));
|
||||
}
|
||||
|
||||
|
||||
if ($this->isHttpException($e) && (isset($statusCode)) && ($statusCode == '404' )) {
|
||||
|
||||
@@ -1520,11 +1520,11 @@ class Helper
|
||||
if ($redirect_option == 'target') {
|
||||
switch ($checkout_to_type) {
|
||||
case 'user':
|
||||
return route('users.show', ['user' => $request->assigned_user]);
|
||||
return route('users.show', $request->assigned_user);
|
||||
case 'location':
|
||||
return route('locations.show', ['location' => $request->assigned_location]);
|
||||
return route('locations.show', $request->assigned_location);
|
||||
case 'asset':
|
||||
return route('hardware.show', ['hardware' => $request->assigned_asset]);
|
||||
return route('hardware.show', $request->assigned_asset);
|
||||
}
|
||||
}
|
||||
return redirect()->back()->with('error', trans('admin/hardware/message.checkout.error'));
|
||||
|
||||
@@ -59,6 +59,8 @@ class IconHelper
|
||||
return 'fas fa-cog';
|
||||
case 'angle-left':
|
||||
return 'fas fa-angle-left';
|
||||
case 'angle-right':
|
||||
return 'fas fa-angle-right';
|
||||
case 'warning':
|
||||
return 'fas fa-exclamation-triangle';
|
||||
case 'kits':
|
||||
@@ -184,6 +186,8 @@ class IconHelper
|
||||
return 'fa-regular fa-id-card';
|
||||
case 'department' :
|
||||
return 'fa-solid fa-building-user';
|
||||
case 'home' :
|
||||
return 'fa-solid fa-house';
|
||||
case 'note':
|
||||
case 'notes':
|
||||
return 'fas fa-sticky-note';
|
||||
|
||||
@@ -95,16 +95,10 @@ class AccessoriesController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryId
|
||||
*/
|
||||
public function edit($accessoryId = null) : View | RedirectResponse
|
||||
public function edit(Accessory $accessory) : View | RedirectResponse
|
||||
{
|
||||
|
||||
if ($item = Accessory::find($accessoryId)) {
|
||||
$this->authorize($item);
|
||||
return view('accessories.edit', compact('item'))->with('category_type', 'accessory');
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
|
||||
$this->authorize('update', Accessory::class);
|
||||
return view('accessories.edit')->with('item', $accessory)->with('category_type', 'accessory');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -114,19 +108,12 @@ class AccessoriesController extends Controller
|
||||
* @param int $accessoryId
|
||||
* @since [v6.0]
|
||||
*/
|
||||
public function getClone($accessoryId = null) : View | RedirectResponse
|
||||
public function getClone(Accessory $accessory) : View | RedirectResponse
|
||||
{
|
||||
|
||||
$this->authorize('create', Accessory::class);
|
||||
|
||||
// Check if the asset exists
|
||||
if (is_null($accessory_to_clone = Accessory::find($accessoryId))) {
|
||||
// Redirect to the asset management page
|
||||
return redirect()->route('accessories.index')
|
||||
->with('error', trans('admin/accessories/message.does_not_exist', ['id' => $accessoryId]));
|
||||
}
|
||||
|
||||
$accessory = clone $accessory_to_clone;
|
||||
$accessory = clone $accessory;
|
||||
$accessory->id = null;
|
||||
$accessory->location_id = null;
|
||||
|
||||
@@ -142,9 +129,9 @@ class AccessoriesController extends Controller
|
||||
* @param ImageUploadRequest $request
|
||||
* @param int $accessoryId
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $accessoryId = null) : RedirectResponse
|
||||
public function update(ImageUploadRequest $request, Accessory $accessory) : RedirectResponse
|
||||
{
|
||||
if ($accessory = Accessory::withCount('checkouts as checkouts_count')->find($accessoryId)) {
|
||||
if ($accessory = Accessory::withCount('checkouts as checkouts_count')->find($accessory->id)) {
|
||||
|
||||
$this->authorize($accessory);
|
||||
|
||||
@@ -231,14 +218,10 @@ class AccessoriesController extends Controller
|
||||
* @see AccessoriesController::getDataView() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show($accessoryID = null) : View | RedirectResponse
|
||||
public function show(Accessory $accessory) : View | RedirectResponse
|
||||
{
|
||||
$accessory = Accessory::withCount('checkouts as checkouts_count')->find($accessoryID);
|
||||
$accessory = Accessory::withCount('checkouts as checkouts_count')->find($accessory->id);
|
||||
$this->authorize('view', $accessory);
|
||||
if (isset($accessory->id)) {
|
||||
return view('accessories.view', compact('accessory'));
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist', ['id' => $accessoryID]));
|
||||
return view('accessories.view', compact('accessory'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,18 @@ class AssetModelsController extends Controller
|
||||
$assetmodels->onlyTrashed();
|
||||
}
|
||||
|
||||
if ($request->filled('name')) {
|
||||
$assetmodels = $assetmodels->where('models.name', '=', $request->input('name'));
|
||||
}
|
||||
|
||||
if ($request->filled('model_number')) {
|
||||
$assetmodels = $assetmodels->where('models.model_number', '=', $request->input('model_number'));
|
||||
}
|
||||
|
||||
if ($request->filled('notes')) {
|
||||
$assetmodels = $assetmodels->where('models.notes', '=', $request->input('notes'));
|
||||
}
|
||||
|
||||
if ($request->filled('category_id')) {
|
||||
$assetmodels = $assetmodels->where('models.category_id', '=', $request->input('category_id'));
|
||||
}
|
||||
|
||||
@@ -1230,7 +1230,10 @@ class AssetsController extends Controller
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
$this->authorize('view', $asset);
|
||||
$accessory_checkouts = AccessoryCheckout::AssetsAssigned()->with('adminuser')->with('accessories');
|
||||
$accessory_checkouts = AccessoryCheckout::AssetsAssigned()
|
||||
->where('assigned_to', $asset->id)
|
||||
->with('adminuser')
|
||||
->with('accessories');
|
||||
|
||||
$offset = ($request->input('offset') > $accessory_checkouts->count()) ? $accessory_checkouts->count() : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
@@ -1239,6 +1242,8 @@ class AssetsController extends Controller
|
||||
$accessory_checkouts = $accessory_checkouts->skip($offset)->take($limit)->get();
|
||||
return (new AssetsTransformer)->transformCheckedoutAccessories($accessory_checkouts, $total);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generate asset labels by tag
|
||||
*
|
||||
|
||||
@@ -48,7 +48,8 @@ class ComponentsController extends Controller
|
||||
];
|
||||
|
||||
$components = Component::select('components.*')
|
||||
->with('company', 'location', 'category', 'assets', 'supplier', 'adminuser', 'manufacturer');
|
||||
->with('company', 'location', 'category', 'assets', 'supplier', 'adminuser', 'manufacturer', 'uncontrainedAssets')
|
||||
->withSum('uncontrainedAssets', 'components_assets.assigned_qty');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$components = $components->TextSearch($request->input('search'));
|
||||
@@ -197,6 +198,11 @@ class ComponentsController extends Controller
|
||||
$this->authorize('delete', Component::class);
|
||||
$component = Component::findOrFail($id);
|
||||
$this->authorize('delete', $component);
|
||||
|
||||
if ($component->numCheckedOut() > 0) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.delete.error_qty')));
|
||||
}
|
||||
|
||||
$component->delete();
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/components/message.delete.success')));
|
||||
|
||||
@@ -66,25 +66,41 @@ class ImportController extends Controller
|
||||
if (! ini_get('auto_detect_line_endings')) {
|
||||
ini_set('auto_detect_line_endings', '1');
|
||||
}
|
||||
$file_contents = $file->getContent(); //TODO - this *does* load the whole file in RAM, but we need that to be able to 'iconv' it?
|
||||
$encoding = $detector->getEncoding($file_contents);
|
||||
$reader = null;
|
||||
if (strcasecmp($encoding, 'UTF-8') != 0) {
|
||||
$transliterated = iconv($encoding, 'UTF-8', $file_contents);
|
||||
if ($transliterated !== false) {
|
||||
$tmpname = tempnam(sys_get_temp_dir(), '');
|
||||
$tmpresults = file_put_contents($tmpname, $transliterated);
|
||||
if ($tmpresults !== false) {
|
||||
if (function_exists('iconv')) {
|
||||
$file_contents = $file->getContent(); //TODO - this *does* load the whole file in RAM, but we need that to be able to 'iconv' it?
|
||||
$encoding = $detector->getEncoding($file_contents);
|
||||
\Log::warning("Discovered encoding: $encoding in uploaded CSV");
|
||||
$reader = null;
|
||||
if (strcasecmp($encoding, 'UTF-8') != 0) {
|
||||
$transliterated = false;
|
||||
try {
|
||||
$transliterated = iconv(strtoupper($encoding), 'UTF-8', $file_contents);
|
||||
} catch (\Exception $e) {
|
||||
$transliterated = false; //blank out the partially-decoded string
|
||||
return response()->json(
|
||||
Helper::formatStandardApiResponse(
|
||||
'error',
|
||||
null,
|
||||
trans('admin/hardware/message.import.transliterate_failure', ["encoding" => $encoding])
|
||||
),
|
||||
422
|
||||
);
|
||||
}
|
||||
if ($transliterated !== false) {
|
||||
$tmpname = tempnam(sys_get_temp_dir(), '');
|
||||
$tmpresults = file_put_contents($tmpname, $transliterated);
|
||||
$transliterated = null; //save on memory?
|
||||
$newfile = new UploadedFile($tmpname, $file->getClientOriginalName(), null, null, true); //WARNING: this is enabling 'test mode' - which is gross, but otherwise the file won't be treated as 'uploaded'
|
||||
if ($newfile->isValid()) {
|
||||
$file = $newfile;
|
||||
if ($tmpresults !== false) {
|
||||
$newfile = new UploadedFile($tmpname, $file->getClientOriginalName(), null, null, true); //WARNING: this is enabling 'test mode' - which is gross, but otherwise the file won't be treated as 'uploaded'
|
||||
if ($newfile->isValid()) {
|
||||
$file = $newfile;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$file_contents = null; //try to save on memory, I guess?
|
||||
}
|
||||
$reader = Reader::createFromFileObject($file->openFile('r')); //file pointer leak?
|
||||
$file_contents = null; //try to save on memory, I guess?
|
||||
|
||||
try {
|
||||
$import->header_row = $reader->fetchOne(0);
|
||||
|
||||
@@ -1,43 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Events\NoteAdded;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class NotesController extends Controller
|
||||
{
|
||||
public function store(Request $request)
|
||||
{
|
||||
$validated = $request->validate([
|
||||
'note' => 'required|string|max:500',
|
||||
'type' => [
|
||||
'required',
|
||||
Rule::in(['asset']),
|
||||
],
|
||||
]);
|
||||
|
||||
// This can be made dynamic by using $request->input('type') to determine which model type to add the note to.
|
||||
// For now, we are only placing this on Assets
|
||||
$item = Asset::findOrFail($request->input("id"));
|
||||
$this->authorize('update', $item);
|
||||
|
||||
event(new NoteAdded($item, Auth::user(), $validated['note']));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success'));
|
||||
}
|
||||
|
||||
public function update(Request $request)
|
||||
{
|
||||
|
||||
}
|
||||
public function destroy(Request $request)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
@@ -290,10 +290,12 @@ class StatuslabelsController extends Controller
|
||||
|
||||
/**
|
||||
* Returns a boolean response based on whether the status label
|
||||
* is one that is deployable.
|
||||
* is one that is deployable or pending.
|
||||
*
|
||||
* This is used by the hardware create/edit view to determine whether
|
||||
* we should provide a dropdown of users for them to check the asset out to.
|
||||
* we should provide a dropdown of users for them to check the asset out to,
|
||||
* and whether we show a warning that the asset will be checked in if it's already
|
||||
* assigned but the status is changed to one that isn't pending or deployable
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
@@ -301,7 +303,7 @@ class StatuslabelsController extends Controller
|
||||
public function checkIfDeployable($id) : string
|
||||
{
|
||||
$statuslabel = Statuslabel::findOrFail($id);
|
||||
if ($statuslabel->getStatuslabelType() == 'deployable') {
|
||||
if (($statuslabel->getStatuslabelType() == 'pending') || ($statuslabel->getStatuslabelType() == 'deployable')) {
|
||||
return '1';
|
||||
}
|
||||
|
||||
|
||||
@@ -139,19 +139,12 @@ class AssetMaintenancesController extends Controller
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function edit($assetMaintenanceId = null) : View | RedirectResponse
|
||||
public function edit(AssetMaintenance $maintenance) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
|
||||
// Redirect to the asset maintenance management page
|
||||
return redirect()->route('maintenances.index')->with('error', trans('admin/asset_maintenances/message.not_found'));
|
||||
} elseif ((!$assetMaintenance->asset) || ($assetMaintenance->asset->deleted_at!='')) {
|
||||
// Redirect to the asset maintenance management page
|
||||
if ((!$maintenance->asset) || ($maintenance->asset->deleted_at!='')) {
|
||||
return redirect()->route('maintenances.index')->with('error', 'asset does not exist');
|
||||
} elseif (! Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
} elseif (! Company::isCurrentUserHasAccess($maintenance->asset)) {
|
||||
return static::getInsufficientPermissionsRedirect();
|
||||
}
|
||||
|
||||
@@ -161,7 +154,7 @@ class AssetMaintenancesController extends Controller
|
||||
return view('asset_maintenances/edit')
|
||||
->with('selectedAsset', null)
|
||||
->with('assetMaintenanceType', $assetMaintenanceType)
|
||||
->with('item', $assetMaintenance);
|
||||
->with('item', $maintenance);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,24 +167,20 @@ class AssetMaintenancesController extends Controller
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function update(Request $request, $assetMaintenanceId = null) : View | RedirectResponse
|
||||
public function update(Request $request, AssetMaintenance $maintenance) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
|
||||
// Redirect to the asset maintenance management page
|
||||
return redirect()->route('maintenances.index')->with('error', trans('admin/asset_maintenances/message.not_found'));
|
||||
} elseif ((!$assetMaintenance->asset) || ($assetMaintenance->asset->deleted_at!='')) {
|
||||
// Redirect to the asset maintenance management page
|
||||
|
||||
if ((!$maintenance->asset) || ($maintenance->asset->deleted_at!='')) {
|
||||
return redirect()->route('maintenances.index')->with('error', 'asset does not exist');
|
||||
} elseif (! Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
} elseif (! Company::isCurrentUserHasAccess($maintenance->asset)) {
|
||||
return static::getInsufficientPermissionsRedirect();
|
||||
}
|
||||
|
||||
$assetMaintenance->supplier_id = $request->input('supplier_id');
|
||||
$assetMaintenance->is_warranty = $request->input('is_warranty');
|
||||
$assetMaintenance->cost = $request->input('cost');
|
||||
$assetMaintenance->notes = $request->input('notes');
|
||||
$maintenance->supplier_id = $request->input('supplier_id');
|
||||
$maintenance->is_warranty = $request->input('is_warranty');
|
||||
$maintenance->cost = $request->input('cost');
|
||||
$maintenance->notes = $request->input('notes');
|
||||
|
||||
$asset = Asset::find(request('asset_id'));
|
||||
|
||||
@@ -200,39 +189,39 @@ class AssetMaintenancesController extends Controller
|
||||
}
|
||||
|
||||
// Save the asset maintenance data
|
||||
$assetMaintenance->asset_id = $request->input('asset_id');
|
||||
$assetMaintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
|
||||
$assetMaintenance->title = $request->input('title');
|
||||
$assetMaintenance->start_date = $request->input('start_date');
|
||||
$assetMaintenance->completion_date = $request->input('completion_date');
|
||||
$maintenance->asset_id = $request->input('asset_id');
|
||||
$maintenance->asset_maintenance_type = $request->input('asset_maintenance_type');
|
||||
$maintenance->title = $request->input('title');
|
||||
$maintenance->start_date = $request->input('start_date');
|
||||
$maintenance->completion_date = $request->input('completion_date');
|
||||
|
||||
if (($assetMaintenance->completion_date == null)
|
||||
if (($maintenance->completion_date == null)
|
||||
) {
|
||||
if (($assetMaintenance->asset_maintenance_time !== 0)
|
||||
|| (! is_null($assetMaintenance->asset_maintenance_time))
|
||||
if (($maintenance->asset_maintenance_time !== 0)
|
||||
|| (! is_null($maintenance->asset_maintenance_time))
|
||||
) {
|
||||
$assetMaintenance->asset_maintenance_time = null;
|
||||
$maintenance->asset_maintenance_time = null;
|
||||
}
|
||||
}
|
||||
|
||||
if (($assetMaintenance->completion_date !== null)
|
||||
&& ($assetMaintenance->start_date !== '')
|
||||
&& ($assetMaintenance->start_date !== '0000-00-00')
|
||||
if (($maintenance->completion_date !== null)
|
||||
&& ($maintenance->start_date !== '')
|
||||
&& ($maintenance->start_date !== '0000-00-00')
|
||||
) {
|
||||
$startDate = Carbon::parse($assetMaintenance->start_date);
|
||||
$completionDate = Carbon::parse($assetMaintenance->completion_date);
|
||||
$assetMaintenance->asset_maintenance_time = $completionDate->diffInDays($startDate);
|
||||
$startDate = Carbon::parse($maintenance->start_date);
|
||||
$completionDate = Carbon::parse($maintenance->completion_date);
|
||||
$maintenance->asset_maintenance_time = $completionDate->diffInDays($startDate);
|
||||
}
|
||||
|
||||
// Was the asset maintenance created?
|
||||
if ($assetMaintenance->save()) {
|
||||
if ($maintenance->save()) {
|
||||
|
||||
// Redirect to the new asset maintenance page
|
||||
return redirect()->route('maintenances.index')
|
||||
->with('success', trans('admin/asset_maintenances/message.edit.success'));
|
||||
->with('success', trans('admin/asset_maintenances/message.edit.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($assetMaintenance->getErrors());
|
||||
return redirect()->back()->withInput()->withErrors($maintenance->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -271,19 +260,13 @@ class AssetMaintenancesController extends Controller
|
||||
* @version v1.0
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function show($assetMaintenanceId) : View | RedirectResponse
|
||||
public function show(AssetMaintenance $maintenance) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
// Check if the asset maintenance exists
|
||||
if (is_null($assetMaintenance = AssetMaintenance::find($assetMaintenanceId))) {
|
||||
// Redirect to the asset maintenance management page
|
||||
return redirect()->route('maintenances.index')
|
||||
->with('error', trans('admin/asset_maintenances/message.not_found'));
|
||||
} elseif (! Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
if (! Company::isCurrentUserHasAccess($maintenance->asset)) {
|
||||
return static::getInsufficientPermissionsRedirect();
|
||||
}
|
||||
|
||||
return view('asset_maintenances/view')->with('assetMaintenance', $assetMaintenance);
|
||||
return view('asset_maintenances/view')->with('assetMaintenance', $maintenance);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -109,16 +109,11 @@ class AssetModelsController extends Controller
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
*/
|
||||
public function edit($modelId = null) : View | RedirectResponse
|
||||
public function edit(AssetModel $model) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('update', AssetModel::class);
|
||||
if ($item = AssetModel::find($modelId)) {
|
||||
$category_type = 'asset';
|
||||
return view('models/edit', compact('item', 'category_type'))->with('depreciation_list', Helper::depreciationList());
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
|
||||
$category_type = 'asset';
|
||||
return view('models/edit', compact('category_type'))->with('item', $model)->with('depreciation_list', Helper::depreciationList());
|
||||
}
|
||||
|
||||
|
||||
@@ -133,16 +128,11 @@ class AssetModelsController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(StoreAssetModelRequest $request, $modelId) : RedirectResponse
|
||||
public function update(StoreAssetModelRequest $request, AssetModel $model) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', AssetModel::class);
|
||||
|
||||
if (is_null($model = AssetModel::find($modelId))) {
|
||||
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$model = $request->handleImages($model);
|
||||
|
||||
$model->depreciation_id = $request->input('depreciation_id');
|
||||
$model->eol = $request->input('eol');
|
||||
$model->name = $request->input('name');
|
||||
@@ -188,28 +178,16 @@ class AssetModelsController extends Controller
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
*/
|
||||
public function destroy($modelId) : RedirectResponse
|
||||
public function destroy(AssetModel $model) : RedirectResponse
|
||||
{
|
||||
$this->authorize('delete', AssetModel::class);
|
||||
// Check if the model exists
|
||||
if (is_null($model = AssetModel::find($modelId))) {
|
||||
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
|
||||
}
|
||||
|
||||
|
||||
if ($model->assets()->count() > 0) {
|
||||
// Throw an error that this model is associated with assets
|
||||
return redirect()->route('models.index')->with('error', trans('admin/models/message.assoc_users'));
|
||||
}
|
||||
|
||||
if ($model->image) {
|
||||
try {
|
||||
Storage::disk('public')->delete('models/'.$model->image);
|
||||
$model->update(['image' => null]);
|
||||
} catch (\Exception $e) {
|
||||
Log::info($e);
|
||||
}
|
||||
}
|
||||
|
||||
// Delete the model
|
||||
$model->delete();
|
||||
|
||||
@@ -267,16 +245,10 @@ class AssetModelsController extends Controller
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
*/
|
||||
public function show($modelId = null) : View | RedirectResponse
|
||||
public function show(AssetModel $model) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('view', AssetModel::class);
|
||||
$model = AssetModel::withTrashed()->find($modelId);
|
||||
|
||||
if (isset($model->id)) {
|
||||
return view('models/view', compact('model'));
|
||||
}
|
||||
|
||||
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
|
||||
return view('models/view', compact('model'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -286,23 +258,20 @@ class AssetModelsController extends Controller
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
*/
|
||||
public function getClone($modelId = null) : View | RedirectResponse
|
||||
public function getClone(AssetModel $model) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('create', AssetModel::class);
|
||||
// Check if the model exists
|
||||
if (is_null($model_to_clone = AssetModel::find($modelId))) {
|
||||
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$model = clone $model_to_clone;
|
||||
$cloned_model = clone $model;
|
||||
$model->id = null;
|
||||
$model->deleted_at = null;
|
||||
|
||||
// Show the page
|
||||
return view('models/edit')
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('item', $model)
|
||||
->with('model_id', $model_to_clone->id)
|
||||
->with('clone_model', $model_to_clone);
|
||||
->with('model_id', $model->id)
|
||||
->with('clone_model', $cloned_model);
|
||||
}
|
||||
|
||||
|
||||
@@ -321,7 +290,7 @@ class AssetModelsController extends Controller
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view that allows the user to bulk edit model attrbutes
|
||||
* Returns a view that allows the user to bulk edit model attributes
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.7]
|
||||
|
||||
@@ -58,11 +58,9 @@ class AssetModelsFilesController extends Controller
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show($modelId = null, $fileId = null) : StreamedResponse | Response | RedirectResponse | BinaryFileResponse
|
||||
public function show(AssetModel $model, $fileId = null) : StreamedResponse | Response | RedirectResponse | BinaryFileResponse
|
||||
{
|
||||
$model = AssetModel::find($modelId);
|
||||
// the asset is valid
|
||||
if (isset($model->id)) {
|
||||
|
||||
$this->authorize('view', $model);
|
||||
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
@@ -87,12 +85,6 @@ class AssetModelsFilesController extends Controller
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/hardware/message.does_not_exist', ['id' => $fileId]);
|
||||
|
||||
// Redirect to the hardware management page
|
||||
return redirect()->route('hardware.index')->with('error', $error);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -103,29 +95,21 @@ class AssetModelsFilesController extends Controller
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function destroy($modelId = null, $fileId = null) : RedirectResponse
|
||||
public function destroy(AssetModel $model, $fileId = null) : RedirectResponse
|
||||
{
|
||||
$model = AssetModel::find($modelId);
|
||||
$this->authorize('update', $model);
|
||||
$rel_path = 'private_uploads/assetmodels';
|
||||
|
||||
// the asset is valid
|
||||
if (isset($model->id)) {
|
||||
$this->authorize('update', $model);
|
||||
$log = Actionlog::find($fileId);
|
||||
if ($log) {
|
||||
if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
Storage::delete($rel_path.'/'.$log->filename);
|
||||
}
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
$this->authorize('update', $model);
|
||||
$log = Actionlog::find($fileId);
|
||||
if ($log) {
|
||||
if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
Storage::delete($rel_path.'/'.$log->filename);
|
||||
}
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
// Redirect to the hardware management page
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -27,18 +27,12 @@ class AssetCheckinController extends Controller
|
||||
* @param string $backto
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function create($assetId, $backto = null) : View | RedirectResponse
|
||||
public function create(Asset $asset, $backto = null) : View | RedirectResponse
|
||||
{
|
||||
// Check if the asset exists
|
||||
if (is_null($asset = Asset::find($assetId))) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('checkin', $asset);
|
||||
|
||||
// This asset is already checked in, redirect
|
||||
|
||||
if (is_null($asset->assignedTo)) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
|
||||
}
|
||||
@@ -47,7 +41,11 @@ class AssetCheckinController extends Controller
|
||||
return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
|
||||
}
|
||||
|
||||
return view('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto)->with('table_name', 'Assets');
|
||||
return view('hardware/checkin', compact('asset'))
|
||||
->with('item', $asset)
|
||||
->with('statusLabel_list', Helper::statusLabelList())
|
||||
->with('backto', $backto)
|
||||
->with('table_name', 'Assets');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,6 +89,9 @@ class AssetCheckinController extends Controller
|
||||
$asset->status_id = e($request->get('status_id'));
|
||||
}
|
||||
|
||||
// Add any custom fields that should be included in the checkout
|
||||
$asset->customFieldsForCheckinCheckout('display_checkin');
|
||||
|
||||
$this->migrateLegacyLocations($asset);
|
||||
|
||||
$asset->location_id = $asset->rtd_location_id;
|
||||
@@ -128,6 +129,9 @@ class AssetCheckinController extends Controller
|
||||
|
||||
session()->put('redirect_option', $request->get('redirect_option'));
|
||||
|
||||
// Add any custom fields that should be included in the checkout
|
||||
$asset->customFieldsForCheckinCheckout('display_checkin');
|
||||
|
||||
if ($asset->save()) {
|
||||
|
||||
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), $request->input('note'), $checkin_at, $originalValues));
|
||||
|
||||
@@ -26,27 +26,25 @@ class AssetCheckoutController extends Controller
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create($assetId) : View | RedirectResponse
|
||||
public function create(Asset $asset) : View | RedirectResponse
|
||||
{
|
||||
// Check if the asset exists
|
||||
if (is_null($asset = Asset::with('company')->find(e($assetId)))) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $asset);
|
||||
|
||||
if (!$asset->model) {
|
||||
return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
|
||||
return redirect()->route('hardware.show', $asset)
|
||||
->with('error', trans('admin/hardware/general.model_invalid_fix'));
|
||||
}
|
||||
|
||||
if ($asset->availableForCheckout()) {
|
||||
return view('hardware/checkout', compact('asset'))
|
||||
->with('statusLabel_list', Helper::deployableStatusLabelList())
|
||||
->with('table_name', 'Assets');
|
||||
->with('table_name', 'Assets')
|
||||
->with('item', $asset);
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
|
||||
return redirect()->route('hardware.index')
|
||||
->with('error', trans('admin/hardware/message.checkout.not_available'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -68,7 +66,7 @@ class AssetCheckoutController extends Controller
|
||||
$this->authorize('checkout', $asset);
|
||||
|
||||
if (!$asset->model) {
|
||||
return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
|
||||
return redirect()->route('hardware.show', $asset)->with('error', trans('admin/hardware/general.model_invalid_fix'));
|
||||
}
|
||||
|
||||
$admin = auth()->user();
|
||||
@@ -91,6 +89,7 @@ class AssetCheckoutController extends Controller
|
||||
$asset->status_id = $request->get('status_id');
|
||||
}
|
||||
|
||||
|
||||
if(!empty($asset->licenseseats->all())){
|
||||
if(request('checkout_to_type') == 'user') {
|
||||
foreach ($asset->licenseseats as $seat){
|
||||
@@ -100,23 +99,26 @@ class AssetCheckoutController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
// Add any custom fields that should be included in the checkout
|
||||
$asset->customFieldsForCheckinCheckout('display_checkout');
|
||||
|
||||
$settings = \App\Models\Setting::getSettings();
|
||||
|
||||
// We have to check whether $target->company_id is null here since locations don't have a company yet
|
||||
if (($settings->full_multiple_companies_support) && ((!is_null($target->company_id)) && (!is_null($asset->company_id)))) {
|
||||
if ($target->company_id != $asset->company_id){
|
||||
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('general.error_user_company'));
|
||||
return redirect()->route('hardware.checkout.create', $asset)->with('error', trans('general.error_user_company'));
|
||||
}
|
||||
}
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
|
||||
|
||||
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, $request->get('note'), $request->get('name'))) {
|
||||
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
|
||||
->with('success', trans('admin/hardware/message.checkout.success'));
|
||||
}
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('admin/hardware/message.checkout.error').$asset->getErrors());
|
||||
return redirect()->route("hardware.checkout.create", $asset)->with('error', trans('admin/hardware/message.checkout.error').$asset->getErrors());
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return redirect()->back()->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($asset->getErrors());
|
||||
} catch (CheckoutNotAllowed $e) {
|
||||
|
||||
@@ -26,11 +26,8 @@ class AssetFilesController extends Controller
|
||||
*@since [v1.0]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $assetId = null) : RedirectResponse
|
||||
public function store(UploadFileRequest $request, Asset $asset) : RedirectResponse
|
||||
{
|
||||
if (! $asset = Asset::find($assetId)) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $asset);
|
||||
|
||||
@@ -59,31 +56,28 @@ class AssetFilesController extends Controller
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show($assetId = null, $fileId = null) : View | RedirectResponse | Response | StreamedResponse | BinaryFileResponse
|
||||
public function show(Asset $asset, $fileId = null) : View | RedirectResponse | Response | StreamedResponse | BinaryFileResponse
|
||||
{
|
||||
if ($asset = Asset::find($assetId)) {
|
||||
|
||||
$this->authorize('view', $asset);
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
|
||||
$file = 'private_uploads/assets/'.$log->filename;
|
||||
|
||||
if ($log->action_type == 'audit') {
|
||||
$file = 'private_uploads/audits/'.$log->filename;
|
||||
}
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('hardware.show', ['hardware' => $asset])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
|
||||
$file = 'private_uploads/assets/'.$log->filename;
|
||||
|
||||
if ($log->action_type == 'audit') {
|
||||
$file = 'private_uploads/audits/'.$log->filename;
|
||||
}
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('hardware.show', $asset)->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.show', ['hardware' => $asset])->with('error', trans('general.log_record_not_found'));
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
return redirect()->route('hardware.show', $asset)->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -95,23 +89,20 @@ class AssetFilesController extends Controller
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function destroy($assetId = null, $fileId = null) : RedirectResponse
|
||||
public function destroy(Asset $asset, $fileId = null) : RedirectResponse
|
||||
{
|
||||
if ($asset = Asset::find($assetId)) {
|
||||
$this->authorize('update', $asset);
|
||||
$rel_path = 'private_uploads/assets';
|
||||
$this->authorize('update', $asset);
|
||||
$rel_path = 'private_uploads/assets';
|
||||
|
||||
if ($log = Actionlog::find($fileId)) {
|
||||
if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
Storage::delete($rel_path.'/'.$log->filename);
|
||||
}
|
||||
$log->delete();
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
if ($log = Actionlog::find($fileId)) {
|
||||
if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
Storage::delete($rel_path.'/'.$log->filename);
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.show', ['hardware' => $asset])->with('error', trans('general.log_record_not_found'));
|
||||
$log->delete();
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
return redirect()->route('hardware.show', $asset)->with('error', trans('general.log_record_not_found'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,6 +30,7 @@ use Illuminate\Http\Response;
|
||||
use Illuminate\Contracts\View\View;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use TypeError;
|
||||
|
||||
/**
|
||||
* This class controls all actions related to assets for
|
||||
@@ -201,7 +202,7 @@ class AssetsController extends Controller
|
||||
$asset->checkOut($target, auth()->user(), date('Y-m-d H:i:s'), $request->input('expected_checkin', null), 'Checked out on asset creation', $request->get('name'), $location);
|
||||
}
|
||||
|
||||
$successes[] = "<a href='" . route('hardware.show', ['hardware' => $asset->id]) . "' style='color: white;'>" . e($asset->asset_tag) . "</a>";
|
||||
$successes[] = "<a href='" . route('hardware.show', $asset) . "' style='color: white;'>" . e($asset->asset_tag) . "</a>";
|
||||
|
||||
} else {
|
||||
$failures[] = join(",", $asset->getErrors()->all());
|
||||
@@ -222,7 +223,7 @@ class AssetsController extends Controller
|
||||
//the most common case, keeping it so we don't have to make every use of that translation string be trans_choice'ed
|
||||
//and re-translated
|
||||
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
|
||||
->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', ['hardware' => $asset->id]), 'id', 'tag' => e($asset->asset_tag)]));
|
||||
->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', $asset), 'id', 'tag' => e($asset->asset_tag)]));
|
||||
} else {
|
||||
//multi-success
|
||||
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
|
||||
@@ -240,20 +241,14 @@ class AssetsController extends Controller
|
||||
* Returns a view that presents a form to edit an existing asset.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit($assetId = null) : View | RedirectResponse
|
||||
public function edit(Asset $asset) : View | RedirectResponse
|
||||
{
|
||||
if (! $item = Asset::find($assetId)) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
//Handles company checks and permissions.
|
||||
$this->authorize($item);
|
||||
|
||||
return view('hardware/edit', compact('item'))
|
||||
$this->authorize($asset);
|
||||
return view('hardware/edit')
|
||||
->with('item', $asset)
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
->with('statuslabel_types', Helper::statusTypeList());
|
||||
}
|
||||
@@ -267,15 +262,14 @@ class AssetsController extends Controller
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show($assetId = null) : View | RedirectResponse
|
||||
public function show(Asset $asset) : View | RedirectResponse
|
||||
{
|
||||
$asset = Asset::withTrashed()->find($assetId);
|
||||
$this->authorize('view', $asset);
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
if (isset($asset)) {
|
||||
$audit_log = Actionlog::where('action_type', '=', 'audit')
|
||||
->where('item_id', '=', $assetId)
|
||||
->where('item_id', '=', $asset->id)
|
||||
->where('item_type', '=', Asset::class)
|
||||
->orderBy('created_at', 'DESC')->first();
|
||||
|
||||
@@ -291,7 +285,7 @@ class AssetsController extends Controller
|
||||
|
||||
$qr_code = (object) [
|
||||
'display' => $settings->qr_code == '1',
|
||||
'url' => route('qr_code/hardware', $asset->id),
|
||||
'url' => route('qr_code/hardware', $asset),
|
||||
];
|
||||
|
||||
return view('hardware/view', compact('asset', 'qr_code', 'settings'))
|
||||
@@ -308,14 +302,9 @@ class AssetsController extends Controller
|
||||
* @since [v1.0]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $assetId = null) : RedirectResponse
|
||||
public function update(ImageUploadRequest $request, Asset $asset) : RedirectResponse
|
||||
{
|
||||
|
||||
// Check if the asset exists
|
||||
if (! $asset = Asset::find($assetId)) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
$this->authorize($asset);
|
||||
|
||||
$asset->status_id = $request->input('status_id', null);
|
||||
@@ -351,15 +340,14 @@ class AssetsController extends Controller
|
||||
|
||||
$status = Statuslabel::find($request->input('status_id'));
|
||||
|
||||
// This is a non-deployable status label - we should check the asset back in.
|
||||
if (($status && $status->getStatuslabelType() != 'deployable') && ($target = $asset->assignedTo)) {
|
||||
|
||||
// This is an archived or undeployable - we should check the asset back in.
|
||||
// Pending is allowed here
|
||||
if (($status) && (($status->getStatuslabelType() != 'pending') && ($status->getStatuslabelType() != 'deployable')) && ($target = $asset->assignedTo)) {
|
||||
$originalValues = $asset->getRawOriginal();
|
||||
$asset->assigned_to = null;
|
||||
$asset->assigned_type = null;
|
||||
$asset->accepted = null;
|
||||
|
||||
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), 'Checkin on asset update', date('Y-m-d H:i:s'), $originalValues));
|
||||
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), 'Checkin on asset update with '.$status->getStatuslabelType().' status', date('Y-m-d H:i:s'), $originalValues));
|
||||
}
|
||||
|
||||
if ($asset->assigned_to == '') {
|
||||
@@ -430,7 +418,7 @@ class AssetsController extends Controller
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
|
||||
|
||||
if ($asset->save()) {
|
||||
return redirect()->to(Helper::getRedirectOption($request, $assetId, 'Assets'))
|
||||
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
|
||||
->with('success', trans('admin/hardware/message.update.success'));
|
||||
}
|
||||
|
||||
@@ -531,12 +519,12 @@ class AssetsController extends Controller
|
||||
* @param int $assetId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function getQrCode($assetId = null) : Response | BinaryFileResponse | string | bool
|
||||
public function getQrCode(Asset $asset) : Response | BinaryFileResponse | string | bool
|
||||
{
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
if (($settings->qr_code == '1') && ($settings->label2_2d_type !== 'none')) {
|
||||
$asset = Asset::withTrashed()->find($assetId);
|
||||
|
||||
if ($asset) {
|
||||
$size = Helper::barcodeDimensions($settings->label2_2d_type);
|
||||
$qr_file = public_path().'/uploads/barcodes/qr-'.str_slug($asset->asset_tag).'-'.str_slug($asset->id).'.png';
|
||||
@@ -590,7 +578,7 @@ class AssetsController extends Controller
|
||||
file_put_contents($barcode_file, $barcode_obj->getPngData());
|
||||
|
||||
return response($barcode_obj->getPngData())->header('Content-type', 'image/png');
|
||||
} catch (\Exception $e) {
|
||||
} catch (\Exception|TypeError $e) {
|
||||
Log::debug('The barcode format is invalid.');
|
||||
|
||||
return response(file_get_contents(public_path('uploads/barcodes/invalid_barcode.gif')))->header('Content-type', 'image/gif');
|
||||
@@ -877,12 +865,11 @@ class AssetsController extends Controller
|
||||
return view('hardware/quickscan-checkin')->with('statusLabel_list', Helper::statusLabelList());
|
||||
}
|
||||
|
||||
public function audit($id)
|
||||
public function audit(Asset $asset)
|
||||
{
|
||||
$settings = Setting::getSettings();
|
||||
$this->authorize('audit', Asset::class);
|
||||
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
|
||||
$asset = Asset::findOrFail($id);
|
||||
return view('hardware/audit')->with('asset', $asset)->with('next_audit_date', $dt)->with('locations_list');
|
||||
}
|
||||
|
||||
@@ -901,7 +888,7 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
public function auditStore(UploadFileRequest $request, $id)
|
||||
public function auditStore(UploadFileRequest $request, Asset $asset)
|
||||
{
|
||||
$this->authorize('audit', Asset::class);
|
||||
|
||||
@@ -916,8 +903,6 @@ class AssetsController extends Controller
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
|
||||
}
|
||||
|
||||
$asset = Asset::findOrFail($id);
|
||||
|
||||
/**
|
||||
* Even though we do a save() further down, we don't want to log this as a "normal" asset update,
|
||||
* which would trigger the Asset Observer and would log an asset *update* log entry (because the
|
||||
|
||||
@@ -358,7 +358,11 @@ class BulkAssetsController extends Controller
|
||||
* to someone/something.
|
||||
*/
|
||||
if ($request->filled('status_id')) {
|
||||
$updated_status = Statuslabel::find($request->input('status_id'));
|
||||
try {
|
||||
$updated_status = Statuslabel::findOrFail($request->input('status_id'));
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return redirect($bulk_back_url)->with('error', trans('admin/statuslabels/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// We cannot assign a non-deployable status type if the asset is already assigned.
|
||||
// This could probably be added to a form request.
|
||||
@@ -366,7 +370,7 @@ class BulkAssetsController extends Controller
|
||||
// Otherwise we need to make sure the status type is still a deployable one.
|
||||
if (
|
||||
($asset->assigned_to == '')
|
||||
|| ($updated_status->deployable == '1') && ($asset->assetstatus->deployable == '1')
|
||||
|| ($updated_status->deployable == '1') && ($asset->assetstatus?->deployable == '1')
|
||||
) {
|
||||
$this->update_array['status_id'] = $updated_status->id;
|
||||
}
|
||||
@@ -525,21 +529,31 @@ class BulkAssetsController extends Controller
|
||||
$this->authorize('delete', Asset::class);
|
||||
|
||||
$bulk_back_url = route('hardware.index');
|
||||
|
||||
if ($request->session()->has('bulk_back_url')) {
|
||||
$bulk_back_url = $request->session()->pull('bulk_back_url');
|
||||
}
|
||||
$assetIds = $request->get('ids');
|
||||
|
||||
if ($request->filled('ids')) {
|
||||
$assets = Asset::find($request->get('ids'));
|
||||
foreach ($assets as $asset) {
|
||||
$asset->delete();
|
||||
} // endforeach
|
||||
|
||||
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.delete.success'));
|
||||
// no values given, nothing to update
|
||||
if(empty($assetIds)) {
|
||||
return redirect($bulk_back_url)->with('error', trans('admin/hardware/message.delete.nothing_updated'));
|
||||
}
|
||||
|
||||
return redirect($bulk_back_url)->with('error', trans('admin/hardware/message.delete.nothing_updated'));
|
||||
$assignedAssets = Asset::whereIn('id', $assetIds)->whereNotNull('assigned_to')->get();
|
||||
if($assignedAssets->isNotEmpty()) {
|
||||
|
||||
//if assets are checked out, return a list of asset tags that would need to be checked in first.
|
||||
$assetTags = $assignedAssets->pluck('asset_tag')->implode(', ');
|
||||
return redirect($bulk_back_url)->with('error', trans_choice('admin/hardware/message.delete.assigned_to_error', $assignedAssets->count(), ['asset_tag' => $assetTags] ));
|
||||
}
|
||||
|
||||
foreach (Asset::wherein('id', $assetIds)->get() as $asset) {
|
||||
$asset->delete();
|
||||
}
|
||||
|
||||
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.delete.success'));
|
||||
// no values given, nothing to update
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -206,6 +206,7 @@ class LoginController extends Controller
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
$user->last_login = \Carbon::now();
|
||||
$user->email = $ldap_attr['email'];
|
||||
$user->first_name = $ldap_attr['firstname'];
|
||||
$user->last_name = $ldap_attr['lastname']; //FIXME (or TODO?) - do we need to map additional fields that we now support? E.g. country, phone, etc.
|
||||
@@ -432,6 +433,7 @@ class LoginController extends Controller
|
||||
|
||||
if (Google2FA::verifyKey($user->two_factor_secret, $secret)) {
|
||||
$user->two_factor_enrolled = 1;
|
||||
$user->last_login = \Carbon::now();
|
||||
$user->saveQuietly();
|
||||
$request->session()->put('2fa_authed', $user->id);
|
||||
|
||||
|
||||
@@ -88,14 +88,10 @@ class CategoriesController extends Controller
|
||||
* @param int $categoryId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function edit($categoryId = null) : RedirectResponse | View
|
||||
public function edit(Category $category) : RedirectResponse | View
|
||||
{
|
||||
$this->authorize('update', Category::class);
|
||||
if (is_null($item = Category::find($categoryId))) {
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.does_not_exist'));
|
||||
}
|
||||
|
||||
return view('categories/edit', compact('item'))
|
||||
return view('categories/edit')->with('item', $category)
|
||||
->with('category_types', Helper::categoryTypeList());
|
||||
}
|
||||
|
||||
@@ -108,19 +104,10 @@ class CategoriesController extends Controller
|
||||
* @param int $categoryId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $categoryId = null) : RedirectResponse
|
||||
public function update(ImageUploadRequest $request, Category $category) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Category::class);
|
||||
if (is_null($category = Category::find($categoryId))) {
|
||||
// Redirect to the categories management page
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Update the category data
|
||||
$category->name = $request->input('name');
|
||||
// If the item count is > 0, we disable the category type in the edit. Disabled items
|
||||
// don't POST, so if the category_type is blank we just set it to the default.
|
||||
|
||||
|
||||
// Don't allow the user to change the category_type once it's been created
|
||||
if (($request->filled('category_type') && ($category->itemCount() > 0))) {
|
||||
@@ -181,10 +168,10 @@ class CategoriesController extends Controller
|
||||
* @param $id
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function show($id) : View | RedirectResponse
|
||||
public function show(Category $category) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('view', Category::class);
|
||||
if ($category = Category::find($id)) {
|
||||
|
||||
if ($category->category_type == 'asset') {
|
||||
$category_type = 'hardware';
|
||||
$category_type_route = 'assets';
|
||||
@@ -199,8 +186,5 @@ class CategoriesController extends Controller
|
||||
return view('categories/view', compact('category'))
|
||||
->with('category_type', $category_type)
|
||||
->with('category_type_route', $category_type_route);
|
||||
}
|
||||
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.does_not_exist'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -80,16 +80,10 @@ final class CompaniesController extends Controller
|
||||
* @since [v1.8]
|
||||
* @param int $companyId
|
||||
*/
|
||||
public function edit($companyId) : View | RedirectResponse
|
||||
public function edit(Company $company) : View | RedirectResponse
|
||||
{
|
||||
if (is_null($item = Company::find($companyId))) {
|
||||
return redirect()->route('companies.index')
|
||||
->with('error', trans('admin/companies/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $item);
|
||||
|
||||
return view('companies/edit')->with('item', $item);
|
||||
$this->authorize('update', $company);
|
||||
return view('companies/edit')->with('item', $company);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -100,14 +94,10 @@ final class CompaniesController extends Controller
|
||||
* @param ImageUploadRequest $request
|
||||
* @param int $companyId
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $companyId) : RedirectResponse
|
||||
public function update(ImageUploadRequest $request, Company $company) : RedirectResponse
|
||||
{
|
||||
if (is_null($company = Company::find($companyId))) {
|
||||
return redirect()->route('companies.index')->with('error', trans('admin/companies/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $company);
|
||||
|
||||
$company->name = $request->input('name');
|
||||
$company->phone = $request->input('phone');
|
||||
$company->fax = $request->input('fax');
|
||||
@@ -158,15 +148,9 @@ final class CompaniesController extends Controller
|
||||
->with('success', trans('admin/companies/message.delete.success'));
|
||||
}
|
||||
|
||||
public function show($id) : View | RedirectResponse
|
||||
public function show(Company $company) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('view', Company::class);
|
||||
|
||||
if (is_null($company = Company::find($id))) {
|
||||
return redirect()->route('companies.index')
|
||||
->with('error', trans('admin/companies/message.not_found'));
|
||||
}
|
||||
|
||||
return view('companies/view')->with('company', $company);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -107,15 +107,13 @@ class ComponentsController extends Controller
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($componentId = null)
|
||||
public function edit(Component $component)
|
||||
{
|
||||
if ($item = Component::find($componentId)) {
|
||||
$this->authorize('update', $item);
|
||||
|
||||
return view('components/edit', compact('item'))->with('category_type', 'component');
|
||||
}
|
||||
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
|
||||
$this->authorize('update', $component);
|
||||
return view('components/edit')
|
||||
->with('item', $component)
|
||||
->with('category_type', 'component');
|
||||
}
|
||||
|
||||
|
||||
@@ -130,11 +128,8 @@ class ComponentsController extends Controller
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v3.0]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $componentId = null)
|
||||
public function update(ImageUploadRequest $request, Component $component)
|
||||
{
|
||||
if (is_null($component = Component::find($componentId))) {
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
|
||||
}
|
||||
$min = $component->numCheckedOut();
|
||||
$validator = Validator::make($request->all(), [
|
||||
'qty' => "required|numeric|min:$min",
|
||||
@@ -201,6 +196,10 @@ class ComponentsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
if ($component->numCheckedOut() > 0) {
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.delete.error_qty'));
|
||||
}
|
||||
|
||||
$component->delete();
|
||||
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.delete.success'));
|
||||
@@ -216,17 +215,9 @@ class ComponentsController extends Controller
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($componentId = null)
|
||||
public function show(Component $component)
|
||||
{
|
||||
$component = Component::find($componentId);
|
||||
|
||||
if (isset($component->id)) {
|
||||
$this->authorize('view', $component);
|
||||
|
||||
return view('components/view', compact('component'));
|
||||
}
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('components.index')
|
||||
->with('error', trans('admin/components/message.does_not_exist'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,15 +104,13 @@ class ConsumablesController extends Controller
|
||||
* @see ConsumablesController::postEdit() method that stores the form data.
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function edit($consumableId = null) : View | RedirectResponse
|
||||
public function edit(Consumable $consumable) : View | RedirectResponse
|
||||
{
|
||||
if ($item = Consumable::find($consumableId)) {
|
||||
$this->authorize($item);
|
||||
$this->authorize($consumable);
|
||||
return view('consumables/edit')
|
||||
->with('item', $consumable)
|
||||
->with('category_type', 'consumable');
|
||||
|
||||
return view('consumables/edit', compact('item'))->with('category_type', 'consumable');
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -126,11 +124,8 @@ class ConsumablesController extends Controller
|
||||
* @see ConsumablesController::getEdit() method that stores the form data.
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function update(StoreConsumableRequest $request, $consumableId = null)
|
||||
public function update(StoreConsumableRequest $request, Consumable $consumable)
|
||||
{
|
||||
if (is_null($consumable = Consumable::find($consumableId))) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$min = $consumable->numCheckedOut();
|
||||
$validator = Validator::make($request->all(), [
|
||||
@@ -202,16 +197,11 @@ class ConsumablesController extends Controller
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($consumableId = null)
|
||||
public function show(Consumable $consumable)
|
||||
{
|
||||
$consumable = Consumable::withCount('users as users_consumables')->find($consumableId);
|
||||
$consumable = Consumable::withCount('users as users_consumables')->find($consumable->id);
|
||||
$this->authorize($consumable);
|
||||
if (isset($consumable->id)) {
|
||||
return view('consumables/view', compact('consumable'));
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.index')
|
||||
->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
return view('consumables/view', compact('consumable'));
|
||||
}
|
||||
|
||||
public function clone(Consumable $consumable) : View
|
||||
|
||||
@@ -104,6 +104,8 @@ class CustomFieldsController extends Controller
|
||||
"auto_add_to_fieldsets" => $request->get("auto_add_to_fieldsets", 0),
|
||||
"show_in_listview" => $request->get("show_in_listview", 0),
|
||||
"show_in_requestable_list" => $request->get("show_in_requestable_list", 0),
|
||||
"display_checkin" => $request->get("display_checkin", 0),
|
||||
"display_checkout" => $request->get("display_checkout", 0),
|
||||
"created_by" => auth()->id()
|
||||
]);
|
||||
|
||||
@@ -193,10 +195,8 @@ class CustomFieldsController extends Controller
|
||||
* @param int $id
|
||||
* @since [v4.0]
|
||||
*/
|
||||
public function edit(Request $request, $id) : View | RedirectResponse
|
||||
public function edit(Request $request, CustomField $field) : View | RedirectResponse
|
||||
{
|
||||
if ($field = CustomField::find($id)) {
|
||||
|
||||
$this->authorize('update', $field);
|
||||
$fieldsets = CustomFieldset::get();
|
||||
$customFormat = '';
|
||||
@@ -210,11 +210,7 @@ class CustomFieldsController extends Controller
|
||||
'fieldsets' => $fieldsets,
|
||||
'predefinedFormats' => Helper::predefined_formats(),
|
||||
]);
|
||||
}
|
||||
|
||||
return redirect()->route("fields.index")
|
||||
->with("error", trans('admin/custom_fields/message.field.invalid'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -229,13 +225,9 @@ class CustomFieldsController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(CustomFieldRequest $request, $id) : RedirectResponse
|
||||
public function update(CustomFieldRequest $request, CustomField $field) : RedirectResponse
|
||||
{
|
||||
$field = CustomField::find($id);
|
||||
|
||||
$this->authorize('update', $field);
|
||||
|
||||
|
||||
$show_in_email = $request->get("show_in_email", 0);
|
||||
$display_in_user_view = $request->get("display_in_user_view", 0);
|
||||
|
||||
@@ -256,6 +248,8 @@ class CustomFieldsController extends Controller
|
||||
$field->auto_add_to_fieldsets = $request->get("auto_add_to_fieldsets", 0);
|
||||
$field->show_in_listview = $request->get("show_in_listview", 0);
|
||||
$field->show_in_requestable_list = $request->get("show_in_requestable_list", 0);
|
||||
$field->display_checkin = $request->get("display_checkin", 0);
|
||||
$field->display_checkout = $request->get("display_checkout", 0);
|
||||
|
||||
if ($request->get('format') == 'CUSTOM REGEX') {
|
||||
$field->format = e($request->get('custom_format'));
|
||||
|
||||
@@ -35,10 +35,12 @@ class CustomFieldsetsController extends Controller
|
||||
* @param int $id
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function show($id) : View | RedirectResponse
|
||||
public function show(CustomFieldset $fieldset) : View | RedirectResponse
|
||||
{
|
||||
$cfset = CustomFieldset::with('fields')
|
||||
->where('id', '=', $id)->orderBy('id', 'ASC')->first();
|
||||
->where('id', '=', $fieldset->id)
|
||||
->orderBy('id', 'ASC')
|
||||
->first();
|
||||
|
||||
$this->authorize('view', $cfset);
|
||||
|
||||
@@ -122,16 +124,10 @@ class CustomFieldsetsController extends Controller
|
||||
* @param int $id
|
||||
* @since [v6.0.14]
|
||||
*/
|
||||
public function edit($id) : View | RedirectResponse
|
||||
public function edit(CustomFieldset $fieldset) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('create', CustomField::class);
|
||||
|
||||
if ($fieldset = CustomFieldset::find($id)) {
|
||||
return view('custom_fields.fieldsets.edit')->with('item', $fieldset);
|
||||
}
|
||||
|
||||
return redirect()->route('fields.index')->with('error', trans('admin/custom_fields/general.fieldset_does_not_exist', ['id' => $id]));
|
||||
|
||||
return view('custom_fields.fieldsets.edit')->with('item', $fieldset);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -141,23 +137,18 @@ class CustomFieldsetsController extends Controller
|
||||
* @param int $id
|
||||
* @since [v6.0.14]
|
||||
*/
|
||||
public function update(Request $request, $id) : RedirectResponse
|
||||
public function update(Request $request, CustomFieldset $fieldset) : RedirectResponse
|
||||
{
|
||||
$this->authorize('create', CustomField::class);
|
||||
|
||||
if ($fieldset = CustomFieldset::find($id)) {
|
||||
|
||||
$fieldset->name = $request->input('name');
|
||||
|
||||
if ($fieldset->save()) {
|
||||
return redirect()->route('fields.index')->with('success', trans('admin/custom_fields/general.fieldset_updated'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($fieldset->getErrors());
|
||||
$fieldset->name = $request->input('name');
|
||||
|
||||
if ($fieldset->save()) {
|
||||
return redirect()->route('fields.index')->with('success', trans('admin/custom_fields/general.fieldset_updated'));
|
||||
}
|
||||
|
||||
return redirect()->route('fields.index')->with('error', trans('admin/custom_fields/general.fieldset_does_not_exist', ['id' => $id]));
|
||||
return redirect()->back()->withInput()->withErrors($fieldset->getErrors());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -40,7 +40,7 @@ class DashboardController extends Controller
|
||||
|
||||
if ((! file_exists(storage_path().'/oauth-private.key')) || (! file_exists(storage_path().'/oauth-public.key'))) {
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
\Artisan::call('passport:install');
|
||||
Artisan::call('passport:install', ['--no-interaction' => true]);
|
||||
}
|
||||
|
||||
return view('dashboard')->with('asset_stats', $asset_stats)->with('counts', $counts);
|
||||
|
||||
@@ -73,17 +73,10 @@ class DepartmentsController extends Controller
|
||||
* @param int $id
|
||||
* @since [v4.0]
|
||||
*/
|
||||
public function show($id) : View | RedirectResponse
|
||||
public function show(Department $department) : View | RedirectResponse
|
||||
{
|
||||
$department = Department::find($id);
|
||||
|
||||
$this->authorize('view', $department);
|
||||
|
||||
if (isset($department->id)) {
|
||||
return view('departments/view', compact('department'));
|
||||
}
|
||||
|
||||
return redirect()->route('departments.index')->with('error', trans('admin/departments/message.does_not_exist'));
|
||||
return view('departments/view', compact('department'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -139,15 +132,10 @@ class DepartmentsController extends Controller
|
||||
* @param int $departmentId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function edit($departmentId = null) : View | RedirectResponse
|
||||
public function edit(Department $department) : View | RedirectResponse
|
||||
{
|
||||
if (is_null($item = Department::find($departmentId))) {
|
||||
return redirect()->back()->with('error', trans('admin/locations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $item);
|
||||
|
||||
return view('departments/edit', compact('item'));
|
||||
$this->authorize('update', $department);
|
||||
return view('departments/edit')->with('item', $department);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -158,11 +146,8 @@ class DepartmentsController extends Controller
|
||||
* @param int $departmentId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $id) : RedirectResponse
|
||||
public function update(ImageUploadRequest $request, Department $department) : RedirectResponse
|
||||
{
|
||||
if (is_null($department = Department::find($id))) {
|
||||
return redirect()->route('departments.index')->with('error', trans('admin/departments/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $department);
|
||||
|
||||
|
||||
@@ -95,17 +95,11 @@ class DepreciationsController extends Controller
|
||||
* @param int $depreciationId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function edit($depreciationId = null) : RedirectResponse | View
|
||||
public function edit(Depreciation $depreciation) : RedirectResponse | View
|
||||
{
|
||||
// Check if the depreciation exists
|
||||
if (is_null($item = Depreciation::find($depreciationId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $item);
|
||||
|
||||
return view('depreciations/edit', compact('item'));
|
||||
$this->authorize('update', $depreciation);
|
||||
return view('depreciations/edit')->with('item', $depreciation);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,17 +111,10 @@ class DepreciationsController extends Controller
|
||||
* @param int $depreciationId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function update(Request $request, $depreciationId = null) : RedirectResponse
|
||||
public function update(Request $request, Depreciation $depreciation) : RedirectResponse
|
||||
{
|
||||
// Check if the depreciation exists
|
||||
if (is_null($depreciation = Depreciation::find($depreciationId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $depreciation);
|
||||
|
||||
// Depreciation data
|
||||
$depreciation->name = $request->input('name');
|
||||
$depreciation->months = $request->input('months');
|
||||
|
||||
@@ -191,12 +178,12 @@ class DepreciationsController extends Controller
|
||||
* @param int $depreciationId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show($id) : View | RedirectResponse
|
||||
public function show(Depreciation $depreciation) : View | RedirectResponse
|
||||
{
|
||||
$depreciation = Depreciation::withCount('assets as assets_count')
|
||||
->withCount('models as models_count')
|
||||
->withCount('licenses as licenses_count')
|
||||
->find($id);
|
||||
->find($depreciation->id);
|
||||
|
||||
$this->authorize('view', $depreciation);
|
||||
|
||||
|
||||
@@ -79,19 +79,12 @@ class GroupsController extends Controller
|
||||
* @param int $id
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function edit($id) : View | RedirectResponse
|
||||
public function edit(Group $group) : View | RedirectResponse
|
||||
{
|
||||
$group = Group::find($id);
|
||||
|
||||
if ($group) {
|
||||
$permissions = config('permissions');
|
||||
$groupPermissions = $group->decodePermissions();
|
||||
$selected_array = Helper::selectedPermissionsArray($permissions, $groupPermissions);
|
||||
|
||||
return view('groups.edit', compact('group', 'permissions', 'selected_array', 'groupPermissions'));
|
||||
}
|
||||
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', ['id' => $id]));
|
||||
$permissions = config('permissions');
|
||||
$groupPermissions = $group->decodePermissions();
|
||||
$selected_array = Helper::selectedPermissionsArray($permissions, $groupPermissions);
|
||||
return view('groups.edit', compact('group', 'permissions', 'selected_array', 'groupPermissions'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -102,11 +95,8 @@ class GroupsController extends Controller
|
||||
* @param int $id
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function update(Request $request, $id = null) : RedirectResponse
|
||||
public function update(Request $request, Group $group) : RedirectResponse
|
||||
{
|
||||
if (! $group = Group::find($id)) {
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', ['id' => $id]));
|
||||
}
|
||||
$group->name = $request->input('name');
|
||||
$group->permissions = json_encode($request->input('permission'));
|
||||
$group->notes = $request->input('notes');
|
||||
@@ -151,14 +141,8 @@ class GroupsController extends Controller
|
||||
* @param $id
|
||||
* @since [v4.0.11]
|
||||
*/
|
||||
public function show($id) : View | RedirectResponse
|
||||
public function show(Group $group) : View | RedirectResponse
|
||||
{
|
||||
$group = Group::find($id);
|
||||
|
||||
if ($group) {
|
||||
return view('groups/view', compact('group'));
|
||||
}
|
||||
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', ['id' => $id]));
|
||||
return view('groups/view', compact('group'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -4,10 +4,8 @@ namespace App\Http\Controllers\Kits;
|
||||
|
||||
use App\Http\Controllers\CheckInOutRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\PredefinedKit;
|
||||
use App\Models\Asset;
|
||||
use App\Models\PredefinedLicence;
|
||||
use App\Models\PredefinedModel;
|
||||
use App\Models\PredefinedKit;
|
||||
use App\Models\User;
|
||||
use App\Services\PredefinedKitCheckoutService;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -35,12 +33,9 @@ class CheckoutKitController extends Controller
|
||||
* @author [D. Minaev.] [<dmitriy.minaev.v@gmail.com>]
|
||||
* @return \Illuminate\Contracts\View\View View to checkout
|
||||
*/
|
||||
public function showCheckout($kit_id)
|
||||
public function showCheckout(PredefinedKit $kit)
|
||||
{
|
||||
$this->authorize('checkout', Asset::class);
|
||||
|
||||
$kit = PredefinedKit::findOrFail($kit_id);
|
||||
|
||||
return view('kits/checkout')->with('kit', $kit);
|
||||
}
|
||||
|
||||
|
||||
@@ -76,17 +76,15 @@ class PredefinedKitsController extends Controller
|
||||
* @param int $kit_id
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit($kit_id = null)
|
||||
public function edit(PredefinedKit $kit)
|
||||
{
|
||||
$this->authorize('update', PredefinedKit::class);
|
||||
if ($kit = PredefinedKit::find($kit_id)) {
|
||||
|
||||
return view('kits/edit')
|
||||
->with('item', $kit)
|
||||
->with('models', $kit->models)
|
||||
->with('licenses', $kit->licenses);
|
||||
}
|
||||
|
||||
return redirect()->route('kits.index')->with('error', trans('admin/kits/general.kit_none'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -98,15 +96,9 @@ class PredefinedKitsController extends Controller
|
||||
* @param int $kit_id
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $kit_id = null)
|
||||
public function update(ImageUploadRequest $request, PredefinedKit $kit)
|
||||
{
|
||||
$this->authorize('update', PredefinedKit::class);
|
||||
// Check if the kit exists
|
||||
if (is_null($kit = PredefinedKit::find($kit_id))) {
|
||||
// Redirect to the kits management page
|
||||
return redirect()->route('kits.index')->with('error', trans('admin/kits/general.kit_none'));
|
||||
}
|
||||
|
||||
$kit->name = $request->input('name');
|
||||
|
||||
if ($kit->save()) {
|
||||
@@ -153,9 +145,9 @@ class PredefinedKitsController extends Controller
|
||||
* @param int $modelId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show($kit_id = null)
|
||||
public function show(PredefinedKit $kit)
|
||||
{
|
||||
return $this->edit($kit_id);
|
||||
return $this->edit($kit);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -28,16 +28,11 @@ class LicenseCheckinController extends Controller
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($seatId = null, $backTo = null)
|
||||
public function create(LicenseSeat $licenseSeat, $backTo = null)
|
||||
{
|
||||
// Check if the asset exists
|
||||
if (is_null($licenseSeat = LicenseSeat::find($seatId)) || is_null($license = License::find($licenseSeat->license_id))) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
|
||||
$license = License::find($licenseSeat->license_id);
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
return view('licenses/checkin', compact('licenseSeat'))->with('backto', $backTo);
|
||||
}
|
||||
|
||||
|
||||
@@ -28,33 +28,24 @@ class LicenseCheckoutController extends Controller
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($id)
|
||||
public function create(License $license)
|
||||
{
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
if ($license = License::find($id)) {
|
||||
if ($license->category) {
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
if ($license->category) {
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($license->availCount()->count() < 1){
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.not_enough_seats'));
|
||||
}
|
||||
|
||||
// Return the checkout view
|
||||
return view('licenses/checkout', compact('license'));
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($license->availCount()->count() < 1) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.not_enough_seats'));
|
||||
}
|
||||
|
||||
// Invalid category
|
||||
return redirect()->route('licenses.edit', ['license' => $license->id])
|
||||
->with('error', trans('general.invalid_item_category_single', ['type' => trans('general.license')]));
|
||||
|
||||
// Return the checkout view
|
||||
return view('licenses/checkout', compact('license'));
|
||||
}
|
||||
|
||||
// Not found
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
|
||||
// Invalid category
|
||||
return redirect()->route('licenses.edit', ['license' => $license->id])
|
||||
->with('error', trans('general.invalid_item_category_single', ['type' => trans('general.license')]));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -121,13 +121,10 @@ class LicensesController extends Controller
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($licenseId = null)
|
||||
public function edit(License $license)
|
||||
{
|
||||
if (is_null($item = License::find($licenseId))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $item);
|
||||
$this->authorize('update', $license);
|
||||
|
||||
$maintained_list = [
|
||||
'' => 'Maintained',
|
||||
@@ -135,7 +132,8 @@ class LicensesController extends Controller
|
||||
'0' => 'No',
|
||||
];
|
||||
|
||||
return view('licenses/edit', compact('item'))
|
||||
return view('licenses/edit')
|
||||
->with('item', $license)
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('maintained_list', $maintained_list);
|
||||
}
|
||||
@@ -153,11 +151,9 @@ class LicensesController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(Request $request, $licenseId = null)
|
||||
public function update(Request $request, License $license)
|
||||
{
|
||||
if (is_null($license = License::find($licenseId))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
|
||||
$this->authorize('update', $license);
|
||||
|
||||
@@ -201,10 +197,10 @@ class LicensesController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($licenseId)
|
||||
public function destroy(License $license)
|
||||
{
|
||||
// Check if the license exists
|
||||
if (is_null($license = License::find($licenseId))) {
|
||||
if (is_null($license = License::find($license->id))) {
|
||||
// Redirect to the license management page
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
@@ -238,14 +234,9 @@ class LicensesController extends Controller
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($licenseId = null)
|
||||
public function show(License $license)
|
||||
{
|
||||
$license = License::with('assignedusers')->find($licenseId);
|
||||
|
||||
if (!$license) {
|
||||
return redirect()->route('licenses.index')
|
||||
->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
$license = License::with('assignedusers')->find($license->id);
|
||||
|
||||
$users_count = User::where('autoassign_licenses', '1')->count();
|
||||
$total_seats_count = $license->totalSeatsByLicenseID();
|
||||
@@ -267,10 +258,10 @@ class LicensesController extends Controller
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return \Illuminate\Http\RedirectResponse | \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function getClone($licenseId = null)
|
||||
public function getClone($licenseId = null) : \Illuminate\Contracts\View\View | \Illuminate\Http\RedirectResponse
|
||||
{
|
||||
if (is_null($license_to_clone = License::find($licenseId))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
|
||||
@@ -97,15 +97,10 @@ class LocationsController extends Controller
|
||||
* @param int $locationId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function edit($locationId = null) : View | RedirectResponse
|
||||
public function edit(Location $location) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Location::class);
|
||||
// Check if the location exists
|
||||
if (is_null($item = Location::find($locationId))) {
|
||||
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
return view('locations/edit', compact('item'));
|
||||
return view('locations/edit')->with('item', $location);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -117,15 +112,10 @@ class LocationsController extends Controller
|
||||
* @param int $locationId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $locationId = null) : RedirectResponse
|
||||
public function update(ImageUploadRequest $request, Location $location) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Location::class);
|
||||
// Check if the location exists
|
||||
if (is_null($location = Location::find($locationId))) {
|
||||
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Update the location data
|
||||
$location->name = $request->input('name');
|
||||
$location->parent_id = $request->input('parent_id', null);
|
||||
$location->currency = $request->input('currency', '$');
|
||||
@@ -194,7 +184,7 @@ class LocationsController extends Controller
|
||||
* @param int $id
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show($id = null) : View | RedirectResponse
|
||||
public function show(Location $location) : View | RedirectResponse
|
||||
{
|
||||
$location = Location::withCount('assignedAssets as assigned_assets_count')
|
||||
->withCount('assets as assets_count')
|
||||
@@ -202,7 +192,7 @@ class LocationsController extends Controller
|
||||
->withCount('children as children_count')
|
||||
->withCount('users as users_count')
|
||||
->withTrashed()
|
||||
->find($id);
|
||||
->find($location->id);
|
||||
|
||||
if (isset($location->id)) {
|
||||
return view('locations/view', compact('location'));
|
||||
|
||||
@@ -85,18 +85,10 @@ class ManufacturersController extends Controller
|
||||
* @param int $manufacturerId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function edit($manufacturerId = null) : View | RedirectResponse
|
||||
public function edit(Manufacturer $manufacturer) : View | RedirectResponse
|
||||
{
|
||||
// Handles manufacturer checks and permissions.
|
||||
$this->authorize('update', Manufacturer::class);
|
||||
|
||||
// Check if the manufacturer exists
|
||||
if (! $item = Manufacturer::find($manufacturerId)) {
|
||||
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Show the page
|
||||
return view('manufacturers/edit', compact('item'));
|
||||
return view('manufacturers/edit')->with('item', $manufacturer);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -108,16 +100,10 @@ class ManufacturersController extends Controller
|
||||
* @param int $manufacturerId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $manufacturerId = null) : RedirectResponse
|
||||
public function update(ImageUploadRequest $request, Manufacturer $manufacturer) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Manufacturer::class);
|
||||
// Check if the manufacturer exists
|
||||
if (is_null($manufacturer = Manufacturer::find($manufacturerId))) {
|
||||
// Redirect to the manufacturer page
|
||||
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Save the data
|
||||
$manufacturer->name = $request->input('name');
|
||||
$manufacturer->url = $request->input('url');
|
||||
$manufacturer->support_url = $request->input('support_url');
|
||||
@@ -185,18 +171,10 @@ class ManufacturersController extends Controller
|
||||
* @param int $manufacturerId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function show($manufacturerId = null) : View | RedirectResponse
|
||||
public function show(Manufacturer $manufacturer) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('view', Manufacturer::class);
|
||||
$manufacturer = Manufacturer::find($manufacturerId);
|
||||
|
||||
if (isset($manufacturer->id)) {
|
||||
return view('manufacturers/view', compact('manufacturer'));
|
||||
}
|
||||
|
||||
$error = trans('admin/manufacturers/message.does_not_exist');
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('manufacturers.index')->with('error', $error);
|
||||
return view('manufacturers/view', compact('manufacturer'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
42
app/Http/Controllers/NotesController.php
Normal file
42
app/Http/Controllers/NotesController.php
Normal file
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Validation\Rule;
|
||||
|
||||
class NotesController extends Controller
|
||||
{
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
$validated = $request->validate([
|
||||
'id' => 'required',
|
||||
'note' => 'required|string|max:50000',
|
||||
'type' => [
|
||||
'required',
|
||||
Rule::in(['asset']),
|
||||
],
|
||||
]);
|
||||
|
||||
$item = Asset::findOrFail($validated['id']);
|
||||
|
||||
$this->authorize('update', $item);
|
||||
|
||||
$logaction = new Actionlog;
|
||||
$logaction->item_id = $item->id;
|
||||
$logaction->item_type = get_class($item);
|
||||
$logaction->note = $validated['note'];
|
||||
$logaction->created_by = Auth::id();
|
||||
$logaction->logaction('note added');
|
||||
|
||||
return redirect()
|
||||
->route('hardware.show', $validated['id'])
|
||||
->withFragment('history')
|
||||
->with('success', trans('general.note_added'));
|
||||
}
|
||||
}
|
||||
@@ -266,7 +266,7 @@ class ReportsController extends Controller
|
||||
|
||||
$actionlogs = Actionlog::with('item', 'user', 'target', 'location', 'adminuser')
|
||||
->orderBy('created_at', 'DESC')
|
||||
->chunk(20, function ($actionlogs) use ($handle) {
|
||||
->chunk(500, function ($actionlogs) use ($handle) {
|
||||
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
|
||||
Log::debug('Walking results: '.$executionTime);
|
||||
$count = 0;
|
||||
@@ -748,7 +748,7 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
Log::debug($assets->toSql());
|
||||
$assets->orderBy('assets.id', 'ASC')->chunk(20, function ($assets) use ($handle, $customfields, $request) {
|
||||
$assets->orderBy('assets.id', 'ASC')->chunk(500, function ($assets) use ($handle, $customfields, $request) {
|
||||
|
||||
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
|
||||
Log::debug('Walking results: '.$executionTime);
|
||||
@@ -1175,18 +1175,13 @@ class ReportsController extends Controller
|
||||
}
|
||||
$email = $assetItem->assignedTo?->email;
|
||||
$locale = $assetItem->assignedTo?->locale;
|
||||
// Only send notification if assigned
|
||||
if ($locale && $email) {
|
||||
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note))->locale($locale));
|
||||
|
||||
} elseif ($email) {
|
||||
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note)));
|
||||
}
|
||||
|
||||
if ($email == ''){
|
||||
if (is_null($email) || $email === '') {
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.no_email'));
|
||||
}
|
||||
|
||||
Mail::to($email)->send((new CheckoutAssetMail($assetItem, $assetItem->assignedTo, $logItem->user, $acceptance, $logItem->note, firstTimeSending: false))->locale($locale));
|
||||
|
||||
return redirect()->route('reports/unaccepted_assets')->with('success', trans('admin/reports/general.reminder_sent'));
|
||||
}
|
||||
|
||||
|
||||
3
app/Http/Controllers/SettingsController.php
Executable file → Normal file
3
app/Http/Controllers/SettingsController.php
Executable file → Normal file
@@ -256,7 +256,7 @@ class SettingsController extends Controller
|
||||
Artisan::call('migrate', ['--force' => true]);
|
||||
if ((! file_exists(storage_path().'/oauth-private.key')) || (! file_exists(storage_path().'/oauth-public.key'))) {
|
||||
Artisan::call('migrate', ['--path' => 'vendor/laravel/passport/database/migrations', '--force' => true]);
|
||||
Artisan::call('passport:install');
|
||||
Artisan::call('passport:install', ['--no-interaction' => true]);
|
||||
}
|
||||
|
||||
return view('setup/migrate')
|
||||
@@ -851,6 +851,7 @@ class SettingsController extends Controller
|
||||
$setting->ldap_auth_filter_query = $request->input('ldap_auth_filter_query');
|
||||
$setting->ldap_version = $request->input('ldap_version', 3);
|
||||
$setting->ldap_active_flag = $request->input('ldap_active_flag');
|
||||
$setting->ldap_invert_active_flag = $request->input('ldap_invert_active_flag');
|
||||
$setting->ldap_emp_num = $request->input('ldap_emp_num');
|
||||
$setting->ldap_email = $request->input('ldap_email');
|
||||
$setting->ldap_manager = $request->input('ldap_manager');
|
||||
|
||||
@@ -26,14 +26,10 @@ class StatuslabelsController extends Controller
|
||||
return view('statuslabels.index');
|
||||
}
|
||||
|
||||
public function show($id) : View | RedirectResponse
|
||||
public function show(Statuslabel $statuslabel) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
if ($statuslabel = Statuslabel::find($id)) {
|
||||
return view('statuslabels.view')->with('statuslabel', $statuslabel);
|
||||
}
|
||||
|
||||
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist'));
|
||||
return view('statuslabels.view')->with('statuslabel', $statuslabel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -91,20 +87,15 @@ class StatuslabelsController extends Controller
|
||||
*
|
||||
* @param int $statuslabelId
|
||||
*/
|
||||
public function edit($statuslabelId = null) : View | RedirectResponse
|
||||
public function edit(Statuslabel $statuslabel) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Statuslabel::class);
|
||||
// Check if the Statuslabel exists
|
||||
if (is_null($item = Statuslabel::find($statuslabelId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$use_statuslabel_type = $item->getStatuslabelType();
|
||||
|
||||
$statuslabel_types = ['' => trans('admin/hardware/form.select_statustype')] + ['undeployable' => trans('admin/hardware/general.undeployable')] + ['pending' => trans('admin/hardware/general.pending')] + ['archived' => trans('admin/hardware/general.archived')] + ['deployable' => trans('admin/hardware/general.deployable')];
|
||||
|
||||
return view('statuslabels/edit', compact('item', 'statuslabel_types'))->with('use_statuslabel_type', $use_statuslabel_type);
|
||||
return view('statuslabels/edit', compact('statuslabel_types'))
|
||||
->with('item', $statuslabel)
|
||||
->with('use_statuslabel_type', $statuslabel);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -112,14 +103,9 @@ class StatuslabelsController extends Controller
|
||||
*
|
||||
* @param int $statuslabelId
|
||||
*/
|
||||
public function update(Request $request, $statuslabelId = null) : RedirectResponse
|
||||
public function update(Request $request, Statuslabel $statuslabel) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Statuslabel::class);
|
||||
// Check if the Statuslabel exists
|
||||
if (is_null($statuslabel = Statuslabel::find($statuslabelId))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist'));
|
||||
}
|
||||
|
||||
if (! $request->filled('statuslabel_types')) {
|
||||
return redirect()->back()->withInput()->withErrors(['statuslabel_types' => trans('validation.statuslabel_type')]);
|
||||
|
||||
@@ -77,17 +77,10 @@ class SuppliersController extends Controller
|
||||
*
|
||||
* @param int $supplierId
|
||||
*/
|
||||
public function edit($supplierId = null) : View | RedirectResponse
|
||||
public function edit(Supplier $supplier) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Supplier::class);
|
||||
// Check if the supplier exists
|
||||
if (is_null($item = Supplier::find($supplierId))) {
|
||||
// Redirect to the supplier page
|
||||
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Show the page
|
||||
return view('suppliers/edit', compact('item'));
|
||||
return view('suppliers/edit')->with('item', $supplier);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -95,14 +88,9 @@ class SuppliersController extends Controller
|
||||
*
|
||||
* @param int $supplierId
|
||||
*/
|
||||
public function update($supplierId, ImageUploadRequest $request) : RedirectResponse
|
||||
public function update(ImageUploadRequest $request, Supplier $supplier) : RedirectResponse
|
||||
{
|
||||
$this->authorize('update', Supplier::class);
|
||||
|
||||
if (is_null($supplier = Supplier::find($supplierId))) {
|
||||
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Save the data
|
||||
$supplier->name = request('name');
|
||||
$supplier->address = request('address');
|
||||
@@ -163,15 +151,10 @@ class SuppliersController extends Controller
|
||||
* @param null $supplierId
|
||||
* @internal param int $assetId
|
||||
*/
|
||||
public function show($supplierId = null) : View | RedirectResponse
|
||||
public function show(Supplier $supplier) : View | RedirectResponse
|
||||
{
|
||||
$this->authorize('view', Supplier::class);
|
||||
$supplier = Supplier::find($supplierId);
|
||||
return view('suppliers/view', compact('supplier'));
|
||||
|
||||
if (isset($supplier->id)) {
|
||||
return view('suppliers/view', compact('supplier'));
|
||||
}
|
||||
|
||||
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.does_not_exist'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,6 +15,7 @@ use App\Models\ConsumableAssignment;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CurrentInventory;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
@@ -52,6 +53,28 @@ class BulkUsersController extends Controller
|
||||
return view('users/bulk-edit', compact('users'))
|
||||
->with('groups', Group::pluck('name', 'id'));
|
||||
|
||||
// bulk send assigned inventory
|
||||
} elseif ($request->input('bulk_actions') == 'send_assigned') {
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
$users_without_email = 0;
|
||||
foreach ($users as $user) {
|
||||
if (empty($user->email)) {
|
||||
$users_without_email++;
|
||||
} else {
|
||||
$user->notify((new CurrentInventory($user)));
|
||||
}
|
||||
}
|
||||
|
||||
if ($users_without_email == 0) {
|
||||
return redirect()->back()->with('success', trans_choice('admin/users/general.users_notified', $users->count()));
|
||||
} else {
|
||||
return redirect()->back()->with('warning', trans_choice('admin/users/general.users_notified_warning', $users->count(), ['no_email' => $users_without_email]));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// bulk delete, display the bulk delete confirmation form
|
||||
} elseif ($request->input('bulk_actions') == 'delete') {
|
||||
$this->authorize('delete', User::class);
|
||||
|
||||
@@ -22,43 +22,34 @@ class UserFilesController extends Controller
|
||||
*@author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $userId = null)
|
||||
public function store(UploadFileRequest $request, User $user)
|
||||
{
|
||||
$user = User::find($userId);
|
||||
$destinationPath = config('app.private_uploads').'/users';
|
||||
$this->authorize('update', $user);
|
||||
$files = $request->file('file');
|
||||
|
||||
if (isset($user->id)) {
|
||||
$this->authorize('update', $user);
|
||||
|
||||
$logActions = [];
|
||||
$files = $request->file('file');
|
||||
|
||||
if (is_null($files)) {
|
||||
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/users/', 'user-'.$user->id, $file);
|
||||
|
||||
//Log the uploaded file to the log
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->note = $request->input('notes');
|
||||
$logAction->target_id = null;
|
||||
$logAction->created_at = date("Y-m-d H:i:s");
|
||||
$logAction->filename = $file_name;
|
||||
$logAction->action_type = 'uploaded';
|
||||
|
||||
if (! $logAction->save()) {
|
||||
return JsonResponse::create(['error' => 'Failed validation: '.print_r($logAction->getErrors(), true)], 500);
|
||||
}
|
||||
$logActions[] = $logAction;
|
||||
}
|
||||
// dd($logActions);
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.upload.success'));
|
||||
if (is_null($files)) {
|
||||
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
|
||||
}
|
||||
foreach ($files as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/users/', 'user-'.$user->id, $file);
|
||||
|
||||
//Log the uploaded file to the log
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->note = $request->input('notes');
|
||||
$logAction->target_id = null;
|
||||
$logAction->created_at = date("Y-m-d H:i:s");
|
||||
$logAction->filename = $file_name;
|
||||
$logAction->action_type = 'uploaded';
|
||||
|
||||
if (! $logAction->save()) {
|
||||
return JsonResponse::create(['error' => 'Failed validation: '.print_r($logAction->getErrors(), true)], 500);
|
||||
}
|
||||
|
||||
return redirect()->back()->withFragment('files')->with('success', trans('admin/users/message.upload.success'));
|
||||
}
|
||||
return redirect()->back()->with('error', trans('admin/users/message.upload.nofiles'));
|
||||
|
||||
|
||||
}
|
||||
@@ -110,7 +101,7 @@ class UserFilesController extends Controller
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($userId = null, $fileId = null)
|
||||
public function show(User $user, $fileId = null)
|
||||
{
|
||||
|
||||
|
||||
@@ -118,29 +109,21 @@ class UserFilesController extends Controller
|
||||
return redirect()->route('users.show')->with('error', 'Invalid file request');
|
||||
}
|
||||
|
||||
if ($user = User::find($userId)) {
|
||||
|
||||
$this->authorize('view', $user);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $user->id)->find($fileId)) {
|
||||
$file = 'private_uploads/users/'.$log->filename;
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $user->id)->find($fileId)) {
|
||||
$file = 'private_uploads/users/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
|
||||
return redirect()->back()->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
|
||||
// Redirect to the user management page if the user doesn't exist
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', ['id' => $userId]));
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -182,11 +182,11 @@ class UsersController extends Controller
|
||||
* @internal param int $id
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($id)
|
||||
public function edit(User $user)
|
||||
{
|
||||
|
||||
$this->authorize('update', User::class);
|
||||
$user = User::with(['assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc'])->withTrashed()->find($id);
|
||||
$user = User::with(['assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc'])->withTrashed()->find($user->id);
|
||||
|
||||
if ($user) {
|
||||
|
||||
@@ -198,7 +198,7 @@ class UsersController extends Controller
|
||||
$userPermissions = Helper::selectedPermissionsArray($permissions, $user->permissions);
|
||||
$permissions = $this->filterDisplayable($permissions);
|
||||
|
||||
return view('users/edit', compact('user', 'groups', 'userGroups', 'permissions', 'userPermissions'))->with('item', $user);
|
||||
return view('users/edit', compact('user', 'groups', 'userGroups', 'permissions', 'userPermissions'));
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', compact('id')));
|
||||
@@ -324,7 +324,7 @@ class UsersController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy(DeleteUserRequest $request, $id = null)
|
||||
public function destroy(DeleteUserRequest $request, $id)
|
||||
{
|
||||
$this->authorize('delete', User::class);
|
||||
|
||||
@@ -333,13 +333,6 @@ class UsersController extends Controller
|
||||
$this->authorize('delete', $user);
|
||||
|
||||
if ($user->delete()) {
|
||||
if (Storage::disk('public')->exists('avatars/' . $user->avatar)) {
|
||||
try {
|
||||
Storage::disk('public')->delete('avatars/' . $user->avatar);
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e);
|
||||
}
|
||||
}
|
||||
return redirect()->route('users.index')->with('success', trans('admin/users/message.success.delete'));
|
||||
}
|
||||
}
|
||||
@@ -398,23 +391,18 @@ class UsersController extends Controller
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($userId = null)
|
||||
public function show(User $user)
|
||||
{
|
||||
// Make sure the user can view users at all
|
||||
$this->authorize('view', User::class);
|
||||
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($userId);
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($user->id);
|
||||
|
||||
// Make sure they can view this particular user
|
||||
$this->authorize('view', $user);
|
||||
|
||||
if ($user) {
|
||||
$userlog = $user->userlog->load('item');
|
||||
return view('users/view', compact('user', 'userlog'))->with('settings', Setting::getSettings());
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', ['id' => $userId]));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -428,7 +416,7 @@ class UsersController extends Controller
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function getClone(Request $request, $id = null)
|
||||
public function getClone(Request $request, User $user)
|
||||
{
|
||||
$this->authorize('create', User::class);
|
||||
|
||||
@@ -438,7 +426,7 @@ class UsersController extends Controller
|
||||
app('request')->request->set('permissions', $permissions);
|
||||
|
||||
|
||||
$user_to_clone = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id);
|
||||
$user_to_clone = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($user->id);
|
||||
// Make sure they can view this particular user
|
||||
$this->authorize('view', $user_to_clone);
|
||||
|
||||
|
||||
@@ -24,7 +24,7 @@ class DeleteUserRequest extends FormRequest
|
||||
|
||||
public function prepareForValidation(): void
|
||||
{
|
||||
$user_to_delete = User::withTrashed()->find(request()->route('user'));
|
||||
$user_to_delete = User::withTrashed()->with('managesUsers')->find(request()->route('user'));
|
||||
|
||||
if ($user_to_delete) {
|
||||
$this->merge([
|
||||
@@ -61,7 +61,8 @@ class DeleteUserRequest extends FormRequest
|
||||
public function messages(): array
|
||||
{
|
||||
|
||||
$user_to_delete = User::withTrashed()->find(request()->route('user'));
|
||||
$user_to_delete = User::withTrashed()->with('managesUsers')->find(request()->route('user'));
|
||||
|
||||
$messages = [];
|
||||
|
||||
if ($user_to_delete) {
|
||||
|
||||
@@ -26,9 +26,9 @@ class StoreNotificationSettings extends FormRequest
|
||||
return [
|
||||
'alert_email' => 'email_array|nullable',
|
||||
'admin_cc_email' => 'email_array|nullable',
|
||||
'alert_threshold' => 'numeric|nullable|gt:0',
|
||||
'alert_threshold' => 'numeric|nullable',
|
||||
'alert_interval' => 'numeric|nullable|gt:0',
|
||||
'audit_warning_days' => 'numeric|nullable|gt:0',
|
||||
'audit_warning_days' => 'numeric|nullable',
|
||||
'due_checkin_days' => 'numeric|nullable|gt:0',
|
||||
'audit_interval' => 'numeric|nullable|gt:0',
|
||||
];
|
||||
|
||||
@@ -140,13 +140,13 @@ class ActionlogsTransformer
|
||||
} else {
|
||||
if ($actionlog->item) {
|
||||
if ($actionlog->itemType() == 'asset') {
|
||||
$file_url = route('show/assetfile', ['assetId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
$file_url = route('show/assetfile', ['asset' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'accessory') {
|
||||
$file_url = route('show.accessoryfile', ['accessoryId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'license') {
|
||||
$file_url = route('show.licensefile', ['licenseId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
} elseif ($actionlog->itemType() == 'user') {
|
||||
$file_url = route('show/userfile', ['userId' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
$file_url = route('show/userfile', ['user' => $actionlog->item->id, 'fileId' => $actionlog->id]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,6 +309,7 @@ class AssetsTransformer
|
||||
'id' => $accessory_checkout->accessory->id,
|
||||
'name' => $accessory_checkout->accessory->name,
|
||||
],
|
||||
'assigned_to' => $accessory_checkout->assigned_to,
|
||||
'image' => ($accessory_checkout->accessory->image) ? Storage::disk('public')->url('accessories/'.e($accessory_checkout->accessory->image)) : null,
|
||||
'note' => $accessory_checkout->note ? e($accessory_checkout->note) : null,
|
||||
'created_by' => $accessory_checkout->adminuser ? [
|
||||
|
||||
@@ -62,7 +62,7 @@ class ComponentsTransformer
|
||||
'checkout' => Gate::allows('checkout', Component::class),
|
||||
'checkin' => Gate::allows('checkin', Component::class),
|
||||
'update' => Gate::allows('update', Component::class),
|
||||
'delete' => Gate::allows('delete', Component::class),
|
||||
'delete' => $component->isDeletable(),
|
||||
];
|
||||
$array += $permissions_array;
|
||||
|
||||
|
||||
@@ -100,6 +100,7 @@ class LocationsTransformer
|
||||
|
||||
$array = [
|
||||
'id' => $accessory_checkout->id,
|
||||
'assigned_to' => $accessory_checkout->assigned_to,
|
||||
'accessory' => [
|
||||
'id' => $accessory_checkout->accessory->id,
|
||||
'name' => $accessory_checkout->accessory->name,
|
||||
|
||||
@@ -1,81 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\LegacyEncrypter;
|
||||
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
|
||||
abstract class BaseEncrypter
|
||||
{
|
||||
/**
|
||||
* The encryption key.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $key;
|
||||
|
||||
/**
|
||||
* Create a MAC for the given value.
|
||||
*
|
||||
* @param string $iv
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function hash($iv, $value)
|
||||
{
|
||||
return hash_hmac('sha256', $iv.$value, $this->key);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the JSON array from the given payload.
|
||||
*
|
||||
* @param string $payload
|
||||
* @return array
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Encryption\DecryptException
|
||||
*/
|
||||
protected function getJsonPayload($payload)
|
||||
{
|
||||
$payload = json_decode(base64_decode($payload), true);
|
||||
|
||||
// If the payload is not valid JSON or does not have the proper keys set we will
|
||||
// assume it is invalid and bail out of the routine since we will not be able
|
||||
// to decrypt the given value. We'll also check the MAC for this encryption.
|
||||
if (! $payload || $this->invalidPayload($payload)) {
|
||||
throw new DecryptException('The payload is invalid.');
|
||||
}
|
||||
|
||||
if (! $this->validMac($payload)) {
|
||||
throw new DecryptException('The MAC is invalid.');
|
||||
}
|
||||
|
||||
return $payload;
|
||||
}
|
||||
|
||||
/**
|
||||
* Verify that the encryption payload is valid.
|
||||
*
|
||||
* @param array|mixed $data
|
||||
* @return bool
|
||||
*/
|
||||
protected function invalidPayload($data)
|
||||
{
|
||||
return ! is_array($data) || ! isset($data['iv']) || ! isset($data['value']) || ! isset($data['mac']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the MAC for the given payload is valid.
|
||||
*
|
||||
* @param array $payload
|
||||
* @return bool
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
protected function validMac(array $payload)
|
||||
{
|
||||
$bytes = random_bytes(16);
|
||||
|
||||
$calcMac = hash_hmac('sha256', $this->hash($payload['iv'], $payload['value']), $bytes, true);
|
||||
|
||||
return hash_equals(hash_hmac('sha256', $payload['mac'], $bytes, true), $calcMac);
|
||||
}
|
||||
}
|
||||
@@ -1,214 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\LegacyEncrypter;
|
||||
|
||||
use Exception;
|
||||
use Illuminate\Contracts\Encryption\DecryptException;
|
||||
use Illuminate\Contracts\Encryption\Encrypter as EncrypterContract;
|
||||
use Illuminate\Contracts\Encryption\EncryptException;
|
||||
use RuntimeException;
|
||||
|
||||
/**
|
||||
* @deprecated since version 5.1. Use Illuminate\Encryption\Encrypter.
|
||||
*/
|
||||
class McryptEncrypter extends BaseEncrypter implements EncrypterContract
|
||||
{
|
||||
/**
|
||||
* The algorithm used for encryption.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $cipher;
|
||||
|
||||
/**
|
||||
* The block size of the cipher.
|
||||
*
|
||||
* @var int
|
||||
*/
|
||||
protected $block;
|
||||
|
||||
/**
|
||||
* Create a new encrypter instance.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $cipher
|
||||
* @return void
|
||||
*
|
||||
* @throws \RuntimeException
|
||||
*/
|
||||
public function __construct($key, $cipher = MCRYPT_RIJNDAEL_128)
|
||||
{
|
||||
$key = (string) $key;
|
||||
|
||||
if (static::supported($key, $cipher)) {
|
||||
$this->key = $key;
|
||||
$this->cipher = $cipher;
|
||||
$this->block = mcrypt_get_iv_size($this->cipher, MCRYPT_MODE_CBC);
|
||||
} else {
|
||||
throw new RuntimeException('The only supported ciphers are MCRYPT_RIJNDAEL_128 and MCRYPT_RIJNDAEL_256.');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given key and cipher combination is valid.
|
||||
*
|
||||
* @param string $key
|
||||
* @param string $cipher
|
||||
* @return bool
|
||||
*/
|
||||
public static function supported($key, $cipher)
|
||||
{
|
||||
return defined('MCRYPT_RIJNDAEL_128') &&
|
||||
($cipher === MCRYPT_RIJNDAEL_128 || $cipher === MCRYPT_RIJNDAEL_256);
|
||||
}
|
||||
|
||||
/**
|
||||
* Encrypt the given value.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Encryption\EncryptException
|
||||
*/
|
||||
public function encrypt($value, $serialize = true)
|
||||
{
|
||||
$iv = mcrypt_create_iv($this->getIvSize(), $this->getRandomizer());
|
||||
|
||||
$value = base64_encode($this->padAndMcrypt($value, $iv));
|
||||
|
||||
// Once we have the encrypted value we will go ahead base64_encode the input
|
||||
// vector and create the MAC for the encrypted value so we can verify its
|
||||
// authenticity. Then, we'll JSON encode the data in a "payload" array.
|
||||
$mac = $this->hash($iv = base64_encode($iv), $value);
|
||||
|
||||
$json = json_encode(compact('iv', 'value', 'mac'));
|
||||
|
||||
if (! is_string($json)) {
|
||||
throw new EncryptException('Could not encrypt the data.');
|
||||
}
|
||||
|
||||
return base64_encode($json);
|
||||
}
|
||||
|
||||
/**
|
||||
* Pad and use mcrypt on the given value and input vector.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $iv
|
||||
* @return string
|
||||
*/
|
||||
protected function padAndMcrypt($value, $iv)
|
||||
{
|
||||
$value = $this->addPadding(serialize($value));
|
||||
|
||||
return mcrypt_encrypt($this->cipher, $this->key, $value, MCRYPT_MODE_CBC, $iv);
|
||||
}
|
||||
|
||||
/**
|
||||
* Decrypt the given value.
|
||||
*
|
||||
* @param string $payload
|
||||
* @return string
|
||||
*/
|
||||
public function decrypt($payload, $unserialize = true)
|
||||
{
|
||||
$payload = $this->getJsonPayload($payload);
|
||||
|
||||
// We'll go ahead and remove the PKCS7 padding from the encrypted value before
|
||||
// we decrypt it. Once we have the de-padded value, we will grab the vector
|
||||
// and decrypt the data, passing back the unserialized from of the value.
|
||||
$value = base64_decode($payload['value']);
|
||||
|
||||
$iv = base64_decode($payload['iv']);
|
||||
|
||||
return unserialize($this->stripPadding($this->mcryptDecrypt($value, $iv)));
|
||||
}
|
||||
|
||||
/**
|
||||
* Run the mcrypt decryption routine for the value.
|
||||
*
|
||||
* @param string $value
|
||||
* @param string $iv
|
||||
* @return string
|
||||
*
|
||||
* @throws \Illuminate\Contracts\Encryption\DecryptException
|
||||
*/
|
||||
protected function mcryptDecrypt($value, $iv)
|
||||
{
|
||||
try {
|
||||
return mcrypt_decrypt($this->cipher, $this->key, $value, MCRYPT_MODE_CBC, $iv);
|
||||
} catch (Exception $e) {
|
||||
throw new DecryptException($e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Add PKCS7 padding to a given value.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function addPadding($value)
|
||||
{
|
||||
$pad = $this->block - (strlen($value) % $this->block);
|
||||
|
||||
return $value.str_repeat(chr($pad), $pad);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the padding from the given value.
|
||||
*
|
||||
* @param string $value
|
||||
* @return string
|
||||
*/
|
||||
protected function stripPadding($value)
|
||||
{
|
||||
$pad = ord($value[($len = strlen($value)) - 1]);
|
||||
|
||||
return $this->paddingIsValid($pad, $value) ? substr($value, 0, $len - $pad) : $value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the given padding for a value is valid.
|
||||
*
|
||||
* @param string $pad
|
||||
* @param string $value
|
||||
* @return bool
|
||||
*/
|
||||
protected function paddingIsValid($pad, $value)
|
||||
{
|
||||
$beforePad = strlen($value) - $pad;
|
||||
|
||||
return substr($value, $beforePad) == str_repeat(substr($value, -1), $pad);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the IV size for the cipher.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getIvSize()
|
||||
{
|
||||
return mcrypt_get_iv_size($this->cipher, MCRYPT_MODE_CBC);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the random data source available for the OS.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
protected function getRandomizer()
|
||||
{
|
||||
if (defined('MCRYPT_DEV_URANDOM')) {
|
||||
return MCRYPT_DEV_URANDOM;
|
||||
}
|
||||
|
||||
if (defined('MCRYPT_DEV_RANDOM')) {
|
||||
return MCRYPT_DEV_RANDOM;
|
||||
}
|
||||
|
||||
mt_srand();
|
||||
|
||||
return MCRYPT_RAND;
|
||||
}
|
||||
}
|
||||
@@ -115,7 +115,7 @@ class CheckoutableListener
|
||||
}
|
||||
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) .trans('admin/settings/message.webhook.webhook_fail') );
|
||||
} catch (Exception $e) {
|
||||
Log::error(ucfirst(Setting::getSettings()->webhook_selected) . ' webhook notification failed:', [
|
||||
Log::warning(ucfirst(Setting::getSettings()->webhook_selected) . ' webhook notification failed:', [
|
||||
'error' => $e->getMessage(),
|
||||
'webhook_endpoint' => Setting::getSettings()->webhook_endpoint,
|
||||
'event' => $event,
|
||||
@@ -211,7 +211,7 @@ class CheckoutableListener
|
||||
return redirect()->back()->with('warning', ucfirst(Setting::getSettings()->webhook_selected) . trans('admin/settings/message.webhook.webhook_fail'));
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Log::error(ucfirst(Setting::getSettings()->webhook_selected) . ' webhook notification failed:', [
|
||||
Log::warning(ucfirst(Setting::getSettings()->webhook_selected) . ' webhook notification failed:', [
|
||||
'error' => $e->getMessage(),
|
||||
'webhook_endpoint' => Setting::getSettings()->webhook_endpoint,
|
||||
'event' => $event,
|
||||
|
||||
@@ -17,7 +17,6 @@ use App\Events\ItemAccepted;
|
||||
use App\Events\ItemDeclined;
|
||||
use App\Events\LicenseCheckedIn;
|
||||
use App\Events\LicenseCheckedOut;
|
||||
use App\Events\NoteAdded;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use App\Models\LicenseSeat;
|
||||
@@ -129,23 +128,6 @@ class LogListener
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Note is added to action log
|
||||
*
|
||||
*/
|
||||
public function onNoteAdded(NoteAdded $event)
|
||||
{
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_id = $event->itemNoteAddedOn->id;
|
||||
$logaction->item_type = get_class($event->itemNoteAddedOn);
|
||||
$logaction->note = $event->note; //this is the received alphanumeric text from the box
|
||||
$logaction->created_by = $event->noteAddedBy->id;
|
||||
$logaction->action_type = 'note_added';
|
||||
$logaction->save();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Register the listeners for the subscriber.
|
||||
*
|
||||
|
||||
@@ -12,11 +12,11 @@ class CategoryEditForm extends Component
|
||||
|
||||
public $originalSendCheckInEmailValue;
|
||||
|
||||
public $requireAcceptance;
|
||||
public bool $requireAcceptance;
|
||||
|
||||
public $sendCheckInEmail;
|
||||
public bool $sendCheckInEmail;
|
||||
|
||||
public $useDefaultEula;
|
||||
public bool $useDefaultEula;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
|
||||
@@ -20,10 +20,12 @@ class CheckoutAssetMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
private bool $firstTimeSending;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $acceptance, $note)
|
||||
public function __construct(Asset $asset, $checkedOutTo, User $checkedOutBy, $acceptance, $note, bool $firstTimeSending = true)
|
||||
{
|
||||
$this->item = $asset;
|
||||
$this->admin = $checkedOutBy;
|
||||
@@ -36,6 +38,8 @@ class CheckoutAssetMail extends Mailable
|
||||
$this->last_checkout = '';
|
||||
$this->expected_checkin = '';
|
||||
|
||||
$this->firstTimeSending = $firstTimeSending;
|
||||
|
||||
if ($this->item->last_checkout) {
|
||||
$this->last_checkout = Helper::getFormattedDateObject($this->item->last_checkout, 'date',
|
||||
false);
|
||||
@@ -56,7 +60,7 @@ class CheckoutAssetMail extends Mailable
|
||||
|
||||
return new Envelope(
|
||||
from: $from,
|
||||
subject: trans('mail.Asset_Checkout_Notification'),
|
||||
subject: $this->getSubject(),
|
||||
);
|
||||
}
|
||||
|
||||
@@ -107,4 +111,13 @@ class CheckoutAssetMail extends Mailable
|
||||
{
|
||||
return [];
|
||||
}
|
||||
|
||||
private function getSubject(): string
|
||||
{
|
||||
if ($this->firstTimeSending) {
|
||||
return trans('mail.Asset_Checkout_Notification');
|
||||
}
|
||||
|
||||
return trans('mail.unaccepted_asset_reminder');
|
||||
}
|
||||
}
|
||||
|
||||
65
app/Mail/SendUpcomingAuditMail.php
Normal file
65
app/Mail/SendUpcomingAuditMail.php
Normal file
@@ -0,0 +1,65 @@
|
||||
<?php
|
||||
|
||||
namespace App\Mail;
|
||||
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Mail\Mailable;
|
||||
use Illuminate\Mail\Mailables\Address;
|
||||
use Illuminate\Mail\Mailables\Content;
|
||||
use Illuminate\Mail\Mailables\Envelope;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class SendUpcomingAuditMail extends Mailable
|
||||
{
|
||||
use Queueable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new message instance.
|
||||
*/
|
||||
public function __construct($params, $threshold)
|
||||
{
|
||||
$this->assets = $params;
|
||||
$this->threshold = $threshold;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message envelope.
|
||||
*/
|
||||
public function envelope(): Envelope
|
||||
{
|
||||
$from = new Address(config('mail.from.address'), config('mail.from.name'));
|
||||
|
||||
return new Envelope(
|
||||
from: $from,
|
||||
subject: trans_choice('mail.upcoming-audits', $this->assets->count(), ['count' => $this->assets->count(), 'threshold' => $this->threshold]),
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the message content definition.
|
||||
*/
|
||||
public function content(): Content
|
||||
{
|
||||
|
||||
|
||||
return new Content(
|
||||
|
||||
markdown: 'notifications.markdown.upcoming-audits',
|
||||
with: [
|
||||
'assets' => $this->assets,
|
||||
'threshold' => $this->threshold,
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the attachments for the message.
|
||||
*
|
||||
* @return array<int, \Illuminate\Mail\Mailables\Attachment>
|
||||
*/
|
||||
public function attachments(): array
|
||||
{
|
||||
return [];
|
||||
}
|
||||
}
|
||||
@@ -19,9 +19,10 @@ class UnacceptedAssetReminderMail extends Mailable
|
||||
*/
|
||||
public function __construct($checkout_info, $count)
|
||||
{
|
||||
|
||||
$this->count = $count;
|
||||
$this->target = $checkout_info['acceptance']?->assignedTo;
|
||||
$this->acceptance = $checkout_info['acceptance'];
|
||||
$this->target = $checkout_info?->assignedTo;
|
||||
$this->acceptance = $checkout_info;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -57,7 +57,7 @@ class AccessoryCheckout extends Model
|
||||
*/
|
||||
public function adminuser()
|
||||
{
|
||||
return $this->hasOne(\App\Models\User::class, 'created_by');
|
||||
return $this->hasOne(\App\Models\User::class, 'id', 'created_by');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -118,7 +118,7 @@ class AccessoryCheckout extends Model
|
||||
$query->where('assigned_type', '=', Location::class);
|
||||
}
|
||||
|
||||
public function scopeAssetAssigned(Builder $query): void
|
||||
public function scopeAssetsAssigned(Builder $query): void
|
||||
{
|
||||
$query->where('assigned_type', '=', Asset::class);
|
||||
}
|
||||
|
||||
@@ -293,16 +293,22 @@ class Actionlog extends SnipeModel
|
||||
public function daysUntilNextAudit($monthInterval = 12, $asset = null)
|
||||
{
|
||||
$now = Carbon::now();
|
||||
$last_audit_date = $this->created_at;
|
||||
$next_audit = $last_audit_date->addMonth($monthInterval);
|
||||
$next_audit_days = $now->diffInDays($next_audit);
|
||||
$last_audit_date = $this->created_at; // this is the action log's created at, not the asset itself
|
||||
$next_audit = $last_audit_date->addMonth($monthInterval); // this actually *modifies* the $last_audit_date
|
||||
$next_audit_days = round($now->diffInDays($next_audit, true));
|
||||
$override_default_next = $next_audit;
|
||||
|
||||
// Override the default setting for interval if the asset has its own next audit date
|
||||
if (($asset) && ($asset->next_audit_date)) {
|
||||
$override_default_next = \Carbon::parse($asset->next_audit_date);
|
||||
$next_audit_days = $override_default_next->diffInDays($now);
|
||||
$override_default_next = Carbon::parse($asset->next_audit_date);
|
||||
$next_audit_days = round($override_default_next->diffInDays($now, true));
|
||||
}
|
||||
|
||||
// Show as negative number if the next audit date is before the audit date we're looking at
|
||||
if ($this->created_at > $override_default_next) {
|
||||
$next_audit_days = '-'.$next_audit_days;
|
||||
}
|
||||
|
||||
return $next_audit_days;
|
||||
}
|
||||
|
||||
|
||||
@@ -413,6 +413,17 @@ class Asset extends Depreciable
|
||||
return $this->rules;
|
||||
}
|
||||
|
||||
public function customFieldsForCheckinCheckout($checkin_checkout) {
|
||||
// Check to see if any of the custom fields were included on the form and if they have any values
|
||||
if (($this->model) && ($this->model->fieldset) && ($this->model->fieldset->fields)) {
|
||||
foreach ($this->model->fieldset->fields as $field) {
|
||||
if (($field->{$checkin_checkout} == 1) && (request()->has($field->db_column))){
|
||||
$this->{$field->db_column} = request()->get($field->db_column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the asset -> depreciation relationship
|
||||
@@ -523,6 +534,18 @@ class Asset extends Depreciable
|
||||
return $this->morphMany(self::class, 'assigned', 'assigned_type', 'assigned_to')->withTrashed();
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the accessory -> asset assignment relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function assignedAccessories()
|
||||
{
|
||||
return $this->morphMany(\App\Models\AccessoryCheckout::class, 'assigned', 'assigned_type', 'assigned_to');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the asset's location based on the assigned user
|
||||
|
||||
@@ -234,7 +234,7 @@ class AssetModel extends SnipeModel
|
||||
*/
|
||||
public function adminuser()
|
||||
{
|
||||
return $this->belongsTo(\App\Models\User::class, 'created_by');
|
||||
return $this->belongsTo(\App\Models\User::class, 'created_by')->withTrashed();
|
||||
}
|
||||
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
/**
|
||||
@@ -104,6 +105,13 @@ class Component extends SnipeModel
|
||||
];
|
||||
|
||||
|
||||
public function isDeletable()
|
||||
{
|
||||
return Gate::allows('delete', $this)
|
||||
&& ($this->numCheckedOut() === 0)
|
||||
&& ($this->deleted_at == '');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the components -> action logs -> uploads relationship
|
||||
*
|
||||
@@ -234,13 +242,24 @@ class Component extends SnipeModel
|
||||
// In case there are elements checked out to assets that belong to a different company
|
||||
// than this asset and full multiple company support is on we'll remove the global scope,
|
||||
// so they are included in the count.
|
||||
foreach ($this->assets()->withoutGlobalScope(new CompanyableScope)->get() as $checkout) {
|
||||
$checkedout += $checkout->pivot->assigned_qty;
|
||||
}
|
||||
|
||||
return $checkedout;
|
||||
return $this->uncontrainedAssets->sum('pivot.assigned_qty');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return \Illuminate\Database\Eloquent\Relations\BelongsToMany
|
||||
*
|
||||
* This allows us to get the assets with assigned components without the company restriction
|
||||
*/
|
||||
public function uncontrainedAssets() {
|
||||
|
||||
return $this->belongsToMany(\App\Models\Asset::class, 'components_assets')
|
||||
->withPivot('id', 'assigned_qty', 'created_at', 'created_by', 'note')
|
||||
->withoutGlobalScope(new CompanyableScope);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check how many items within a component are remaining
|
||||
*
|
||||
|
||||
@@ -149,11 +149,6 @@ class CustomField extends Model
|
||||
return true;
|
||||
}
|
||||
|
||||
// This is just a dumb thing we have to include because Laraval/Doctrine doesn't
|
||||
// play well with enums or a table that EVER had enums. :(
|
||||
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
|
||||
$platform->registerDoctrineTypeMapping('enum', 'string');
|
||||
|
||||
// Rename the field if the name has changed
|
||||
Schema::table(self::$table_name, function ($table) use ($custom_field) {
|
||||
$table->renameColumn($custom_field->convertUnicodeDbSlug($custom_field->getOriginal('name')), $custom_field->convertUnicodeDbSlug());
|
||||
|
||||
@@ -34,7 +34,11 @@ trait Loggable
|
||||
*/
|
||||
public function logCheckout($note, $target, $action_date = null, $originalValues = [])
|
||||
{
|
||||
|
||||
$log = new Actionlog;
|
||||
|
||||
$fields_array = [];
|
||||
|
||||
$log = $this->determineLogItemType($log);
|
||||
if (auth()->user()) {
|
||||
$log->created_by = auth()->id();
|
||||
@@ -55,6 +59,7 @@ trait Loggable
|
||||
$log->target_type = get_class($target);
|
||||
$log->target_id = $target->id;
|
||||
|
||||
|
||||
// Figure out what the target is
|
||||
if ($log->target_type == Location::class) {
|
||||
$log->location_id = $target->id;
|
||||
@@ -64,6 +69,21 @@ trait Loggable
|
||||
$log->location_id = $target->location_id;
|
||||
}
|
||||
|
||||
if (static::class == Asset::class) {
|
||||
if ($asset = Asset::find($log->item_id)) {
|
||||
|
||||
// add the custom fields that were changed
|
||||
if ($asset->model->fieldset) {
|
||||
$fields_array = [];
|
||||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
if ($field->display_checkout == 1) {
|
||||
$fields_array[$field->db_column] = $asset->{$field->db_column};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$log->note = $note;
|
||||
$log->action_date = $action_date;
|
||||
|
||||
@@ -72,7 +92,10 @@ trait Loggable
|
||||
}
|
||||
|
||||
$changed = [];
|
||||
$originalValues = array_intersect_key($originalValues, array_flip(['action_date','name','status_id','location_id','expected_checkin']));
|
||||
$array_to_flip = array_keys($fields_array);
|
||||
$array_to_flip = array_merge($array_to_flip, ['action_date','name','status_id','location_id','expected_checkin']);
|
||||
$originalValues = array_intersect_key($originalValues, array_flip($array_to_flip));
|
||||
|
||||
|
||||
foreach ($originalValues as $key => $value) {
|
||||
if ($key == 'action_date' && $value != $action_date) {
|
||||
@@ -119,6 +142,8 @@ trait Loggable
|
||||
{
|
||||
$log = new Actionlog;
|
||||
|
||||
$fields_array = [];
|
||||
|
||||
if($target != null){
|
||||
$log->target_type = get_class($target);
|
||||
$log->target_id = $target->id;
|
||||
@@ -135,6 +160,16 @@ trait Loggable
|
||||
if (static::class == Asset::class) {
|
||||
if ($asset = Asset::find($log->item_id)) {
|
||||
$asset->increment('checkin_counter', 1);
|
||||
|
||||
// add the custom fields that were changed
|
||||
if ($asset->model->fieldset) {
|
||||
$fields_array = [];
|
||||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
if ($field->display_checkin == 1) {
|
||||
$fields_array[$field->db_column] = $asset->{$field->db_column};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -152,9 +187,14 @@ trait Loggable
|
||||
}
|
||||
|
||||
$changed = [];
|
||||
$originalValues = array_intersect_key($originalValues, array_flip(['action_date','name','status_id','location_id','rtd_location_id','expected_checkin']));
|
||||
|
||||
$array_to_flip = array_keys($fields_array);
|
||||
$array_to_flip = array_merge($array_to_flip, ['action_date','name','status_id','location_id','expected_checkin']);
|
||||
|
||||
$originalValues = array_intersect_key($originalValues, array_flip($array_to_flip));
|
||||
|
||||
foreach ($originalValues as $key => $value) {
|
||||
|
||||
if ($key == 'action_date' && $value != $action_date) {
|
||||
$changed[$key]['old'] = $value;
|
||||
$changed[$key]['new'] = is_string($action_date) ? $action_date : $action_date->format('Y-m-d H:i:s');
|
||||
|
||||
@@ -20,6 +20,7 @@ class AssetAuditPresenter extends Presenter
|
||||
[
|
||||
'field' => 'checkbox',
|
||||
'checkbox' => true,
|
||||
'titleTooltip' => trans('general.select_all_none'),
|
||||
],
|
||||
[
|
||||
'field' => 'id',
|
||||
|
||||
@@ -22,6 +22,15 @@ class AssetMaintenancesPresenter extends Presenter
|
||||
'title' => trans('general.id'),
|
||||
'visible' => false,
|
||||
], [
|
||||
'field' => 'title',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.name'),
|
||||
'visible' => true,
|
||||
'formatter' => 'maintenancesLinkFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'company',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
@@ -81,12 +90,6 @@ class AssetMaintenancesPresenter extends Presenter
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'title' => trans('admin/asset_maintenances/form.asset_maintenance_type'),
|
||||
], [
|
||||
'field' => 'title',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => false,
|
||||
'title' => trans('admin/asset_maintenances/form.title'),
|
||||
], [
|
||||
'field' => 'start_date',
|
||||
'searchable' => true,
|
||||
|
||||
@@ -15,6 +15,7 @@ class AssetModelPresenter extends Presenter
|
||||
[
|
||||
'field' => 'checkbox',
|
||||
'checkbox' => true,
|
||||
'titleTooltip' => trans('general.select_all_none'),
|
||||
],
|
||||
[
|
||||
'field' => 'id',
|
||||
|
||||
@@ -21,6 +21,7 @@ class AssetPresenter extends Presenter
|
||||
[
|
||||
'field' => 'checkbox',
|
||||
'checkbox' => true,
|
||||
'titleTooltip' => trans('general.select_all_none'),
|
||||
], [
|
||||
'field' => 'id',
|
||||
'searchable' => false,
|
||||
@@ -35,7 +36,7 @@ class AssetPresenter extends Presenter
|
||||
'switchable' => true,
|
||||
'title' => trans('general.company'),
|
||||
'visible' => false,
|
||||
'formatter' => 'assetCompanyObjFilterFormatter',
|
||||
'formatter' => 'companiesLinkObjFormatter',
|
||||
], [
|
||||
'field' => 'name',
|
||||
'searchable' => true,
|
||||
@@ -352,6 +353,74 @@ class AssetPresenter extends Presenter
|
||||
return json_encode($layout);
|
||||
}
|
||||
|
||||
|
||||
public static function assignedAccessoriesDataTableLayout()
|
||||
{
|
||||
$layout = [
|
||||
[
|
||||
'field' => 'id',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.id'),
|
||||
'visible' => false,
|
||||
],
|
||||
[
|
||||
'field' => 'accessory',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.accessory'),
|
||||
'visible' => true,
|
||||
'formatter' => 'accessoriesLinkObjFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'image',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.image'),
|
||||
'visible' => true,
|
||||
'formatter' => 'imageFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'note',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.notes'),
|
||||
'visible' => true,
|
||||
],
|
||||
[
|
||||
'field' => 'created_at',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/hardware/table.checkout_date'),
|
||||
'visible' => true,
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'created_by',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'title' => trans('general.created_by'),
|
||||
'visible' => false,
|
||||
'formatter' => 'usersLinkObjFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'available_actions',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => false,
|
||||
'title' => trans('table.actions'),
|
||||
'formatter' => 'accessoriesInOutFormatter',
|
||||
],
|
||||
];
|
||||
|
||||
return json_encode($layout);
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate html link to this items name.
|
||||
* @return string
|
||||
|
||||
@@ -102,13 +102,13 @@ class LocationPresenter extends Presenter
|
||||
'titleTooltip' => trans('general.people'),
|
||||
'visible' => true,
|
||||
'class' => 'css-house-user',
|
||||
// 'data-tooltip' => true, - not working, but I want to try to use regular tooltips here
|
||||
], [
|
||||
'field' => 'currency',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.currency'),
|
||||
'title' => trans('general.currency_text'),
|
||||
'titleTooltip' => trans('general.currency_text'),
|
||||
'visible' => true,
|
||||
'class' => 'css-currency',
|
||||
], [
|
||||
|
||||
@@ -28,7 +28,7 @@ class StatusLabelPresenter extends Presenter
|
||||
'switchable' => false,
|
||||
'title' => trans('general.name'),
|
||||
'visible' => true,
|
||||
'formatter' => 'statuslabelsAssetLinkFormatter',
|
||||
'formatter' => 'statuslabelsLinkFormatter',
|
||||
],[
|
||||
'field' => 'type',
|
||||
'searchable' => false,
|
||||
|
||||
@@ -24,6 +24,7 @@ class UserPresenter extends Presenter
|
||||
[
|
||||
'field' => 'checkbox',
|
||||
'checkbox' => true,
|
||||
'titleTooltip' => trans('general.select_all_none'),
|
||||
],
|
||||
[
|
||||
'field' => 'id',
|
||||
|
||||
@@ -87,9 +87,9 @@ class AuthServiceProvider extends ServiceProvider
|
||||
]);
|
||||
|
||||
$this->registerPolicies();
|
||||
Passport::tokensExpireIn(Carbon::now()->addYears(config('passport.expiration_years')));
|
||||
Passport::refreshTokensExpireIn(Carbon::now()->addYears(config('passport.expiration_years')));
|
||||
Passport::personalAccessTokensExpireIn(Carbon::now()->addYears(config('passport.expiration_years')));
|
||||
Passport::tokensExpireIn(Carbon::now()->addYears((int)config('passport.expiration_years')));
|
||||
Passport::refreshTokensExpireIn(Carbon::now()->addYears((int)config('passport.expiration_years')));
|
||||
Passport::personalAccessTokensExpireIn(Carbon::now()->addYears((int)config('passport.expiration_years')));
|
||||
|
||||
Passport::cookie(config('passport.cookie_name'));
|
||||
|
||||
|
||||
555
app/Providers/BreadcrumbsServiceProvider.php
Normal file
555
app/Providers/BreadcrumbsServiceProvider.php
Normal file
@@ -0,0 +1,555 @@
|
||||
<?php namespace App\Providers;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetMaintenance;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
use App\Models\Company;
|
||||
use App\Models\Component;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
use App\Models\Department;
|
||||
use App\Models\Depreciation;
|
||||
use App\Models\Group;
|
||||
use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\Location;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\PredefinedKit;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Tabuna\Breadcrumbs\Breadcrumbs;
|
||||
use Tabuna\Breadcrumbs\Trail;
|
||||
|
||||
class BreadcrumbsServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Handles the resource routes for first-class objects
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function boot()
|
||||
{
|
||||
|
||||
// Default home
|
||||
Breadcrumbs::for('home', fn (Trail $trail) =>
|
||||
$trail->push('<x-icon type="home" /><span class="sr-only">'.trans('general.dashboard').'</span>', route('home'))
|
||||
);
|
||||
|
||||
/**
|
||||
* Asset Breadcrumbs
|
||||
*/
|
||||
|
||||
|
||||
if ((request()->is('hardware*')) && (request()->status!='')) {
|
||||
Breadcrumbs::for('hardware.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.assets'), route('hardware.index'))
|
||||
->push(request()->status.' '.trans('general.assets'), route('hardware.index', ['status' => request()->status]))
|
||||
);
|
||||
|
||||
} else {
|
||||
Breadcrumbs::for('hardware.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.assets'), route('hardware.index'))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
Breadcrumbs::for('hardware.create', fn (Trail $trail) =>
|
||||
$trail->parent('hardware.index', route('hardware.index'))
|
||||
->push(trans('general.create'), route('hardware.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('hardware.show', fn (Trail $trail, Asset $asset) =>
|
||||
$trail->parent('hardware.index', route('hardware.index'))
|
||||
->push($asset->present()->fullName(), route('hardware.show', $asset))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('hardware.edit', fn (Trail $trail, Asset $asset) =>
|
||||
$trail->parent('hardware.index', route('hardware.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $asset->asset_tag]), route('hardware.edit', $asset))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Asset Model Breadcrumbs
|
||||
*/
|
||||
|
||||
if ((request()->is('models*')) && (request()->status=='deleted')) {
|
||||
Breadcrumbs::for('models.index', fn (Trail $trail) =>
|
||||
$trail->parent('hardware.index', route('hardware.index'))
|
||||
->push(trans('general.asset_models'), route('models.index'))
|
||||
->push(trans('general.deleted_models'), route('models.index', ['status' => request()->status]))
|
||||
);
|
||||
} else {
|
||||
Breadcrumbs::for('models.index', fn (Trail $trail) =>
|
||||
$trail->parent('hardware.index', route('hardware.index'))
|
||||
->push(trans('general.asset_models'), route('models.index'))
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
Breadcrumbs::for('models.create', fn (Trail $trail) =>
|
||||
$trail->parent('models.index', route('models.index'))
|
||||
->push(trans('general.create'), route('models.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('models.show', fn (Trail $trail, AssetModel $model) =>
|
||||
$trail->parent('models.index', route('models.index'))
|
||||
->push($model->name, route('models.show', $model))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('models.edit', fn (Trail $trail, AssetModel $model) =>
|
||||
$trail->parent('models.index', route('models.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $model->name]), route('models.edit', $model))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Accessories Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('accessories.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.accessories'), route('accessories.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('accessories.create', fn (Trail $trail) =>
|
||||
$trail->parent('accessories.index', route('accessories.index'))
|
||||
->push(trans('general.create'), route('accessories.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('accessories.show', fn (Trail $trail, Accessory $accessory) =>
|
||||
$trail->parent('accessories.index', route('accessories.index'))
|
||||
->push($accessory->name, route('accessories.show', $accessory))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('accessories.edit', fn (Trail $trail, Accessory $accessory) =>
|
||||
$trail->parent('accessories.index', route('accessories.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $accessory->name]), route('accessories.edit', $accessory))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Categories Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('categories.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.categories'), route('categories.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('categories.create', fn (Trail $trail) =>
|
||||
$trail->parent('categories.index', route('categories.index'))
|
||||
->push(trans('general.create'), route('categories.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('categories.show', fn (Trail $trail, Category $category) =>
|
||||
$trail->parent('categories.index', route('categories.index'))
|
||||
->push($category->name, route('categories.show', $category))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('categories.edit', fn (Trail $trail, Category $category) =>
|
||||
$trail->parent('categories.index', route('categories.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $category->name]), route('categories.edit', $category))
|
||||
);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Company Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('companies.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.companies'), route('companies.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('companies.create', fn (Trail $trail) =>
|
||||
$trail->parent('companies.index', route('companies.index'))
|
||||
->push(trans('general.create'), route('companies.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('companies.show', fn (Trail $trail, Company $company) =>
|
||||
$trail->parent('companies.index', route('companies.index'))
|
||||
->push($company->name, route('companies.show', $company))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('companies.edit', fn (Trail $trail, Company $company) =>
|
||||
$trail->parent('companies.index', route('companies.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $company->name]), route('companies.edit', $company))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Components Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('components.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.components'), route('components.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('components.create', fn (Trail $trail) =>
|
||||
$trail->parent('components.index', route('components.index'))
|
||||
->push(trans('general.create'), route('components.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('components.show', fn (Trail $trail, Component $component) =>
|
||||
$trail->parent('components.index', route('components.index'))
|
||||
->push($component->name, route('components.show', $component))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('components.edit', fn (Trail $trail, Component $component) =>
|
||||
$trail->parent('components.index', route('components.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $component->name]), route('components.edit', $component))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Consumables Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('consumables.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.consumables'), route('consumables.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('consumables.create', fn (Trail $trail) =>
|
||||
$trail->parent('consumables.index', route('consumables.index'))
|
||||
->push(trans('general.create'), route('consumables.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('consumables.show', fn (Trail $trail, Consumable $consumable) =>
|
||||
$trail->parent('consumables.index', route('consumables.index'))
|
||||
->push($consumable->name, route('consumables.show', $consumable))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('consumables.edit', fn (Trail $trail, Consumable $consumable) =>
|
||||
$trail->parent('consumables.index', route('consumables.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $consumable->name]), route('consumables.edit', $consumable))
|
||||
);
|
||||
|
||||
/**
|
||||
* Custom fields Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('fields.index', fn (Trail $trail) =>
|
||||
$trail->parent('models.index', route('models.index'))
|
||||
->push(trans('admin/custom_fields/general.custom_fields'), route('fields.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('fields.create', fn (Trail $trail) =>
|
||||
$trail->parent('fields.index', route('fields.index'))
|
||||
->push(trans('general.create'), route('fields.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('fields.edit', fn (Trail $trail, CustomField $field) =>
|
||||
$trail->parent('fields.index', route('fields.index'))
|
||||
->push($field->name, route('fields.edit', $field))
|
||||
);
|
||||
|
||||
/**
|
||||
* Custom fieldsets Breadcrumbs
|
||||
*/
|
||||
|
||||
Breadcrumbs::for('fieldsets.create', fn (Trail $trail) =>
|
||||
$trail->parent('fields.index', route('fields.index'))
|
||||
->push(trans('general.create'), route('fieldsets.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('fieldsets.show', fn (Trail $trail, CustomFieldset $fieldset) =>
|
||||
$trail->parent('fields.index', route('fields.index'))
|
||||
->push($fieldset->name, route('fields.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('fieldsets.edit', fn (Trail $trail, CustomFieldset $fieldset) =>
|
||||
$trail->parent('fields.index', route('fields.index'))
|
||||
->push($fieldset->name, route('fieldsets.edit', $fieldset))
|
||||
);
|
||||
|
||||
/**
|
||||
* Department Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('departments.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.departments'), route('departments.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('departments.create', fn (Trail $trail) =>
|
||||
$trail->parent('departments.index', route('departments.index'))
|
||||
->push(trans('general.create'), route('departments.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('departments.show', fn (Trail $trail, Department $department) =>
|
||||
$trail->parent('departments.index', route('departments.index'))
|
||||
->push($department->name, route('home'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('departments.edit', fn (Trail $trail, Department $department) =>
|
||||
$trail->parent('departments.index', route('departments.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $department->name]), route('departments.edit', $department))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Department Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('depreciations.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.depreciations'), route('depreciations.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('depreciations.create', fn (Trail $trail) =>
|
||||
$trail->parent('depreciations.index', route('depreciations.index'))
|
||||
->push(trans('general.create'), route('depreciations.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('depreciations.show', fn (Trail $trail, Depreciation $depreciation) =>
|
||||
$trail->parent('depreciations.index', route('depreciations.index'))
|
||||
->push($depreciation->name, route('depreciations.show', $depreciation))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('depreciations.edit', fn (Trail $trail, Depreciation $depreciation) =>
|
||||
$trail->parent('depreciations.index', route('depreciations.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $depreciation->name]), route('depreciations.edit', $depreciation))
|
||||
);
|
||||
|
||||
/**
|
||||
* Groups Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('groups.index', fn (Trail $trail) =>
|
||||
$trail->parent('settings.index', route('settings.index'))
|
||||
->push(trans('general.groups'), route('groups.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('groups.create', fn (Trail $trail) =>
|
||||
$trail->parent('groups.index', route('groups.index'))
|
||||
->push(trans('general.create'), route('groups.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('groups.show', fn (Trail $trail, Group $group) =>
|
||||
$trail->parent('groups.index', route('groups.index'))
|
||||
->push($group->name, route('groups.show', $group))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('groups.edit', fn (Trail $trail, Group $group) =>
|
||||
$trail->parent('groups.index', route('groups.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $group->name]), route('groups.edit', $group))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Licenses Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('licenses.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.licenses'), route('licenses.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('licenses.create', fn (Trail $trail) =>
|
||||
$trail->parent('licenses.index', route('licenses.index'))
|
||||
->push(trans('general.create'), route('licenses.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('licenses.show', fn (Trail $trail, License $license) =>
|
||||
$trail->parent('licenses.index', route('licenses.index'))
|
||||
->push($license->name, route('licenses.show', $license))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('licenses.edit', fn (Trail $trail, License $license) =>
|
||||
$trail->parent('licenses.index', route('licenses.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $license->name]), route('licenses.edit', $license))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Locations Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('locations.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.locations'), route('locations.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('locations.create', fn (Trail $trail) =>
|
||||
$trail->parent('locations.index', route('locations.index'))
|
||||
->push(trans('general.create'), route('locations.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('locations.show', fn (Trail $trail, Location $location) =>
|
||||
$trail->parent('locations.index', route('locations.index'))
|
||||
->push($location->name, route('locations.show', $location))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('locations.edit', fn (Trail $trail, Location $location) =>
|
||||
$trail->parent('locations.index', route('locations.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $location->name]), route('locations.edit', $location))
|
||||
);
|
||||
|
||||
/**
|
||||
* Maintenances Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('maintenances.index', fn (Trail $trail) =>
|
||||
$trail->parent('hardware.index', route('hardware.index'))
|
||||
->push(trans('general.maintenances'), route('maintenances.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('maintenances.create', fn (Trail $trail) =>
|
||||
$trail->parent('maintenances.index', route('maintenances.index'))
|
||||
->push(trans('general.create'), route('maintenances.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('maintenances.show', fn (Trail $trail, AssetMaintenance $maintenance) =>
|
||||
$trail->parent('maintenances.index', route('locations.index'))
|
||||
->push($maintenance->title, route('maintenances.show', $maintenance))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('manufacturers.edit', fn (Trail $trail, Manufacturer $manufacturer) =>
|
||||
$trail->parent('manufacturers.index', route('manufacturers.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $manufacturer->name]), route('manufacturers.edit', $manufacturer))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Manufacturers Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('manufacturers.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.manufacturers'), route('manufacturers.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('manufacturers.create', fn (Trail $trail) =>
|
||||
$trail->parent('manufacturers.index', route('manufacturers.index'))
|
||||
->push(trans('general.create'), route('manufacturers.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('manufacturers.show', fn (Trail $trail, Manufacturer $manufacturer) =>
|
||||
$trail->parent('manufacturers.index', route('manufacturers.index'))
|
||||
->push($manufacturer->name, route('home'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('manufacturers.edit', fn (Trail $trail, Manufacturer $manufacturer) =>
|
||||
$trail->parent('manufacturers.index', route('manufacturers.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $manufacturer->name]), route('manufacturers.edit', $manufacturer))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Predefined Kits Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('kits.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.kits'), route('kits.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('kits.create', fn (Trail $trail) =>
|
||||
$trail->parent('kits.index', route('kits.index'))
|
||||
->push(trans('general.create'), route('kits.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('kits.show', fn (Trail $trail, PredefinedKit $kit) =>
|
||||
$trail->parent('kits.index', route('kits.index'))
|
||||
->push($kit->name, route('kits.show', $kit))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('kits.edit', fn (Trail $trail, PredefinedKit $kit) =>
|
||||
$trail->parent('kits.index', route('kits.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $kit->name]), route('kits.edit', $kit))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Status Labels Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('statuslabels.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.status_labels'), route('statuslabels.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('statuslabels.create', fn (Trail $trail) =>
|
||||
$trail->parent('statuslabels.index', route('statuslabels.index'))
|
||||
->push(trans('general.create'), route('statuslabels.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('statuslabels.show', fn (Trail $trail, Statuslabel $statuslabel) =>
|
||||
$trail->parent('statuslabels.index', route('statuslabels.index'))
|
||||
->push($statuslabel->name, route('statuslabels.show', $statuslabel))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('statuslabels.edit', fn (Trail $trail, Statuslabel $statuslabel) =>
|
||||
$trail->parent('statuslabels.index', route('statuslabels.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $statuslabel->name]), route('statuslabels.edit', $statuslabel))
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
* Settings Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('settings.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.admin'), route('settings.index'))
|
||||
);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Suppliers Breadcrumbs
|
||||
*/
|
||||
Breadcrumbs::for('suppliers.index', fn (Trail $trail) =>
|
||||
$trail->parent('home', route('home'))
|
||||
->push(trans('general.suppliers'), route('suppliers.index'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('suppliers.create', fn (Trail $trail) =>
|
||||
$trail->parent('suppliers.index', route('suppliers.index'))
|
||||
->push(trans('general.create'), route('suppliers.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('suppliers.show', fn (Trail $trail, Supplier $supplier) =>
|
||||
$trail->parent('suppliers.index', route('suppliers.index'))
|
||||
->push($supplier->name, route('home'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('suppliers.edit', fn (Trail $trail, Supplier $supplier) =>
|
||||
$trail->parent('suppliers.index', route('suppliers.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $supplier->name]), route('suppliers.edit', $supplier))
|
||||
);
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Users Breadcrumbs
|
||||
*/
|
||||
if ((request()->is('users*')) && (request()->status=='deleted')) {
|
||||
Breadcrumbs::for('users.index', fn(Trail $trail) => $trail->parent('home', route('home'))
|
||||
->push(trans('general.users'), route('users.index'))
|
||||
->push(trans('general.deleted_users'), route('users.index'))
|
||||
);
|
||||
} else {
|
||||
Breadcrumbs::for('users.index', fn(Trail $trail) => $trail->parent('home', route('home'))
|
||||
->push(trans('general.users'), route('users.index'))
|
||||
);
|
||||
}
|
||||
|
||||
Breadcrumbs::for('users.create', fn (Trail $trail) =>
|
||||
$trail->parent('users.index', route('users.index'))
|
||||
->push(trans('general.create'), route('users.create'))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('users.show', fn (Trail $trail, User $user) =>
|
||||
$trail->parent('users.index', route('users.index'))
|
||||
->push($user->username, route('users.show', $user))
|
||||
);
|
||||
|
||||
Breadcrumbs::for('users.edit', fn (Trail $trail, User $user) =>
|
||||
$trail->parent('users.index', route('users.index'))
|
||||
->push(trans('general.breadcrumb_button_actions.edit_item', ['name' => $user->name]), route('users.edit', $user))
|
||||
);
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -49,10 +49,6 @@ class SamlServiceProvider extends ServiceProvider
|
||||
'uses' => 'Auth\SamlController@login', ]
|
||||
);
|
||||
|
||||
Route::group(['prefix' => 'admin', 'middleware' => ['web', 'auth', 'authorize:superuser']], function () {
|
||||
Route::get('saml', ['as' => 'settings.saml.index', 'uses' => 'SettingsController@getSamlSettings']);
|
||||
Route::post('saml', ['as' => 'settings.saml.save', 'uses' => 'SettingsController@postSamlSettings']);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
@@ -140,8 +140,8 @@ class Label implements View
|
||||
$barcode2DTarget = $asset->serial;
|
||||
break;
|
||||
case 'hardware_id':
|
||||
default:
|
||||
$barcode2DTarget = route('hardware.show', ['hardware' => $asset->id]);
|
||||
default:
|
||||
$barcode2DTarget = route('hardware.show', $asset);
|
||||
break;
|
||||
}
|
||||
$assetData->put('barcode2d', (object)[
|
||||
|
||||
@@ -70,6 +70,7 @@
|
||||
"rollbar/rollbar-laravel": "^8.0",
|
||||
"spatie/laravel-backup": "^8.8",
|
||||
"spatie/laravel-ignition": "^2.0",
|
||||
"tabuna/breadcrumbs": "^4.2",
|
||||
"tecnickcom/tc-lib-barcode": "^1.15",
|
||||
"tecnickcom/tcpdf": "^6.5",
|
||||
"unicodeveloper/laravel-password": "^1.0",
|
||||
|
||||
68
composer.lock
generated
68
composer.lock
generated
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "8229576658d67211b967e98b5629224f",
|
||||
"content-hash": "87742cc73d186f6f47627ad498cf0fe5",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alek13/slack",
|
||||
@@ -11011,6 +11011,72 @@
|
||||
],
|
||||
"time": "2024-11-08T15:48:14+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tabuna/breadcrumbs",
|
||||
"version": "4.2.1",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tabuna/breadcrumbs.git",
|
||||
"reference": "1d9047306f67e7fcc86fc7e608f1432f247636da"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/tabuna/breadcrumbs/zipball/1d9047306f67e7fcc86fc7e608f1432f247636da",
|
||||
"reference": "1d9047306f67e7fcc86fc7e608f1432f247636da",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"laravel/framework": "^10.0|^11.0",
|
||||
"laravel/serializable-closure": "^1.0|^2.0",
|
||||
"php": "^8.1"
|
||||
},
|
||||
"require-dev": {
|
||||
"orchestra/testbench": "^8.0|^9.0",
|
||||
"phpunit/php-code-coverage": "^10.|^11.0",
|
||||
"phpunit/phpunit": "^10.5|^11.0"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"laravel": {
|
||||
"aliases": {
|
||||
"Breadcrumbs": "Tabuna\\Breadcrumbs\\Breadcrumbs"
|
||||
},
|
||||
"providers": [
|
||||
"Tabuna\\Breadcrumbs\\BreadcrumbsServiceProvider"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Tabuna\\Breadcrumbs\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Alexandr Chernyaev",
|
||||
"email": "bliz48rus@gmail.com"
|
||||
},
|
||||
{
|
||||
"name": "Dwight Watson",
|
||||
"email": "dwight@studentservices.com.au"
|
||||
},
|
||||
{
|
||||
"name": "Dave James Miller",
|
||||
"email": "dave@davejamesmiller.com"
|
||||
}
|
||||
],
|
||||
"description": "An easy way to add breadcrumbs to your Laravel app.",
|
||||
"support": {
|
||||
"issues": "https://github.com/tabuna/breadcrumbs/issues",
|
||||
"source": "https://github.com/tabuna/breadcrumbs/tree/4.2.1"
|
||||
},
|
||||
"time": "2024-11-26T12:21:27+00:00"
|
||||
},
|
||||
{
|
||||
"name": "tecnickcom/tc-lib-barcode",
|
||||
"version": "1.18.4",
|
||||
|
||||
@@ -242,7 +242,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'min_php' => '8.1.2',
|
||||
'min_php' => '8.2.0',
|
||||
|
||||
|
||||
/*
|
||||
@@ -316,6 +316,7 @@ return [
|
||||
App\Providers\LivewireServiceProvider::class,
|
||||
App\Providers\MacroServiceProvider::class,
|
||||
App\Providers\SamlServiceProvider::class,
|
||||
App\Providers\BreadcrumbsServiceProvider::class,
|
||||
|
||||
],
|
||||
|
||||
|
||||
@@ -105,4 +105,17 @@ $config = [
|
||||
// (by default, the PUBLIC_FILESYSTEM DISK is 'local_public', in the public/uploads directory)
|
||||
$config['disks']['public'] = $config['disks'][env('PUBLIC_FILESYSTEM_DISK','local_public')];
|
||||
|
||||
// Handle the 'backup' disk for S3 consideration
|
||||
if (env('PRIVATE_FILESYSTEM_DISK') == 's3_private') {
|
||||
$config['disks']['backup']['driver'] = 's3';
|
||||
$config['disks']['backup']['key'] = $config['disks']['s3_private']['key'];
|
||||
$config['disks']['backup']['secret'] = $config['disks']['s3_private']['secret'];
|
||||
$config['disks']['backup']['region'] = $config['disks']['s3_private']['region'];
|
||||
$config['disks']['backup']['bucket'] = $config['disks']['s3_private']['bucket'];
|
||||
$config['disks']['backup']['url'] = $config['disks']['s3_private']['url'];
|
||||
$config['disks']['backup']['root'] = $config['disks']['s3_private']['root'];
|
||||
$config['disks']['backup']['visibility'] = 'private';
|
||||
}
|
||||
|
||||
|
||||
return $config;
|
||||
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
return array (
|
||||
'app_version' => 'v7.1.16',
|
||||
'full_app_version' => 'v7.1.16 - build 16564-gfb857ccf5',
|
||||
'build_version' => '16564',
|
||||
'app_version' => 'v8.0.2',
|
||||
'full_app_version' => 'v8.0.2 - build 17048-g44dd06161',
|
||||
'build_version' => '17048',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => 'gfb857ccf5',
|
||||
'full_hash' => 'v7.1.16-510-gfb857ccf5',
|
||||
'hash_version' => 'g44dd06161',
|
||||
'full_hash' => 'v8.0.2-54-g44dd06161',
|
||||
'branch' => 'develop',
|
||||
);
|
||||
@@ -27,6 +27,10 @@ class CheckoutAcceptanceFactory extends Factory
|
||||
public function configure(): static
|
||||
{
|
||||
return $this->afterCreating(function (CheckoutAcceptance $acceptance) {
|
||||
if ($acceptance->checkoutable instanceof Asset) {
|
||||
$this->createdAssociatedActionLogEntry($acceptance);
|
||||
}
|
||||
|
||||
if ($acceptance->checkoutable instanceof Asset && $acceptance->assignedTo instanceof User) {
|
||||
$acceptance->checkoutable->update([
|
||||
'assigned_to' => $acceptance->assigned_to_id,
|
||||
@@ -51,4 +55,23 @@ class CheckoutAcceptanceFactory extends Factory
|
||||
'declined_at' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
public function accepted()
|
||||
{
|
||||
return $this->state([
|
||||
'accepted_at' => now()->subDay(),
|
||||
'declined_at' => null,
|
||||
]);
|
||||
}
|
||||
|
||||
private function createdAssociatedActionLogEntry(CheckoutAcceptance $acceptance): void
|
||||
{
|
||||
$acceptance->checkoutable->assetlog()->create([
|
||||
'action_type' => 'checkout',
|
||||
'target_id' => $acceptance->assigned_to_id,
|
||||
'target_type' => get_class($acceptance->assignedTo),
|
||||
'item_id' => $acceptance->checkoutable_id,
|
||||
'item_type' => $acceptance->checkoutable_type,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,8 +12,8 @@ class AddSoftDeletedToLog extends Migration
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
|
||||
$platform->registerDoctrineTypeMapping('enum', 'string');
|
||||
//$platform = Schema::getConnection()->getDoctrineSchemaManager()->getDatabasePlatform();
|
||||
//$platform->registerDoctrineTypeMapping('enum', 'string');
|
||||
|
||||
Schema::table('asset_logs', function ($table) {
|
||||
$table->string('asset_type', 100)->nullable()->change();
|
||||
|
||||
@@ -14,7 +14,7 @@ class ChangeLicenseNotesType extends Migration
|
||||
{
|
||||
//
|
||||
Schema::table('licenses', function ($table) {
|
||||
$table->text('notes')->change();
|
||||
$table->text('notes')->nullable()->change();
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user