Compare commits
4 Commits
refactor_s
...
pagination
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
276950072f | ||
|
|
52344c5574 | ||
|
|
8cfca8bff7 | ||
|
|
f400b38c9c |
@@ -3154,69 +3154,6 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "r-xyz",
|
||||
"name": "r-xyz",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/100710244?v=4",
|
||||
"profile": "https://github.com/r-xyz",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "DrekiDegga",
|
||||
"name": "Steven Mainor",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/47491036?v=4",
|
||||
"profile": "https://github.com/DrekiDegga",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "arne-kroeger",
|
||||
"name": "arne-kroeger",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/65785975?v=4",
|
||||
"profile": "https://github.com/arne-kroeger",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Glukose1",
|
||||
"name": "Glukose1",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/167117705?v=4",
|
||||
"profile": "https://github.com/Glukose1",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Scarzy",
|
||||
"name": "Scarzy",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1197791?v=4",
|
||||
"profile": "https://github.com/Scarzy",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "setpill",
|
||||
"name": "setpill",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/37372069?v=4",
|
||||
"profile": "https://github.com/setpill",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "swift2512",
|
||||
"name": "swift2512",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/3755203?v=4",
|
||||
"profile": "https://github.com/swift2512",
|
||||
"contributions": [
|
||||
"bug"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
# --------------------------------------------
|
||||
# REQUIRED: DB SETUP
|
||||
# --------------------------------------------
|
||||
# https://mariadb.com/kb/en/mariadb-server-docker-official-image-environment-variables/
|
||||
|
||||
MYSQL_DATABASE=snipeit
|
||||
MYSQL_USER=snipeit
|
||||
MYSQL_PASSWORD=changeme1234
|
||||
|
||||
@@ -14,7 +14,7 @@ APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
|
||||
APP_URL=http://localhost:8000
|
||||
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones - TZ identifier
|
||||
APP_TIMEZONE='UTC'
|
||||
APP_LOCALE=en-US
|
||||
APP_LOCALE=en
|
||||
MAX_RESULTS=500
|
||||
|
||||
# --------------------------------------------
|
||||
@@ -97,7 +97,7 @@ API_TOKEN_EXPIRATION_YEARS=40
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SECURITY HEADER SETTINGS
|
||||
# --------------------------------------------
|
||||
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1,172.16.0.0/12
|
||||
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1,172.0.0.0/8
|
||||
ALLOW_IFRAMING=false
|
||||
REFERRER_POLICY=same-origin
|
||||
ENABLE_CSP=false
|
||||
|
||||
@@ -6,7 +6,7 @@ APP_DEBUG=false
|
||||
APP_KEY=base64:hTUIUh9CP6dQx+6EjSlfWTgbaMaaRvlpEwk45vp+xmk=
|
||||
APP_URL=http://127.0.0.1:8000
|
||||
APP_TIMEZONE='US/Eastern'
|
||||
APP_LOCALE=en-US
|
||||
APP_LOCALE=en
|
||||
APP_LOCKED=false
|
||||
MAX_RESULTS=200
|
||||
|
||||
|
||||
@@ -32,8 +32,6 @@ DB_PREFIX=null
|
||||
DB_DUMP_PATH='/usr/bin'
|
||||
DB_CHARSET=utf8mb4
|
||||
DB_COLLATION=utf8mb4_unicode_ci
|
||||
DB_SANITIZE_BY_DEFAULT=false
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SSL DATABASE SETTINGS
|
||||
@@ -89,7 +87,6 @@ SESSION_LIFETIME=12000
|
||||
EXPIRE_ON_CLOSE=false
|
||||
ENCRYPT=false
|
||||
COOKIE_NAME=snipeit_session
|
||||
PASSPORT_COOKIE_NAME='snipeit_passport_token'
|
||||
COOKIE_DOMAIN=null
|
||||
SECURE_COOKIES=false
|
||||
API_TOKEN_EXPIRATION_YEARS=15
|
||||
|
||||
43
.github/stale.yml
vendored
Normal file
43
.github/stale.yml
vendored
Normal file
@@ -0,0 +1,43 @@
|
||||
# Number of days of inactivity before an issue becomes stale
|
||||
daysUntilStale: 60
|
||||
# Number of days of inactivity before a stale issue is closed
|
||||
daysUntilClose: 7
|
||||
# Issues with these labels will never be considered stale
|
||||
exemptLabels:
|
||||
- pinned
|
||||
- security
|
||||
- :woman_technologist: ready for dev
|
||||
- :moneybag: bounty
|
||||
- :hand: bug
|
||||
- "🔐 security"
|
||||
- "👩💻 ready for dev"
|
||||
- "💰 bounty"
|
||||
- "✋ bug"
|
||||
|
||||
exemptMilestones: true
|
||||
|
||||
# Label to use when marking an issue as stale
|
||||
staleLabel: stale
|
||||
|
||||
only: issues
|
||||
|
||||
# Comment to post when removing the stale label.
|
||||
unmarkComment: >
|
||||
Okay, it looks like this issue or feature request might still be important. We'll re-open
|
||||
it for now. Thank you for letting us know!
|
||||
|
||||
# Comment to post when marking an issue as stale. Set to `false` to disable
|
||||
markComment: >
|
||||
Is this still relevant? We haven't heard from anyone in a bit. If so,
|
||||
please comment with any updates or additional detail.
|
||||
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Don't
|
||||
take it personally, we just need to keep a handle on things. Thank you
|
||||
for your contributions!
|
||||
# Comment to post when closing a stale issue. Set to `false` to disable
|
||||
closeComment: >
|
||||
This issue has been automatically closed because it has not had
|
||||
recent activity. If you believe this is still an issue, please confirm that
|
||||
this issue is still happening in the most recent version of Snipe-IT and reply
|
||||
to this thread to re-open it.
|
||||
40
.github/workflows/stale.yml
vendored
40
.github/workflows/stale.yml
vendored
@@ -1,40 +0,0 @@
|
||||
name: 'Close stale issues'
|
||||
on:
|
||||
schedule:
|
||||
- cron: '30 1 * * *'
|
||||
|
||||
jobs:
|
||||
stale:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
# contents: write # only for delete-branch option
|
||||
issues: write
|
||||
# pull-requests: write
|
||||
steps:
|
||||
- uses: actions/stale@v9
|
||||
with:
|
||||
debug-only: true
|
||||
ascending: true
|
||||
operations-per-run: 1000 # just while we're debugging
|
||||
repo-token: ${{ secrets.GITHUB_TOKEN }}
|
||||
days-before-stale: 60
|
||||
days-before-close: 7
|
||||
exempt-all-milestones: true
|
||||
stale-issue-message: >
|
||||
Is this still relevant? We haven't heard from anyone in a bit. If so,
|
||||
please comment with any updates or additional detail.
|
||||
|
||||
This issue has been automatically marked as stale because it has not had
|
||||
recent activity. It will be closed if no further activity occurs. Don't
|
||||
take it personally, we just need to keep a handle on things. Thank you
|
||||
for your contributions!
|
||||
close-issue-message: >
|
||||
This issue has been automatically closed because it has not had
|
||||
recent activity. If you believe this is still an issue, please confirm that
|
||||
this issue is still happening in the most recent version of Snipe-IT and reply
|
||||
to this thread to re-open it.
|
||||
# There doesn't seem to be a 'reopen issue message'?
|
||||
# Since there is no 'stale-pr-message' - PR's should not be stale'd
|
||||
stale-issue-label: stale
|
||||
exempt-issue-labels: >
|
||||
pinned,security,:woman_technologist: ready for dev,:moneybag: bounty,:hand: bug,🔐 security,👩💻 ready for dev,💰 bounty,✋ bug
|
||||
2
.github/workflows/tests-mysql.yml
vendored
2
.github/workflows/tests-mysql.yml
vendored
@@ -76,4 +76,4 @@ jobs:
|
||||
DB_DATABASE: snipeit
|
||||
DB_PORT: ${{ job.services.mysql.ports[3306] }}
|
||||
DB_USERNAME: root
|
||||
run: php artisan test
|
||||
run: php artisan test --parallel
|
||||
|
||||
2
.github/workflows/tests-postgres.yml
vendored
2
.github/workflows/tests-postgres.yml
vendored
@@ -74,4 +74,4 @@ jobs:
|
||||
DB_PORT: ${{ job.services.postgresql.ports[5432] }}
|
||||
DB_USERNAME: snipeit
|
||||
DB_PASSWORD: password
|
||||
run: php artisan test
|
||||
run: php artisan test --parallel
|
||||
|
||||
2
.github/workflows/tests-sqlite.yml
vendored
2
.github/workflows/tests-sqlite.yml
vendored
@@ -58,4 +58,4 @@ jobs:
|
||||
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
||||
env:
|
||||
DB_CONNECTION: sqlite_testing
|
||||
run: php artisan test
|
||||
run: php artisan test --parallel
|
||||
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -47,7 +47,6 @@ storage/private_uploads/users/*
|
||||
tests/_data/scenarios
|
||||
tests/_output/*
|
||||
tests/_support/_generated/*
|
||||
tests/coverage/*
|
||||
/npm-debug.log
|
||||
/storage/oauth-private.key
|
||||
/storage/oauth-public.key
|
||||
@@ -68,6 +67,3 @@ _ide_helper_models.php
|
||||
/.phplint-cache
|
||||
storage/ldap_client_tls.cert
|
||||
storage/ldap_client_tls.key
|
||||
/storage/framework/testing
|
||||
|
||||
/.phpunit.cache
|
||||
@@ -51,8 +51,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
| [<img src="https://avatars.githubusercontent.com/u/111287779?v=4" width="110px;"/><br /><sub>NojoudAlshehri</sub>](https://github.com/NojoudAlshehri)<br />[💻](https://github.com/snipe/snipe-it/commits?author=NojoudAlshehri "Code") | [<img src="https://avatars.githubusercontent.com/u/54367449?v=4" width="110px;"/><br /><sub>Stefan Stidl</sub>](https://github.com/stefanstidlffg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=stefanstidlffg "Code") | [<img src="https://avatars.githubusercontent.com/u/87803479?v=4" width="110px;"/><br /><sub>Quentin Aymard</sub>](https://github.com/qay21)<br />[💻](https://github.com/snipe/snipe-it/commits?author=qay21 "Code") | [<img src="https://avatars.githubusercontent.com/u/5396871?v=4" width="110px;"/><br /><sub>Grant Le Roux</sub>](https://github.com/cram42)<br />[💻](https://github.com/snipe/snipe-it/commits?author=cram42 "Code") | [<img src="https://avatars.githubusercontent.com/u/58479551?v=4" width="110px;"/><br /><sub>Bogdan</sub>](http://@singrity)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Singrity "Code") | [<img src="https://avatars.githubusercontent.com/u/3483684?v=4" width="110px;"/><br /><sub>mmanjos</sub>](https://github.com/mmanjos)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mmanjos "Code") | [<img src="https://avatars.githubusercontent.com/u/7429229?v=4" width="110px;"/><br /><sub>Abdelaziz Faki</sub>](https://azooz2014.github.io/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azooz2014 "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/47315739?v=4" width="110px;"/><br /><sub>bilias</sub>](https://github.com/bilias)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bilias "Code") | [<img src="https://avatars.githubusercontent.com/u/2565989?v=4" width="110px;"/><br /><sub>coach1988</sub>](https://github.com/coach1988)<br />[💻](https://github.com/snipe/snipe-it/commits?author=coach1988 "Code") | [<img src="https://avatars.githubusercontent.com/u/11910225?v=4" width="110px;"/><br /><sub>MrM</sub>](https://github.com/mauro-miatello)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mauro-miatello "Code") | [<img src="https://avatars.githubusercontent.com/u/60405354?v=4" width="110px;"/><br /><sub>koiakoia</sub>](https://github.com/koiakoia)<br />[💻](https://github.com/snipe/snipe-it/commits?author=koiakoia "Code") | [<img src="https://avatars.githubusercontent.com/u/5323832?v=4" width="110px;"/><br /><sub>Mustafa Online</sub>](https://github.com/mustafa-online)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mustafa-online "Code") | [<img src="https://avatars.githubusercontent.com/u/104601439?v=4" width="110px;"/><br /><sub>franceslui</sub>](https://github.com/franceslui)<br />[💻](https://github.com/snipe/snipe-it/commits?author=franceslui "Code") | [<img src="https://avatars.githubusercontent.com/u/125313163?v=4" width="110px;"/><br /><sub>Q4kK</sub>](https://github.com/Q4kK)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Q4kK "Code") |
|
||||
| [<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/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") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
@@ -1,35 +1,35 @@
|
||||
FROM alpine:3.19
|
||||
FROM alpine:3.18.6
|
||||
# Apache + PHP
|
||||
RUN apk add --no-cache \
|
||||
apache2 \
|
||||
php82 \
|
||||
php82-common \
|
||||
php82-apache2 \
|
||||
php82-curl \
|
||||
php82-ldap \
|
||||
php82-mysqli \
|
||||
php82-gd \
|
||||
php82-xml \
|
||||
php82-mbstring \
|
||||
php82-zip \
|
||||
php82-ctype \
|
||||
php82-tokenizer \
|
||||
php82-pdo_mysql \
|
||||
php82-openssl \
|
||||
php82-bcmath \
|
||||
php82-phar \
|
||||
php82-json \
|
||||
php82-iconv \
|
||||
php82-fileinfo \
|
||||
php82-simplexml \
|
||||
php82-session \
|
||||
php82-dom \
|
||||
php82-xmlwriter \
|
||||
php82-xmlreader \
|
||||
php82-sodium \
|
||||
php82-redis \
|
||||
php82-pecl-memcached \
|
||||
php82-exif \
|
||||
php81 \
|
||||
php81-common \
|
||||
php81-apache2 \
|
||||
php81-curl \
|
||||
php81-ldap \
|
||||
php81-mysqli \
|
||||
php81-gd \
|
||||
php81-xml \
|
||||
php81-mbstring \
|
||||
php81-zip \
|
||||
php81-ctype \
|
||||
php81-tokenizer \
|
||||
php81-pdo_mysql \
|
||||
php81-openssl \
|
||||
php81-bcmath \
|
||||
php81-phar \
|
||||
php81-json \
|
||||
php81-iconv \
|
||||
php81-fileinfo \
|
||||
php81-simplexml \
|
||||
php81-session \
|
||||
php81-dom \
|
||||
php81-xmlwriter \
|
||||
php81-xmlreader \
|
||||
php81-sodium \
|
||||
php81-redis \
|
||||
php81-pecl-memcached \
|
||||
php81-exif \
|
||||
curl \
|
||||
wget \
|
||||
vim \
|
||||
@@ -42,7 +42,7 @@ COPY docker/column-statistics.cnf /etc/mysql/conf.d/column-statistics.cnf
|
||||
# Where apache's PID lives
|
||||
RUN mkdir -p /run/apache2 && chown apache:apache /run/apache2
|
||||
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php82/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php81/php.ini
|
||||
COPY docker/000-default-2.4.conf /etc/apache2/conf.d/default.conf
|
||||
|
||||
# Enable mod_rewrite
|
||||
@@ -79,12 +79,12 @@ USER root
|
||||
|
||||
VOLUME ["/var/lib/snipeit"]
|
||||
|
||||
# Startup script
|
||||
COPY docker/startup_alpine.sh /startup.sh
|
||||
RUN chmod +x /startup.sh
|
||||
# Entrypoints
|
||||
COPY docker/entrypoint_alpine.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/sbin/tini", "--"]
|
||||
|
||||
CMD ["/startup.sh"]
|
||||
CMD ["/entrypoint.sh"]
|
||||
|
||||
EXPOSE 80
|
||||
|
||||
@@ -97,7 +97,7 @@ RUN set -eux; \
|
||||
VOLUME [ "/var/lib/snipeit" ]
|
||||
|
||||
COPY --chown=www-data:www-data docker/docker-secrets.env /var/www/html/.env
|
||||
COPY --chmod=655 docker/startup_alpine_fpm.sh /startup.sh
|
||||
COPY --chmod=655 docker/docker-entrypoint.sh /usr/local/bin/docker-snipeit-entrypoint
|
||||
COPY docker/column-statistics.cnf /etc/mysql/conf.d/column-statistics.cnf
|
||||
ENTRYPOINT [ "/startup.sh" ]
|
||||
CMD [ "/startup.sh", "php-fpm" ]
|
||||
ENTRYPOINT [ "/usr/local/bin/docker-snipeit-entrypoint" ]
|
||||
CMD [ "/usr/local/bin/docker-php-entrypoint", "php-fpm" ]
|
||||
|
||||
13
README.md
13
README.md
@@ -72,23 +72,18 @@ Since the release of the JSON REST API, several third-party developers have been
|
||||
- [Snipe-IT plugin for Jira Service Desk](https://marketplace.atlassian.com/apps/1220964/snipe-it-for-jira)
|
||||
- [Python 3 CSV importer](https://github.com/gastamper/snipeit-csvimporter) - allows importing assets into Snipe-IT based on Item Name rather than Asset Tag.
|
||||
- [Snipe-IT Kubernetes Helm Chart](https://github.com/t3n/helm-charts/tree/master/snipeit) - For more information, [click here](https://hub.helm.sh/charts/t3n/snipeit).
|
||||
- [Snipe-IT Bulk Edit](https://github.com/bricelabelle/snipe-it-bulkedit) - Google Script files to use Google Sheets as a bulk checkout/checkin/edit tool for Snipe-IT.
|
||||
- [MosyleSnipeSync](https://github.com/RodneyLeeBrands/MosyleSnipeSync) by [@Karpadiem](https://github.com/Karpadiem) - Python script to synchronize information between Mosyle and Snipe-IT.
|
||||
- [Snipe-IT Bulk Edit](https://github.com/bricelabelle/snipe-it-bulkedit) - Google Script files to use Google Sheets as a bulk checkout/checkin/edit tool for Snipe-it.
|
||||
- [MosyleSnipeSync](https://github.com/RodneyLeeBrands/MosyleSnipeSync) by [@Karpadiem](https://github.com/Karpadiem) - Python script to synchronize information between Mosyle and Snipe-IT
|
||||
- [WWW::SnipeIT](https://github.com/SEDC/perl-www-snipeit) by [@SEDC](https://github.com/SEDC) - perl module for accessing the API
|
||||
- [UniFi to Snipe-IT](https://github.com/RodneyLeeBrands/UnifiSnipeSync) by [@karpadiem](https://github.com/karpadiem) - Python script that synchronizes UniFi devices with Snipe-IT.
|
||||
- [Kandji2Snipe](https://github.com/grokability/kandji2snipe) by [@briangoldstein](https://github.com/briangoldstein) - Python script that synchronizes Kandji with Snipe-IT.
|
||||
- [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.
|
||||
- [SnipeAgent](https://github.com/ReticentRobot/SnipeAgent) by @ReticentRobot - Windows agent for Snipe-IT
|
||||
|
||||
-----
|
||||
|
||||
### Contributing
|
||||
|
||||
Please refrain from submitting issues or pull requests generated by fully-automated tools. Maintainers reserve the right, at their sole discretion, to close such submissions and to block any account responsible for them.
|
||||
|
||||
Ideally, contributions should follow from a human-to-human discussion in the form of an issue.
|
||||
|
||||
Please see the complete documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing-overview).
|
||||
Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing-overview).
|
||||
|
||||
Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ APP_DEBUG=true
|
||||
APP_KEY=base64:glJpcM7BYwWiBggp3SQ/+NlRkqsBQMaGEOjemXqJzOU=
|
||||
APP_URL=http://localhost:8000
|
||||
APP_TIMEZONE='UTC'
|
||||
APP_LOCALE=en-US
|
||||
APP_LOCALE=en
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: DATABASE SETTINGS
|
||||
|
||||
@@ -1,66 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class FixupAssignedToWithoutAssignedType extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:assigned-to-fixup
|
||||
{--debug : Display debugging output}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Fixes up assets that have an assigned_to but no assigned_type';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$assets = Asset::whereNull("assigned_type")->whereNotNull("assigned_to")->withTrashed();
|
||||
$this->withProgressBar($assets->get(), function (Asset $asset) {
|
||||
//now check each action log, from the most recent backwards, to find the last checkin or checkout
|
||||
foreach($asset->log()->orderBy("id","desc")->get() as $action_log) {
|
||||
if($this->option("debug")) {
|
||||
$this->info("Asset id: " . $asset->id . " action log, action type is: " . $action_log->action_type);
|
||||
}
|
||||
switch($action_log->action_type) {
|
||||
case 'checkin from':
|
||||
if($this->option("debug")) {
|
||||
$this->info("Doing a checkin for ".$asset->id);
|
||||
}
|
||||
$asset->assigned_to = null;
|
||||
// if you have a required custom field, we still want to save, and we *don't* want an action_log
|
||||
$asset->saveQuietly();
|
||||
return;
|
||||
|
||||
case 'checkout':
|
||||
if($this->option("debug")) {
|
||||
$this->info("Doing a checkout for " . $asset->id . " picking target type: " . $action_log->target_type);
|
||||
}
|
||||
if($asset->assigned_to != $action_log->target_id) {
|
||||
$this->error("Asset's assigned_to does *NOT* match Action Log's target_id. \$asset->assigned_to=".$asset->assigned_to." vs. \$action_log->target_id=".$action_log->target_id);
|
||||
//FIXME - do we abort here? Do we try to keep looking? I don't know, this means your data is *really* messed up...
|
||||
}
|
||||
$asset->assigned_type = $action_log->target_type;
|
||||
$asset->saveQuietly(); // see above
|
||||
return;
|
||||
}
|
||||
}
|
||||
$asset->assigned_to = null; //asset was never checked in or out in its lifetime - it stays 'checked in'
|
||||
$asset->saveQuietly(); //see above
|
||||
});
|
||||
$this->newLine();
|
||||
$this->info("Assets assigned_type are fixed");
|
||||
}
|
||||
}
|
||||
276
app/Console/Commands/LdapSync.php
Normal file → Executable file
276
app/Console/Commands/LdapSync.php
Normal file → Executable file
@@ -53,22 +53,18 @@ class LdapSync extends Command
|
||||
|
||||
ini_set('max_execution_time', env('LDAP_TIME_LIM', 600)); //600 seconds = 10 minutes
|
||||
ini_set('memory_limit', env('LDAP_MEM_LIM', '500M'));
|
||||
|
||||
$ldap_map = [
|
||||
"username" => Setting::getSettings()->ldap_username_field,
|
||||
"last_name" => Setting::getSettings()->ldap_lname_field,
|
||||
"first_name" => Setting::getSettings()->ldap_fname_field,
|
||||
"active_flag" => Setting::getSettings()->ldap_active_flag,
|
||||
"emp_num" => Setting::getSettings()->ldap_emp_num,
|
||||
"email" => Setting::getSettings()->ldap_email,
|
||||
"phone" => Setting::getSettings()->ldap_phone_field,
|
||||
"jobtitle" => Setting::getSettings()->ldap_jobtitle,
|
||||
"country" => Setting::getSettings()->ldap_country,
|
||||
"location" => Setting::getSettings()->ldap_location,
|
||||
"dept" => Setting::getSettings()->ldap_dept,
|
||||
"manager" => Setting::getSettings()->ldap_manager,
|
||||
];
|
||||
|
||||
$ldap_result_username = Setting::getSettings()->ldap_username_field;
|
||||
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
|
||||
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
|
||||
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag;
|
||||
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
|
||||
$ldap_result_email = Setting::getSettings()->ldap_email;
|
||||
$ldap_result_phone = Setting::getSettings()->ldap_phone_field;
|
||||
$ldap_result_jobtitle = Setting::getSettings()->ldap_jobtitle;
|
||||
$ldap_result_country = Setting::getSettings()->ldap_country;
|
||||
$ldap_result_location = Setting::getSettings()->ldap_location;
|
||||
$ldap_result_dept = Setting::getSettings()->ldap_dept;
|
||||
$ldap_result_manager = Setting::getSettings()->ldap_manager;
|
||||
$ldap_default_group = Setting::getSettings()->ldap_default_group;
|
||||
$search_base = Setting::getSettings()->ldap_base_dn;
|
||||
|
||||
@@ -111,21 +107,14 @@ class LdapSync extends Command
|
||||
}
|
||||
|
||||
/**
|
||||
* If a filter has been specified, use that, otherwise default to null
|
||||
* If a filter has been specified, use that
|
||||
*/
|
||||
if ($this->option('filter') != '') {
|
||||
$filter = $this->option('filter');
|
||||
$results = Ldap::findLdapUsers($search_base, -1, $this->option('filter'));
|
||||
} else {
|
||||
$filter = null;
|
||||
$results = Ldap::findLdapUsers($search_base);
|
||||
}
|
||||
|
||||
/**
|
||||
* We only need to request the LDAP attributes that we process
|
||||
*/
|
||||
$attributes = array_values(array_filter($ldap_map));
|
||||
|
||||
$results = Ldap::findLdapUsers($search_base, -1, $filter, $attributes);
|
||||
|
||||
|
||||
} catch (\Exception $e) {
|
||||
if ($this->option('json_summary')) {
|
||||
$json_summary = ['error' => true, 'error_message' => $e->getMessage(), 'summary' => []];
|
||||
@@ -137,24 +126,23 @@ class LdapSync extends Command
|
||||
}
|
||||
|
||||
/* Determine which location to assign users to by default. */
|
||||
$default_location = null;
|
||||
$location = null; // TODO - this would be better called "$default_location", which is more explicit about its purpose
|
||||
if ($this->option('location') != '') {
|
||||
if ($default_location = Location::where('name', '=', $this->option('location'))->first()) {
|
||||
if ($location = Location::where('name', '=', $this->option('location'))->first()) {
|
||||
Log::debug('Location name ' . $this->option('location') . ' passed');
|
||||
Log::debug('Importing to '.$default_location->name.' ('.$default_location->id.')');
|
||||
Log::debug('Importing to ' . $location->name . ' (' . $location->id . ')');
|
||||
}
|
||||
|
||||
} elseif ($this->option('location_id')) {
|
||||
//TODO - figure out how or why this is an array?
|
||||
foreach($this->option('location_id') as $location_id) {
|
||||
if ($default_location = Location::where('id', '=', $location_id)->first()) {
|
||||
if ($location = Location::where('id', '=', $location_id)->first()) {
|
||||
Log::debug('Location ID ' . $location_id . ' passed');
|
||||
Log::debug('Importing to '.$default_location->name.' ('.$default_location->id.')');
|
||||
Log::debug('Importing to ' . $location->name . ' (' . $location->id . ')');
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
if (!isset($default_location)) {
|
||||
if (! isset($location)) {
|
||||
Log::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
|
||||
}
|
||||
|
||||
@@ -195,17 +183,17 @@ class LdapSync extends Command
|
||||
}
|
||||
$usernames = [];
|
||||
for ($i = 0; $i < $location_users['count']; $i++) {
|
||||
if (array_key_exists($ldap_map["username"], $location_users[$i])) {
|
||||
if (array_key_exists($ldap_result_username, $location_users[$i])) {
|
||||
$location_users[$i]['ldap_location_override'] = true;
|
||||
$location_users[$i]['location_id'] = $ldap_loc['id'];
|
||||
$usernames[] = $location_users[$i][$ldap_map["username"]][0];
|
||||
$usernames[] = $location_users[$i][$ldap_result_username][0];
|
||||
}
|
||||
}
|
||||
|
||||
// Delete located users from the general group.
|
||||
foreach ($results as $key => $generic_entry) {
|
||||
if ((is_array($generic_entry)) && (array_key_exists($ldap_map["username"], $generic_entry))) {
|
||||
if (in_array($generic_entry[$ldap_map["username"]][0], $usernames)) {
|
||||
if ((is_array($generic_entry)) && (array_key_exists($ldap_result_username, $generic_entry))) {
|
||||
if (in_array($generic_entry[$ldap_result_username][0], $usernames)) {
|
||||
unset($results[$key]);
|
||||
}
|
||||
}
|
||||
@@ -230,78 +218,77 @@ class LdapSync extends Command
|
||||
|
||||
|
||||
for ($i = 0; $i < $results['count']; $i++) {
|
||||
$item = [];
|
||||
$item['username'] = $results[$i][$ldap_map["username"]][0] ?? '';
|
||||
$item['employee_number'] = $results[$i][$ldap_map["emp_num"]][0] ?? '';
|
||||
$item['lastname'] = $results[$i][$ldap_map["last_name"]][0] ?? '';
|
||||
$item['firstname'] = $results[$i][$ldap_map["first_name"]][0] ?? '';
|
||||
$item['email'] = $results[$i][$ldap_map["email"]][0] ?? '';
|
||||
$item['ldap_location_override'] = $results[$i]['ldap_location_override'] ?? '';
|
||||
$item['location_id'] = $results[$i]['location_id'] ?? '';
|
||||
$item['telephone'] = $results[$i][$ldap_map["phone"]][0] ?? '';
|
||||
$item['jobtitle'] = $results[$i][$ldap_map["jobtitle"]][0] ?? '';
|
||||
$item['country'] = $results[$i][$ldap_map["country"]][0] ?? '';
|
||||
$item['department'] = $results[$i][$ldap_map["dept"]][0] ?? '';
|
||||
$item['manager'] = $results[$i][$ldap_map["manager"]][0] ?? '';
|
||||
$item['location'] = $results[$i][$ldap_map["location"]][0] ?? '';
|
||||
$location = $default_location; //initially, set '$location' to the default_location (which may just be `null`)
|
||||
$item = [];
|
||||
$item['username'] = $results[$i][$ldap_result_username][0] ?? '';
|
||||
$item['employee_number'] = $results[$i][$ldap_result_emp_num][0] ?? '';
|
||||
$item['lastname'] = $results[$i][$ldap_result_last_name][0] ?? '';
|
||||
$item['firstname'] = $results[$i][$ldap_result_first_name][0] ?? '';
|
||||
$item['email'] = $results[$i][$ldap_result_email][0] ?? '';
|
||||
$item['ldap_location_override'] = $results[$i]['ldap_location_override'] ?? '';
|
||||
$item['location_id'] = $results[$i]['location_id'] ?? '';
|
||||
$item['telephone'] = $results[$i][$ldap_result_phone][0] ?? '';
|
||||
$item['jobtitle'] = $results[$i][$ldap_result_jobtitle][0] ?? '';
|
||||
$item['country'] = $results[$i][$ldap_result_country][0] ?? '';
|
||||
$item['department'] = $results[$i][$ldap_result_dept][0] ?? '';
|
||||
$item['manager'] = $results[$i][$ldap_result_manager][0] ?? '';
|
||||
$item['location'] = $results[$i][$ldap_result_location][0] ?? '';
|
||||
|
||||
// ONLY if you are using the "ldap_location" option *AND* you have an actual result
|
||||
if ($ldap_map["location"] && $item['location']) {
|
||||
$location = Location::firstOrCreate([
|
||||
'name' => $item['location'],
|
||||
// ONLY if you are using the "ldap_location" option *AND* you have an actual result
|
||||
if ($ldap_result_location && $item['location']) {
|
||||
$location = Location::firstOrCreate([
|
||||
'name' => $item['location'],
|
||||
]);
|
||||
}
|
||||
$department = Department::firstOrCreate([
|
||||
'name' => $item['department'],
|
||||
]);
|
||||
}
|
||||
$department = Department::firstOrCreate([
|
||||
'name' => $item['department'],
|
||||
]);
|
||||
|
||||
$user = User::where('username', $item['username'])->first();
|
||||
if ($user) {
|
||||
// Updating an existing user.
|
||||
$item['createorupdate'] = 'updated';
|
||||
} else {
|
||||
// Creating a new user.
|
||||
$user = new User;
|
||||
$user->password = $user->noPassword();
|
||||
$user->locale = app()->getLocale();
|
||||
$user->activated = 1; // newly created users can log in by default, unless AD's UAC is in use, or an active flag is set (below)
|
||||
$item['createorupdate'] = 'created';
|
||||
}
|
||||
$user = User::where('username', $item['username'])->first();
|
||||
if ($user) {
|
||||
// Updating an existing user.
|
||||
$item['createorupdate'] = 'updated';
|
||||
} else {
|
||||
// Creating a new user.
|
||||
$user = new User;
|
||||
$user->password = $user->noPassword();
|
||||
$user->locale = app()->getLocale();
|
||||
$user->activated = 1; // newly created users can log in by default, unless AD's UAC is in use, or an active flag is set (below)
|
||||
$item['createorupdate'] = 'created';
|
||||
}
|
||||
|
||||
//If a sync option is not filled in on the LDAP settings don't populate the user field
|
||||
if($ldap_map["username"] != null){
|
||||
if($ldap_result_username != null){
|
||||
$user->username = $item['username'];
|
||||
}
|
||||
if($ldap_map["last_name"] != null){
|
||||
if($ldap_result_last_name != null){
|
||||
$user->last_name = $item['lastname'];
|
||||
}
|
||||
if($ldap_map["first_name"] != null){
|
||||
if($ldap_result_first_name != null){
|
||||
$user->first_name = $item['firstname'];
|
||||
}
|
||||
if($ldap_map["emp_num"] != null){
|
||||
if($ldap_result_emp_num != null){
|
||||
$user->employee_num = e($item['employee_number']);
|
||||
}
|
||||
if($ldap_map["email"] != null){
|
||||
if($ldap_result_email != null){
|
||||
$user->email = $item['email'];
|
||||
}
|
||||
if($ldap_map["phone"] != null){
|
||||
if($ldap_result_phone != null){
|
||||
$user->phone = $item['telephone'];
|
||||
}
|
||||
if($ldap_map["jobtitle"] != null){
|
||||
if($ldap_result_jobtitle != null){
|
||||
$user->jobtitle = $item['jobtitle'];
|
||||
}
|
||||
if($ldap_map["country"] != null){
|
||||
if($ldap_result_country != null){
|
||||
$user->country = $item['country'];
|
||||
}
|
||||
if($ldap_map["dept"] != null){
|
||||
if($ldap_result_dept != null){
|
||||
$user->department_id = $department->id;
|
||||
}
|
||||
if($ldap_map["location"] != null){
|
||||
$user->location_id = $location?->id;
|
||||
if($ldap_result_location != null){
|
||||
$user->location_id = $location ? $location->id : null;
|
||||
}
|
||||
|
||||
if($ldap_map["manager"] != null){
|
||||
if($ldap_result_manager != null){
|
||||
if($item['manager'] != null) {
|
||||
// Check Cache first
|
||||
if (isset($manager_cache[$item['manager']])) {
|
||||
@@ -318,7 +305,7 @@ class LdapSync extends Command
|
||||
$ldap_manager = [
|
||||
"count" => 1,
|
||||
0 => [
|
||||
$ldap_map["username"] => [$item['manager']]
|
||||
$ldap_result_username => [$item['manager']]
|
||||
]
|
||||
];
|
||||
}
|
||||
@@ -327,7 +314,7 @@ class LdapSync extends Command
|
||||
|
||||
// Get the Manager's username
|
||||
// PHP LDAP returns every LDAP attribute as an array, and 90% of the time it's an array of just one item. But, hey, it's an array.
|
||||
$ldapManagerUsername = $ldap_manager[0][$ldap_map["username"]][0];
|
||||
$ldapManagerUsername = $ldap_manager[0][$ldap_result_username][0];
|
||||
|
||||
// Get User from Manager username.
|
||||
$ldap_manager = User::where('username', $ldapManagerUsername)->first();
|
||||
@@ -343,38 +330,38 @@ class LdapSync extends Command
|
||||
}
|
||||
}
|
||||
|
||||
// Sync activated state for Active Directory.
|
||||
if (!empty($ldap_map["active_flag"])) { // IF we have an 'active' flag set....
|
||||
// ....then *most* things that are truthy will activate the user. Anything falsey will deactivate them.
|
||||
// (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;
|
||||
// Sync activated state for Active Directory.
|
||||
if ( !empty($ldap_result_active_flag)) { // IF we have an 'active' flag set....
|
||||
// ....then *most* things that are truthy will activate the user. Anything falsey will deactivate them.
|
||||
// (Specifically, we don't handle a value of '0.0' correctly)
|
||||
$raw_value = @$results[$i][$ldap_result_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
|
||||
$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,
|
||||
// ....then use the UAC setting on the account to determine can-log-in vs. cannot-log-in
|
||||
} elseif (array_key_exists('useraccountcontrol', $results[$i]) ) {
|
||||
// ....otherwise, (ie if no 'active' LDAP flag is defined), IF the UAC setting exists,
|
||||
// ....then use the UAC setting on the account to determine can-log-in vs. cannot-log-in
|
||||
|
||||
|
||||
/* The following is _probably_ the correct logic, but we can't use it because
|
||||
some users may have been dependent upon the previous behavior, and this
|
||||
could cause additional access to be available to users they don't want
|
||||
to allow to log in.
|
||||
/* The following is _probably_ the correct logic, but we can't use it because
|
||||
some users may have been dependent upon the previous behavior, and this
|
||||
could cause additional access to be available to users they don't want
|
||||
to allow to log in.
|
||||
|
||||
$useraccountcontrol = $results[$i]['useraccountcontrol'][0];
|
||||
if(
|
||||
// based on MS docs at: https://support.microsoft.com/en-us/help/305144/how-to-use-useraccountcontrol-to-manipulate-user-account-properties
|
||||
($useraccountcontrol & 0x200) && // is a NORMAL_ACCOUNT
|
||||
!($useraccountcontrol & 0x02) && // *and* _not_ ACCOUNTDISABLE
|
||||
!($useraccountcontrol & 0x10) // *and* _not_ LOCKOUT
|
||||
) {
|
||||
$user->activated = 1;
|
||||
} else {
|
||||
$user->activated = 0;
|
||||
} */
|
||||
$enabled_accounts = [
|
||||
$useraccountcontrol = $results[$i]['useraccountcontrol'][0];
|
||||
if(
|
||||
// based on MS docs at: https://support.microsoft.com/en-us/help/305144/how-to-use-useraccountcontrol-to-manipulate-user-account-properties
|
||||
($useraccountcontrol & 0x200) && // is a NORMAL_ACCOUNT
|
||||
!($useraccountcontrol & 0x02) && // *and* _not_ ACCOUNTDISABLE
|
||||
!($useraccountcontrol & 0x10) // *and* _not_ LOCKOUT
|
||||
) {
|
||||
$user->activated = 1;
|
||||
} else {
|
||||
$user->activated = 0;
|
||||
} */
|
||||
$enabled_accounts = [
|
||||
'512', // 0x200 NORMAL_ACCOUNT
|
||||
'544', // 0x220 NORMAL_ACCOUNT, PASSWD_NOTREQD
|
||||
'66048', // 0x10200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD
|
||||
@@ -387,47 +374,44 @@ class LdapSync extends Command
|
||||
'4260352', // 0x410200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, DONT_REQ_PREAUTH
|
||||
'1049088', // 0x100200 NORMAL_ACCOUNT, NOT_DELEGATED
|
||||
'1114624', // 0x110200 NORMAL_ACCOUNT, DONT_EXPIRE_PASSWORD, NOT_DELEGATED,
|
||||
];
|
||||
$user->activated = (in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts)) ? 1 : 0;
|
||||
];
|
||||
$user->activated = (in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts)) ? 1 : 0;
|
||||
|
||||
// If we're not using AD, and there isn't an activated flag set, activate all users
|
||||
} /* implied 'else' here - leave the $user->activated flag alone. Newly-created accounts will be active.
|
||||
already-existing accounts will be however the administrator has set them */
|
||||
} /* implied 'else' here - leave the $user->activated flag alone. Newly-created accounts will be active.
|
||||
already-existing accounts will be however the administrator has set them */
|
||||
|
||||
|
||||
if ($item['ldap_location_override'] == true) {
|
||||
$user->location_id = $item['location_id'];
|
||||
} elseif ((isset($location)) && (!empty($location))) {
|
||||
if ((is_array($location)) && (array_key_exists('id', $location))) {
|
||||
$user->location_id = $location['id'];
|
||||
} elseif (is_object($location)) {
|
||||
$user->location_id = $location->id; //THIS is the magic line, this should do it.
|
||||
if ($item['ldap_location_override'] == true) {
|
||||
$user->location_id = $item['location_id'];
|
||||
} elseif ((isset($location)) && (! empty($location))) {
|
||||
if ((is_array($location)) && (array_key_exists('id', $location))) {
|
||||
$user->location_id = $location['id'];
|
||||
} elseif (is_object($location)) {
|
||||
$user->location_id = $location->id;
|
||||
}
|
||||
}
|
||||
}
|
||||
// TODO - should we be NULLING locations if $location is really `null`, and that's what we came up with?
|
||||
// will that conflict with any overriding setting that the user set? Like, if they moved someone from
|
||||
// the 'null' location to somewhere, we wouldn't want to try to override that, right?
|
||||
$location = null;
|
||||
$user->ldap_import = 1;
|
||||
$location = null;
|
||||
$user->ldap_import = 1;
|
||||
|
||||
$errors = '';
|
||||
$errors = '';
|
||||
|
||||
if ($user->save()) {
|
||||
$item['note'] = $item['createorupdate'];
|
||||
$item['status'] = 'success';
|
||||
if ($item['createorupdate'] === 'created' && $ldap_default_group) {
|
||||
$user->groups()->attach($ldap_default_group);
|
||||
if ($user->save()) {
|
||||
$item['note'] = $item['createorupdate'];
|
||||
$item['status'] = 'success';
|
||||
if ( $item['createorupdate'] === 'created' && $ldap_default_group) {
|
||||
$user->groups()->attach($ldap_default_group);
|
||||
}
|
||||
|
||||
} else {
|
||||
foreach ($user->getErrors()->getMessages() as $key => $err) {
|
||||
$errors .= $err[0];
|
||||
}
|
||||
$item['note'] = $errors;
|
||||
$item['status'] = 'error';
|
||||
}
|
||||
|
||||
} else {
|
||||
foreach ($user->getErrors()->getMessages() as $key => $err) {
|
||||
$errors .= $err[0];
|
||||
}
|
||||
$item['note'] = $errors;
|
||||
$item['status'] = 'error';
|
||||
}
|
||||
|
||||
array_push($summary, $item);
|
||||
array_push($summary, $item);
|
||||
}
|
||||
|
||||
if ($this->option('summary')) {
|
||||
|
||||
@@ -6,7 +6,6 @@ use Illuminate\Console\Command;
|
||||
use Symfony\Component\Console\Input\InputArgument;
|
||||
use Symfony\Component\Console\Input\InputOption;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\Console\Helper\ProgressIndicator;
|
||||
|
||||
ini_set('max_execution_time', env('IMPORT_TIME_LIMIT', 600)); //600 seconds = 10 minutes
|
||||
ini_set('memory_limit', env('IMPORT_MEMORY_LIMIT', '500M'));
|
||||
@@ -30,11 +29,6 @@ class ObjectImportCommand extends Command
|
||||
*/
|
||||
protected $description = 'Import Items from CSV';
|
||||
|
||||
/**
|
||||
* The progress indicator instance.
|
||||
*/
|
||||
protected ProgressIndicator $progressIndicator;
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
@@ -45,6 +39,8 @@ class ObjectImportCommand extends Command
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
private $bar;
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
@@ -52,8 +48,6 @@ class ObjectImportCommand extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$this->progressIndicator = new ProgressIndicator($this->output);
|
||||
|
||||
$filename = $this->argument('filename');
|
||||
$class = title_case($this->option('item-type'));
|
||||
$classString = "App\\Importer\\{$class}Importer";
|
||||
@@ -67,25 +61,46 @@ class ObjectImportCommand extends Command
|
||||
// This $logFile/useFiles() bit is currently broken, so commenting it out for now
|
||||
// $logFile = $this->option('logfile');
|
||||
// Log::useFiles($logFile);
|
||||
$this->progressIndicator->start('======= Importing Items from '.$filename.' =========');
|
||||
|
||||
$this->comment('======= Importing Items from '.$filename.' =========');
|
||||
$importer->import();
|
||||
|
||||
$this->progressIndicator->finish('Import finished.');
|
||||
$this->bar = null;
|
||||
|
||||
if (! empty($this->errors)) {
|
||||
$this->comment('The following Errors were encountered.');
|
||||
foreach ($this->errors as $asset => $error) {
|
||||
$this->comment('Error: Item: '.$asset.' failed validation: '.json_encode($error));
|
||||
}
|
||||
} else {
|
||||
$this->comment('All Items imported successfully!');
|
||||
}
|
||||
$this->comment('');
|
||||
}
|
||||
|
||||
public function errorCallback($item, $field, $error)
|
||||
public function errorCallback($item, $field, $errorString)
|
||||
{
|
||||
$this->output->write("\x0D\x1B[2K");
|
||||
|
||||
$this->warn('Error: Item: '.$item->name.' failed validation: '.json_encode($error));
|
||||
$this->errors[$item->name][$field] = $errorString;
|
||||
}
|
||||
|
||||
public function progress($importedItemsCount)
|
||||
public function progress($count)
|
||||
{
|
||||
$this->progressIndicator->advance();
|
||||
if (! $this->bar) {
|
||||
$this->bar = $this->output->createProgressBar($count);
|
||||
}
|
||||
static $index = 0;
|
||||
$index++;
|
||||
if ($index < $count) {
|
||||
$this->bar->advance();
|
||||
} else {
|
||||
$this->bar->finish();
|
||||
}
|
||||
}
|
||||
|
||||
// Tracks the current item for error messages
|
||||
private $updating;
|
||||
// An array of errors encountered while parsing
|
||||
private $errors;
|
||||
|
||||
/**
|
||||
* Log a message to file, configurable by the --log-file parameter.
|
||||
* If a warning message is passed, we'll spit it to the console as well.
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
@@ -16,8 +15,6 @@ use App\Models\Statuslabel;
|
||||
use App\Models\Supplier;
|
||||
use App\Models\User;
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class Purge extends Command
|
||||
{
|
||||
@@ -144,20 +141,6 @@ class Purge extends Command
|
||||
$this->info($users->count().' users purged.');
|
||||
$user_assoc = 0;
|
||||
foreach ($users as $user) {
|
||||
|
||||
$rel_path = 'private_uploads/users';
|
||||
$filenames = Actionlog::where('action_type', 'uploaded')
|
||||
->where('item_id', $user->id)
|
||||
->pluck('filename');
|
||||
foreach($filenames as $filename) {
|
||||
try {
|
||||
if (Storage::exists($rel_path . '/' . $filename)) {
|
||||
Storage::delete($rel_path . '/' . $filename);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
Log::info('An error occurred while deleting files: ' . $e->getMessage());
|
||||
}
|
||||
}
|
||||
$this->info('- User "'.$user->username.'" deleted.');
|
||||
$user_assoc += $user->userlog()->count();
|
||||
$user->userlog()->forceDelete();
|
||||
|
||||
@@ -1,60 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class RemoveExplicitEols extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:remove-explicit-eols {--model_name= : The name of the asset model to update (use "all" to update all models)}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Removes explicit EOLs on assets with selected model so they may inherit the asset model EOL';
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$startTime = microtime(true);
|
||||
|
||||
if ($this->option('model_name') == 'all') {
|
||||
$assets = Asset::all();
|
||||
$this->updateAssets($assets);
|
||||
} else {
|
||||
$assetModel = AssetModel::where('name', '=', $this->option('model_name'))->first();
|
||||
|
||||
if ($assetModel) {
|
||||
$assets = Asset::where('model_id', '=', $assetModel->id)->get();
|
||||
$this->updateAssets($assets);
|
||||
} else {
|
||||
$this->error('Asset model not found');
|
||||
}
|
||||
}
|
||||
$endTime = microtime(true);
|
||||
$executionTime = ($endTime - $startTime);
|
||||
$this->info('Command executed in ' . round($executionTime, 2) . ' seconds.');
|
||||
}
|
||||
|
||||
private function updateAssets($assets)
|
||||
{
|
||||
foreach ($assets as $asset) {
|
||||
$asset->eol_explicit = 0;
|
||||
$asset->asset_eol_date = null;
|
||||
$asset->save();
|
||||
}
|
||||
|
||||
$this->info($assets->count() . ' Assets updated successfully');
|
||||
}
|
||||
}
|
||||
@@ -73,7 +73,6 @@ class ResetDemoSettings extends Command
|
||||
$settings->saml_forcelogin = '0';
|
||||
$settings->saml_slo = null;
|
||||
$settings->saml_custom_settings = null;
|
||||
$settings->default_avatar = 'default.png';
|
||||
|
||||
|
||||
$settings->save();
|
||||
|
||||
@@ -30,11 +30,8 @@ class SQLStreamer {
|
||||
public function parse_sql(string $line): string {
|
||||
// take into account the 'start of line or not' setting as an instance variable?
|
||||
// 'continuation' lines for a permitted statement are PERMITTED.
|
||||
// remove *only* line-feeds & carriage-returns; helpful for regexes against lines from
|
||||
// Windows dumps
|
||||
$line = trim($line, "\r\n");
|
||||
if($this->statement_is_permitted && $line[0] === ' ') {
|
||||
return $line . "\n"; //re-add the newline
|
||||
return $line;
|
||||
}
|
||||
|
||||
$table_regex = '`?([a-zA-Z0-9_]+)`?';
|
||||
@@ -45,12 +42,8 @@ class SQLStreamer {
|
||||
"/^(INSERT INTO )$table_regex(.*)$/" => false,
|
||||
"/^UNLOCK TABLES/" => false,
|
||||
// "/^\\) ENGINE=InnoDB AUTO_INCREMENT=16 DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_unicode_ci;/" => false, // FIXME not sure what to do here?
|
||||
"/^\\)[a-zA-Z0-9_= ]*;$/" => false,
|
||||
// ^^^^^^ that bit should *exit* the 'permitted' block
|
||||
"/^\\(.*\\)[,;]$/" => false, //older MySQL dump style with one set of values per line
|
||||
/* we *could* have made the ^INSERT INTO blah VALUES$ turn on the capturing state, and closed it with
|
||||
a ^(blahblah);$ but it's cleaner to not have to manage the state machine. We're just going to
|
||||
assume that (blahblah), or (blahblah); are values for INSERT and are always acceptable. */
|
||||
"/^\\)[a-zA-Z0-9_= ]*;$/" => false
|
||||
// ^^^^^^ that bit should *exit* the 'perimitted' black
|
||||
];
|
||||
|
||||
foreach($allowed_statements as $statement => $statechange) {
|
||||
@@ -74,7 +67,7 @@ class SQLStreamer {
|
||||
}
|
||||
//how do we *replace* the tablename?
|
||||
// print "RETURNING LINE: $line";
|
||||
return $line . "\n"; //re-add newline
|
||||
return $line;
|
||||
}
|
||||
}
|
||||
// all that is not allowed is denied.
|
||||
@@ -92,7 +85,7 @@ class SQLStreamer {
|
||||
$parser->line_aware_piping(); // <----- THIS is doing the heavy lifting!
|
||||
|
||||
$check_tables = ['settings' => null, 'migrations' => null /* 'assets' => null */]; //TODO - move to statics?
|
||||
//can't use 'users' because the 'accessories_checkout' table?
|
||||
//can't use 'users' because the 'accessories_users' table?
|
||||
// can't use 'assets' because 'ver1_components_assets'
|
||||
foreach($check_tables as $check_table => $_ignore) {
|
||||
foreach ($parser->tablenames as $tablename => $_count) {
|
||||
@@ -171,8 +164,7 @@ class RestoreFromBackup extends Command
|
||||
{filename : The zip file to be migrated}
|
||||
{--no-progress : Don\'t show a progress bar}
|
||||
{--sanitize-guess-prefix : Guess and output the table-prefix needed to "sanitize" the SQL}
|
||||
{--sanitize-with-prefix= : "Sanitize" the SQL, using the passed-in table prefix (can be learned from --sanitize-guess-prefix). Pass as just \'--sanitize-with-prefix=\' to use no prefix}
|
||||
{--sql-stdout-only : ONLY "Sanitize" the SQL and print it to stdout - useful for debugging - probably requires --sanitize-with-prefix= }';
|
||||
{--sanitize-with-prefix= : "Sanitize" the SQL, using the passed-in table prefix (can be learned from --sanitize-guess-prefix). Pass as just \'--sanitize-with-prefix=\' to use no prefix}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@@ -373,15 +365,6 @@ class RestoreFromBackup extends Command
|
||||
return $this->info("Re-run this command with '--sanitize-with-prefix=".$prefix."' to see an attempt to sanitze your SQL.");
|
||||
}
|
||||
|
||||
// If we're doing --sql-stdout-only, handle that now so we don't have to open pipes to mysql and all of that silliness
|
||||
if ($this->option('sql-stdout-only')) {
|
||||
$sql_importer = new SQLStreamer($sql_contents, STDOUT, $this->option('sanitize-with-prefix'));
|
||||
$bytes_read = $sql_importer->line_aware_piping();
|
||||
return $this->warn("$bytes_read total bytes read");
|
||||
//TODO - it'd be nice to dump this message to STDERR so that STDOUT is just pure SQL,
|
||||
// which would be good for redirecting to a file, and not having to trim the last line off of it
|
||||
}
|
||||
|
||||
//how to invoke the restore?
|
||||
$pipes = [];
|
||||
|
||||
@@ -483,9 +466,6 @@ class RestoreFromBackup extends Command
|
||||
$ugly_file_name = $za->statIndex($file_details['index'])['name'];
|
||||
$fp = $za->getStream($ugly_file_name);
|
||||
//$this->info("Weird problem, here are file details? ".print_r($file_details,true));
|
||||
if (!is_dir($file_details['dest'])) {
|
||||
mkdir($file_details['dest'], 0755, true); //0755 is what Laravel uses, so we do that
|
||||
}
|
||||
$migrated_file = fopen($file_details['dest'].'/'.basename($pretty_file_name), 'w');
|
||||
while (($buffer = fgets($fp, SQLStreamer::$buffer_size)) !== false) {
|
||||
fwrite($migrated_file, $buffer);
|
||||
|
||||
@@ -47,8 +47,7 @@ class SendAcceptanceReminder extends Command
|
||||
{
|
||||
$pending = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')
|
||||
->whereHas('checkoutable', function($query) {
|
||||
$query->where('accepted_at', null)
|
||||
->where('declined_at', null);
|
||||
$query->where('archived', 0);
|
||||
})
|
||||
->with(['assignedTo', 'checkoutable.assignedTo', 'checkoutable.model', 'checkoutable.adminuser'])
|
||||
->get();
|
||||
|
||||
@@ -62,9 +62,8 @@ class Helper
|
||||
'mn' => 'mn-MN', // Mongolian
|
||||
'ms' => 'ms-MY', // Malay
|
||||
'nl' => 'nl-NL', // Dutch
|
||||
'no' => 'nb-NO', // Norwegian Bokmål
|
||||
'no' => 'no-NO', // Norwegian
|
||||
'pl' => 'pl-PL', // Polish
|
||||
'pt' => 'pt-PT', // Portuguese
|
||||
'ro' => 'ro-RO', // Romanian
|
||||
'ru' => 'ru-RU', // Russian
|
||||
'sk' => 'sk-SK', // Slovak
|
||||
@@ -553,7 +552,7 @@ class Helper
|
||||
*/
|
||||
public static function statusLabelList()
|
||||
{
|
||||
$statuslabel_list = ['' => trans('general.select_statuslabel')] + Statuslabel::orderBy('default_label', 'desc')->orderBy('name', 'asc')->orderBy('status_type', 'desc')
|
||||
$statuslabel_list = ['' => trans('general.select_statuslabel')] + Statuslabel::orderBy('default_label', 'desc')->orderBy('name', 'asc')->orderBy('deployable', 'desc')
|
||||
->pluck('name', 'id')->toArray();
|
||||
|
||||
return $statuslabel_list;
|
||||
@@ -572,9 +571,9 @@ class Helper
|
||||
*/
|
||||
public static function deployableStatusLabelList()
|
||||
{
|
||||
$statuslabel_list = Statuslabel::where('status_type', 'deployable')->orderBy('default_label', 'desc')
|
||||
$statuslabel_list = Statuslabel::where('deployable', '=', '1')->orderBy('default_label', 'desc')
|
||||
->orderBy('name', 'asc')
|
||||
->orderBy('status_type', 'desc')
|
||||
->orderBy('deployable', 'desc')
|
||||
->pluck('name', 'id')->toArray();
|
||||
|
||||
return $statuslabel_list;
|
||||
@@ -721,7 +720,7 @@ class Helper
|
||||
{
|
||||
$alert_threshold = \App\Models\Setting::getSettings()->alert_threshold;
|
||||
$consumables = Consumable::withCount('consumableAssignments as consumable_assignments_count')->whereNotNull('min_amt')->get();
|
||||
$accessories = Accessory::withCount('checkouts as checkouts_count')->whereNotNull('min_amt')->get();
|
||||
$accessories = Accessory::withCount('users as users_count')->whereNotNull('min_amt')->get();
|
||||
$components = Component::whereNotNull('min_amt')->get();
|
||||
$asset_models = AssetModel::where('min_amt', '>', 0)->get();
|
||||
$licenses = License::where('min_amt', '>', 0)->get();
|
||||
@@ -749,7 +748,7 @@ class Helper
|
||||
}
|
||||
|
||||
foreach ($accessories as $accessory) {
|
||||
$avail = $accessory->qty - $accessory->checkouts_count;
|
||||
$avail = $accessory->qty - $accessory->users_count;
|
||||
if ($avail < ($accessory->min_amt) + $alert_threshold) {
|
||||
if ($accessory->qty > 0) {
|
||||
$percent = number_format((($avail / $accessory->qty) * 100), 0);
|
||||
@@ -914,22 +913,13 @@ class Helper
|
||||
$rules = $class::rules();
|
||||
foreach ($rules as $rule_name => $rule) {
|
||||
if ($rule_name == $field) {
|
||||
if (is_array($rule)) {
|
||||
if (in_array('required', $rule)) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
if (strpos($rule, 'required') === false) {
|
||||
return false;
|
||||
} else {
|
||||
if (strpos($rule, 'required') === false) {
|
||||
return false;
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1123,7 +1113,6 @@ class Helper
|
||||
'png' => 'far fa-image',
|
||||
'webp' => 'far fa-image',
|
||||
'avif' => 'far fa-image',
|
||||
'svg' => 'fas fa-vector-square',
|
||||
// word
|
||||
'doc' => 'far fa-file-word',
|
||||
'docx' => 'far fa-file-word',
|
||||
@@ -1136,7 +1125,7 @@ class Helper
|
||||
//Text
|
||||
'txt' => 'far fa-file-alt',
|
||||
'rtf' => 'far fa-file-alt',
|
||||
'xml' => 'fas fa-code',
|
||||
'xml' => 'far fa-file-alt',
|
||||
// Misc
|
||||
'pdf' => 'far fa-file-pdf',
|
||||
'lic' => 'far fa-save',
|
||||
@@ -1149,7 +1138,41 @@ class Helper
|
||||
return 'far fa-file';
|
||||
}
|
||||
|
||||
public static function show_file_inline($filename)
|
||||
{
|
||||
$extension = substr(strrchr($filename, '.'), 1);
|
||||
|
||||
if ($extension) {
|
||||
switch ($extension) {
|
||||
case 'jpg':
|
||||
case 'jpeg':
|
||||
case 'gif':
|
||||
case 'png':
|
||||
case 'webp':
|
||||
case 'avif':
|
||||
return true;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random encrypted password.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function generateEncyrptedPassword(): string
|
||||
{
|
||||
return bcrypt(self::generateUnencryptedPassword());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random unencrypted password.
|
||||
@@ -1417,6 +1440,7 @@ class Helper
|
||||
|
||||
foreach (self::$language_map as $legacy => $new) {
|
||||
if ($language_code == $legacy) {
|
||||
Log::debug('Current language is '.$legacy.', using '.$new.' instead');
|
||||
return $new;
|
||||
}
|
||||
}
|
||||
@@ -1427,7 +1451,6 @@ class Helper
|
||||
|
||||
public static function mapBackToLegacyLocale($new_locale = null)
|
||||
{
|
||||
|
||||
if (strlen($new_locale) <= 4) {
|
||||
return $new_locale; //"new locale" apparently wasn't quite so new
|
||||
}
|
||||
@@ -1435,73 +1458,42 @@ class Helper
|
||||
// This does a *reverse* search against our new language map array - given the value, find the *key* for it
|
||||
$legacy_locale = array_search($new_locale, self::$language_map);
|
||||
|
||||
if ($legacy_locale !== false) {
|
||||
if($legacy_locale !== false) {
|
||||
return $legacy_locale;
|
||||
}
|
||||
return $new_locale; // better that you have some weird locale that doesn't fit into our mappings anywhere than 'void'
|
||||
}
|
||||
|
||||
public static function determineLanguageDirection() {
|
||||
return in_array(app()->getLocale(),
|
||||
[
|
||||
'ar-SA',
|
||||
'fa-IR',
|
||||
'he-IL'
|
||||
]) ? 'rtl' : 'ltr';
|
||||
}
|
||||
|
||||
|
||||
static public function getRedirectOption($request, $id, $table, $item_id = null)
|
||||
static public function getRedirectOption($request, $id, $table, $asset_id = null)
|
||||
{
|
||||
|
||||
$redirect_option = Session::get('redirect_option');
|
||||
$checkout_to_type = Session::get('checkout_to_type');
|
||||
|
||||
// return to index
|
||||
if ($redirect_option == 'index') {
|
||||
//return to index
|
||||
if ($redirect_option == '0') {
|
||||
switch ($table) {
|
||||
case "Assets":
|
||||
return route('hardware.index');
|
||||
case "Users":
|
||||
return route('users.index');
|
||||
case "Licenses":
|
||||
return route('licenses.index');
|
||||
case "Accessories":
|
||||
return route('accessories.index');
|
||||
case "Components":
|
||||
return route('components.index');
|
||||
case "Consumables":
|
||||
return route('consumables.index');
|
||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkout.success'));
|
||||
}
|
||||
}
|
||||
|
||||
// return to thing being assigned
|
||||
if ($redirect_option == 'item') {
|
||||
//return to thing being assigned
|
||||
if ($redirect_option == '1') {
|
||||
switch ($table) {
|
||||
case "Assets":
|
||||
return route('hardware.show', $id ?? $item_id);
|
||||
case "Users":
|
||||
return route('users.show', $id ?? $item_id);
|
||||
case "Licenses":
|
||||
return route('licenses.show', $id ?? $item_id);
|
||||
case "Accessories":
|
||||
return route('accessories.show', $id ?? $item_id);
|
||||
case "Components":
|
||||
return route('components.show', $id ?? $item_id);
|
||||
case "Consumables":
|
||||
return route('consumables.show', $id ?? $item_id);
|
||||
return redirect()->route('hardware.show', $id ? $id : $asset_id)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||
}
|
||||
}
|
||||
|
||||
// return to assignment target
|
||||
if ($redirect_option == 'target') {
|
||||
//return to thing being assigned to
|
||||
if ($redirect_option == '2') {
|
||||
switch ($checkout_to_type) {
|
||||
case 'user':
|
||||
return route('users.show', ['user' => $request->assigned_user]);
|
||||
return redirect()->route('users.show', $request->assigned_user)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||
case 'location':
|
||||
return route('locations.show', ['location' => $request->assigned_location]);
|
||||
return redirect()->route('locations.show', $request->assigned_location)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||
case 'asset':
|
||||
return route('hardware.show', ['hardware' => $request->assigned_asset]);
|
||||
return redirect()->route('hardware.show', $request->assigned_asset)->with('success', trans('admin/hardware/message.checkout.success'));
|
||||
}
|
||||
}
|
||||
return redirect()->back()->with('error', trans('admin/hardware/message.checkout.error'));
|
||||
|
||||
@@ -1,190 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
class IconHelper
|
||||
{
|
||||
|
||||
public static function icon($type) {
|
||||
switch ($type) {
|
||||
case 'checkout':
|
||||
return 'fa-solid fa-rotate-left';
|
||||
case 'checkin':
|
||||
return 'fa-solid fa-rotate-right';
|
||||
case 'edit':
|
||||
return 'fas fa-pencil-alt';
|
||||
case 'clone':
|
||||
return 'far fa-clone';
|
||||
case 'delete':
|
||||
return 'fas fa-trash';
|
||||
case 'create':
|
||||
return 'fa-solid fa-plus';
|
||||
case 'audit':
|
||||
return 'fa-solid fa-clipboard-check';
|
||||
case '2fa reset':
|
||||
return 'fa-solid fa-mobile-screen';
|
||||
case 'new-user':
|
||||
return 'fa-solid fa-user-plus';
|
||||
case 'merged-user':
|
||||
return 'fa-solid fa-people-arrows';
|
||||
case 'delete-user':
|
||||
return 'fa-solid fa-user-minus';
|
||||
case 'update-user':
|
||||
return 'fa-solid fa-user-pen';
|
||||
case 'user':
|
||||
return 'fa-solid fa-user';
|
||||
case 'users':
|
||||
return 'fas fa-users';
|
||||
case 'restore':
|
||||
return 'fa-solid fa-trash-arrow-up';
|
||||
case 'external-link':
|
||||
return 'fa fa-external-link';
|
||||
case 'email':
|
||||
return 'fa-regular fa-envelope';
|
||||
case 'phone':
|
||||
return 'fa-solid fa-phone';
|
||||
case 'long-arrow-right':
|
||||
return 'fas fa-long-arrow-alt-right';
|
||||
case 'download':
|
||||
return 'fas fa-download';
|
||||
case 'checkmark':
|
||||
return 'fas fa-check icon-white';
|
||||
case 'x':
|
||||
return 'fas fa-times';
|
||||
case 'logout':
|
||||
return 'fa fa-sign-out';
|
||||
case 'admin-settings':
|
||||
return 'fas fa-cogs';
|
||||
case 'settings':
|
||||
return 'fas fa-cog';
|
||||
case 'angle-left':
|
||||
return 'fas fa-angle-left';
|
||||
case 'warning':
|
||||
return 'fas fa-exclamation-triangle';
|
||||
case 'kits':
|
||||
return 'fas fa-object-group';
|
||||
case 'assets':
|
||||
case 'asset':
|
||||
return 'fas fa-barcode';
|
||||
case 'accessories':
|
||||
case 'accessory':
|
||||
return 'far fa-keyboard';
|
||||
case 'components':
|
||||
case 'component':
|
||||
return 'far fa-hdd';
|
||||
case 'consumables':
|
||||
case 'consumable':
|
||||
return 'fas fa-tint';
|
||||
case 'licenses':
|
||||
case 'license':
|
||||
return 'far fa-save';
|
||||
case 'requestable':
|
||||
return 'fas fa-laptop';
|
||||
case 'reports':
|
||||
return 'fas fa-chart-bar';
|
||||
case 'heart':
|
||||
return 'fas fa-heart';
|
||||
case 'circle':
|
||||
return 'fa-regular fa-circle';
|
||||
case 'circle-solid':
|
||||
return 'fa-solid fa-circle';
|
||||
case 'due':
|
||||
return 'fas fa-history';
|
||||
case 'import':
|
||||
return 'fas fa-cloud-upload-alt';
|
||||
case 'search':
|
||||
return 'fas fa-search';
|
||||
case 'alerts':
|
||||
return 'far fa-flag';
|
||||
case 'password':
|
||||
return 'fa-solid fa-key';
|
||||
case 'api-key':
|
||||
return 'fa-solid fa-user-secret';
|
||||
case 'nav-toggle':
|
||||
return 'fas fa-bars';
|
||||
case 'dashboard':
|
||||
return 'fas fa-tachometer-alt';
|
||||
case 'info-circle':
|
||||
return 'fas fa-info-circle';
|
||||
case 'caret-right':
|
||||
return 'fa fa-caret-right';
|
||||
case 'caret-up':
|
||||
return 'fa fa-caret-up';
|
||||
case 'caret-down':
|
||||
return 'fa fa-caret-down';
|
||||
case 'arrow-circle-right':
|
||||
return 'fa fa-arrow-circle-right';
|
||||
case 'minus':
|
||||
return 'fas fa-minus';
|
||||
case 'spinner':
|
||||
return 'fas fa-spinner fa-spin';
|
||||
case 'copy-clipboard':
|
||||
return 'fa-regular fa-clipboard';
|
||||
case 'paperclip':
|
||||
return 'fas fa-paperclip';
|
||||
case 'files':
|
||||
return 'fa-regular fa-file';
|
||||
case 'more-info':
|
||||
return 'far fa-life-ring';
|
||||
case 'calendar':
|
||||
return 'fas fa-calendar';
|
||||
case 'plus':
|
||||
return 'fas fa-plus';
|
||||
case 'history':
|
||||
return 'fas fa-history';
|
||||
case 'more-files':
|
||||
return 'fa-solid fa-laptop-file';
|
||||
case 'maintenances':
|
||||
return 'fas fa-wrench';
|
||||
case 'seats':
|
||||
return 'far fa-list-alt';
|
||||
case 'globe-us':
|
||||
return 'fas fa-globe-americas';
|
||||
case 'locked':
|
||||
return 'fas fa-lock';
|
||||
case 'unlocked':
|
||||
return 'fas fa-lock';
|
||||
case 'locations':
|
||||
return 'fas fa-map-marker-alt';
|
||||
case 'location':
|
||||
return 'fas fa-map-marker-alt';
|
||||
case 'superadmin':
|
||||
return 'fas fa-crown';
|
||||
case 'print':
|
||||
return 'fa-solid fa-print';
|
||||
case 'checkin-and-delete':
|
||||
return 'fa-solid fa-user-xmark';
|
||||
case 'branding':
|
||||
return 'fas fa-copyright';
|
||||
case 'general-settings':
|
||||
return 'fa-solid fa-list-check';
|
||||
case 'groups':
|
||||
return 'fa-solid fa-user-group';
|
||||
case 'bell':
|
||||
return 'fa-solid fa-bell';
|
||||
case 'hashtag':
|
||||
return 'fa-solid fa-hashtag';
|
||||
case 'asset-tags':
|
||||
return 'fas fa-list-ol';
|
||||
case 'labels':
|
||||
return 'fas fa-tags';
|
||||
case 'ldap':
|
||||
return 'fas fa-sitemap';
|
||||
case 'google':
|
||||
return 'fa-brands fa-google';
|
||||
case 'saml':
|
||||
return 'fas fa-sign-in-alt';
|
||||
case 'backups':
|
||||
return 'fas fa-file-archive';
|
||||
case 'logins':
|
||||
return 'fas fa-crosshairs';
|
||||
case 'oauth':
|
||||
return 'fas fa-user-secret';
|
||||
case 'employee_num' :
|
||||
return 'fa-regular fa-id-card';
|
||||
case 'department' :
|
||||
return 'fa-solid fa-building-user';
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -7,7 +7,6 @@ use Illuminate\Http\Response;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Illuminate\Contracts\Filesystem\FileNotFoundException;
|
||||
class StorageHelper
|
||||
{
|
||||
public static function downloader($filename, $disk = 'default') : BinaryFileResponse | RedirectResponse | StreamedResponse
|
||||
@@ -26,64 +25,4 @@ class StorageHelper
|
||||
return Storage::disk($disk)->download($filename);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* This determines the file types that should be allowed inline and checks their fileinfo extension
|
||||
* to determine that they are safe to display inline.
|
||||
*
|
||||
* @author <A. Gianotto> [<snipe@snipe.net]>
|
||||
* @since v7.0.14
|
||||
* @param $file_with_path
|
||||
* @return bool
|
||||
*/
|
||||
public static function allowSafeInline($file_with_path) {
|
||||
|
||||
$allowed_inline = [
|
||||
'pdf',
|
||||
'svg',
|
||||
'jpg',
|
||||
'gif',
|
||||
'svg',
|
||||
'avif',
|
||||
'webp',
|
||||
'png',
|
||||
];
|
||||
|
||||
|
||||
// The file exists and is allowed to be displayed inline
|
||||
if (Storage::exists($file_with_path) && (in_array(pathinfo($file_with_path, PATHINFO_EXTENSION), $allowed_inline))) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Decide whether to show the file inline or download it.
|
||||
*/
|
||||
public static function showOrDownloadFile($file, $filename) {
|
||||
|
||||
$headers = [];
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
// This is NOT allowed as inline - force it to be displayed as text in the browser
|
||||
if (self::allowSafeInline($file) != true) {
|
||||
$headers = array_merge($headers, ['Content-Type' => 'text/plain']);
|
||||
}
|
||||
}
|
||||
|
||||
// Everything else seems okay, but the file doesn't exist on the server.
|
||||
if (Storage::missing($file)) {
|
||||
throw new FileNotFoundException();
|
||||
}
|
||||
|
||||
return Storage::download($file, $filename, $headers);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,17 +73,16 @@ class AccessoriesController extends Controller
|
||||
$accessory->purchase_date = request('purchase_date');
|
||||
$accessory->purchase_cost = request('purchase_cost');
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->created_by = auth()->id();
|
||||
$accessory->user_id = auth()->id();
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
$accessory->notes = request('notes');
|
||||
|
||||
$accessory = $request->handleImages($accessory);
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
// Was the accessory created?
|
||||
if ($accessory->save()) {
|
||||
// Redirect to the new accessory page
|
||||
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))->with('success', trans('admin/accessories/message.create.success'));
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.create.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($accessory->getErrors());
|
||||
@@ -144,12 +143,12 @@ class AccessoriesController extends Controller
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $accessoryId = null) : RedirectResponse
|
||||
{
|
||||
if ($accessory = Accessory::withCount('checkouts as checkouts_count')->find($accessoryId)) {
|
||||
if ($accessory = Accessory::withCount('users as users_count')->find($accessoryId)) {
|
||||
|
||||
$this->authorize($accessory);
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
"qty" => "required|numeric|min:$accessory->checkouts_count"
|
||||
"qty" => "required|numeric|min:$accessory->users_count"
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
@@ -177,10 +176,9 @@ class AccessoriesController extends Controller
|
||||
|
||||
$accessory = $request->handleImages($accessory);
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
// Was the accessory updated?
|
||||
if ($accessory->save()) {
|
||||
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))->with('success', trans('admin/accessories/message.update.success'));
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
|
||||
}
|
||||
} else {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
@@ -233,7 +231,7 @@ class AccessoriesController extends Controller
|
||||
*/
|
||||
public function show($accessoryID = null) : View | RedirectResponse
|
||||
{
|
||||
$accessory = Accessory::withCount('checkouts as checkouts_count')->find($accessoryID);
|
||||
$accessory = Accessory::withCount('users as users_count')->find($accessoryID);
|
||||
$this->authorize('view', $accessory);
|
||||
if (isset($accessory->id)) {
|
||||
return view('accessories/view', compact('accessory'));
|
||||
|
||||
@@ -106,29 +106,50 @@ class AccessoriesFilesController extends Controller
|
||||
* @param int $accessoryId
|
||||
* @param int $fileId
|
||||
*/
|
||||
public function show($accessoryId = null, $fileId = null) : View | RedirectResponse | Response | BinaryFileResponse | StreamedResponse
|
||||
public function show($accessoryId = null, $fileId = null, $download = true) : View | RedirectResponse | Response | BinaryFileResponse | StreamedResponse
|
||||
{
|
||||
|
||||
Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||
$accessory = Accessory::find($accessoryId);
|
||||
|
||||
|
||||
|
||||
// the accessory is valid
|
||||
if ($accessory = Accessory::find($accessoryId)) {
|
||||
if (isset($accessory->id)) {
|
||||
$this->authorize('view', $accessory);
|
||||
$this->authorize('accessories.files', $accessory);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $accessory->id)->find($fileId)) {
|
||||
$file = 'private_uploads/accessories/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('accessories.show', ['accessory' => $accessory])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $accessory->id)->find($fileId)) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/users/message.log_record_not_found'));
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.show', ['accessory' => $accessory])->with('error', trans('general.log_record_not_found'));
|
||||
$file = 'private_uploads/accessories/'.$log->filename;
|
||||
|
||||
if (Storage::missing($file)) {
|
||||
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||
Log::debug('URL should be '.Storage::url($file));
|
||||
|
||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
|
||||
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
|
||||
// won't work, as they're not accessible via the web
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('general.file_not_found'));
|
||||
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,10 +3,8 @@
|
||||
namespace App\Http\Controllers\Accessories;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\AccessoryCheckout;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -25,7 +23,7 @@ class AccessoryCheckinController extends Controller
|
||||
*/
|
||||
public function create($accessoryUserId = null, $backto = null) : View | RedirectResponse
|
||||
{
|
||||
if (is_null($accessory_user = DB::table('accessories_checkout')->find($accessoryUserId))) {
|
||||
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
|
||||
}
|
||||
|
||||
@@ -40,16 +38,16 @@ class AccessoryCheckinController extends Controller
|
||||
*
|
||||
* @uses Accessory::checkin_email() to determine if an email can and should be sent
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param null $accessoryCheckoutId
|
||||
* @param null $accessoryUserId
|
||||
* @param string $backto
|
||||
*/
|
||||
public function store(Request $request, $accessoryCheckoutId = null, $backto = null) : RedirectResponse
|
||||
public function store(Request $request, $accessoryUserId = null, $backto = null) : RedirectResponse
|
||||
{
|
||||
if (is_null($accessory_checkout = AccessoryCheckout::find($accessoryCheckoutId))) {
|
||||
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$accessory = Accessory::find($accessory_checkout->accessory_id);
|
||||
$accessory = Accessory::find($accessory_user->accessory_id);
|
||||
|
||||
$this->authorize('checkin', $accessory);
|
||||
|
||||
@@ -60,12 +58,12 @@ class AccessoryCheckinController extends Controller
|
||||
}
|
||||
|
||||
// Was the accessory updated?
|
||||
if ($accessory_checkout->delete()) {
|
||||
event(new CheckoutableCheckedIn($accessory, $accessory_checkout->assignedTo, auth()->user(), $request->input('note'), $checkin_at));
|
||||
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
|
||||
$return_to = e($accessory_user->assigned_to);
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
event(new CheckoutableCheckedIn($accessory, User::find($return_to), auth()->user(), $request->input('note'), $checkin_at));
|
||||
|
||||
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))->with('success', trans('admin/accessories/message.checkin.success'));
|
||||
return redirect()->route('accessories.show', $accessory->id)->with('success', trans('admin/accessories/message.checkin.success'));
|
||||
}
|
||||
// Redirect to the accessory management page with error
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkin.error'));
|
||||
|
||||
@@ -3,24 +3,18 @@
|
||||
namespace App\Http\Controllers\Accessories;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\CheckInOutRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AccessoryCheckoutRequest;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\AccessoryCheckout;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use \Illuminate\Http\RedirectResponse;
|
||||
|
||||
class AccessoryCheckoutController extends Controller
|
||||
{
|
||||
|
||||
use CheckInOutRequest;
|
||||
|
||||
/**
|
||||
* Return the form to checkout an Accessory to a user.
|
||||
*
|
||||
@@ -30,7 +24,7 @@ class AccessoryCheckoutController extends Controller
|
||||
public function create($id) : View | RedirectResponse
|
||||
{
|
||||
|
||||
if ($accessory = Accessory::withCount('checkouts as checkouts_count')->find($id)) {
|
||||
if ($accessory = Accessory::withCount('users as users_count')->find($id)) {
|
||||
|
||||
$this->authorize('checkout', $accessory);
|
||||
|
||||
@@ -63,38 +57,44 @@ class AccessoryCheckoutController extends Controller
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param Request $request
|
||||
* @param Accessory $accessory
|
||||
* @param int $accessoryId
|
||||
*/
|
||||
public function store(AccessoryCheckoutRequest $request, Accessory $accessory) : RedirectResponse
|
||||
public function store(Request $request, $accessoryId) : RedirectResponse
|
||||
{
|
||||
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory = Accessory::withCount('users as users_count')->find($accessoryId))) {
|
||||
// Redirect to the accessory management page with error
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.user_not_found'));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $accessory);
|
||||
|
||||
$target = $this->determineCheckoutTarget();
|
||||
|
||||
$accessory->checkout_qty = $request->input('checkout_qty', 1);
|
||||
|
||||
for ($i = 0; $i < $accessory->checkout_qty; $i++) {
|
||||
AccessoryCheckout::create([
|
||||
'accessory_id' => $accessory->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'created_by' => auth()->id(),
|
||||
'assigned_to' => $target->id,
|
||||
'assigned_type' => $target::class,
|
||||
'note' => $request->input('note'),
|
||||
]);
|
||||
if (!$user = User::find($request->input('assigned_to'))) {
|
||||
return redirect()->route('accessories.checkout.show', $accessory->id)->with('error', trans('admin/accessories/message.checkout.user_does_not_exist'));
|
||||
}
|
||||
event(new CheckoutableCheckedOut($accessory, $target, auth()->user(), $request->input('note')));
|
||||
|
||||
// Set this as user since we only allow checkout to user for this item type
|
||||
$request->request->add(['checkout_to_type' => request('checkout_to_type')]);
|
||||
$request->request->add(['assigned_user' => $target->id]);
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($accessory->numRemaining() <= 0){
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
|
||||
|
||||
// Update the accessory data
|
||||
$accessory->assigned_to = e($request->input('assigned_to'));
|
||||
|
||||
$accessory->users()->attach($accessory->id, [
|
||||
'accessory_id' => $accessory->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'user_id' => Auth::id(),
|
||||
'assigned_to' => $request->get('assigned_to'),
|
||||
'note' => $request->input('note'),
|
||||
]);
|
||||
|
||||
DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first();
|
||||
|
||||
event(new CheckoutableCheckedOut($accessory, $user, auth()->user(), $request->input('note')));
|
||||
|
||||
// Redirect to the new accessory page
|
||||
return redirect()->to(Helper::getRedirectOption($request, $accessory->id, 'Accessories'))
|
||||
->with('success', trans('admin/accessories/message.checkout.success'));
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.checkout.success'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -218,7 +218,6 @@ class AcceptanceController extends Controller
|
||||
'item_tag' => $item->asset_tag,
|
||||
'item_model' => $display_model,
|
||||
'item_serial' => $item->serial,
|
||||
'item_status' => $item->assetstatus?->name,
|
||||
'eula' => $item->getEula(),
|
||||
'note' => $request->input('note'),
|
||||
'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d'),
|
||||
@@ -237,11 +236,7 @@ class AcceptanceController extends Controller
|
||||
}
|
||||
|
||||
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note'));
|
||||
try {
|
||||
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
|
||||
} catch (\Exception $e) {
|
||||
Log::warning($e);
|
||||
}
|
||||
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
|
||||
event(new CheckoutAccepted($acceptance));
|
||||
|
||||
$return_msg = trans('admin/users/message.accepted');
|
||||
@@ -313,7 +308,6 @@ class AcceptanceController extends Controller
|
||||
'item_tag' => $item->asset_tag,
|
||||
'item_model' => $display_model,
|
||||
'item_serial' => $item->serial,
|
||||
'item_status' => $item->assetstatus?->name,
|
||||
'note' => $request->input('note'),
|
||||
'declined_date' => Carbon::parse($acceptance->declined_at)->format('Y-m-d'),
|
||||
'signature' => ($sig_filename) ? storage_path() . '/private_uploads/signatures/' . $sig_filename : null,
|
||||
|
||||
@@ -4,10 +4,7 @@ namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\CheckInOutRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AccessoryCheckoutRequest;
|
||||
use App\Http\Requests\StoreAccessoryRequest;
|
||||
use App\Http\Transformers\AccessoriesTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Models\Accessory;
|
||||
@@ -18,12 +15,10 @@ use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\AccessoryCheckout;
|
||||
|
||||
|
||||
class AccessoriesController extends Controller
|
||||
{
|
||||
use CheckInOutRequest;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
@@ -51,14 +46,13 @@ class AccessoriesController extends Controller
|
||||
'min_amt',
|
||||
'company_id',
|
||||
'notes',
|
||||
'checkouts_count',
|
||||
'users_count',
|
||||
'qty',
|
||||
];
|
||||
|
||||
|
||||
$accessories = Accessory::select('accessories.*')
|
||||
->with('category', 'company', 'manufacturer', 'checkouts', 'location', 'supplier', 'adminuser')
|
||||
->withCount('checkouts as checkouts_count');
|
||||
$accessories = Accessory::select('accessories.*')->with('category', 'company', 'manufacturer', 'users', 'location', 'supplier')
|
||||
->withCount('users as users_count');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$accessories = $accessories->TextSearch($request->input('search'));
|
||||
@@ -111,10 +105,7 @@ class AccessoriesController extends Controller
|
||||
break;
|
||||
case 'supplier':
|
||||
$accessories = $accessories->OrderSupplier($order);
|
||||
break;
|
||||
case 'created_by':
|
||||
$accessories = $accessories->OrderByCreatedByName($order);
|
||||
break;
|
||||
break;
|
||||
default:
|
||||
$accessories = $accessories->orderBy($column_sort, $order);
|
||||
break;
|
||||
@@ -130,13 +121,14 @@ class AccessoriesController extends Controller
|
||||
/**
|
||||
* Store a newly created resource in storage.
|
||||
*
|
||||
* @param \App\Http\Requests\ImageUploadRequest $request
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @param \App\Http\Requests\ImageUploadRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function store(StoreAccessoryRequest $request)
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize('create', Accessory::class);
|
||||
$accessory = new Accessory;
|
||||
$accessory->fill($request->all());
|
||||
$accessory = $request->handleImages($accessory);
|
||||
@@ -152,15 +144,15 @@ class AccessoriesController extends Controller
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$this->authorize('view', Accessory::class);
|
||||
$accessory = Accessory::withCount('checkouts as checkouts_count')->findOrFail($id);
|
||||
$accessory = Accessory::withCount('users as users_count')->findOrFail($id);
|
||||
|
||||
return (new AccessoriesTransformer)->transformAccessory($accessory);
|
||||
}
|
||||
@@ -169,10 +161,10 @@ class AccessoriesController extends Controller
|
||||
/**
|
||||
* Display the specified resource.
|
||||
*
|
||||
* @param int $id
|
||||
* @return array
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function accessory_detail($id)
|
||||
{
|
||||
@@ -196,27 +188,35 @@ class AccessoriesController extends Controller
|
||||
$this->authorize('view', Accessory::class);
|
||||
|
||||
$accessory = Accessory::with('lastCheckout')->findOrFail($id);
|
||||
if (! Company::isCurrentUserHasAccess($accessory)) {
|
||||
return ['total' => 0, 'rows' => []];
|
||||
}
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
$accessory_checkouts = $accessory->checkouts;
|
||||
$total = $accessory_checkouts->count();
|
||||
$accessory_users = $accessory->users;
|
||||
$total = $accessory_users->count();
|
||||
|
||||
if ($total < $offset) {
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
$accessory_checkouts = $accessory->checkouts()->skip($offset)->take($limit)->get();
|
||||
$accessory_users = $accessory->users()->skip($offset)->take($limit)->get();
|
||||
|
||||
if ($request->filled('search')) {
|
||||
|
||||
$accessory_checkouts = $accessory->checkouts()->TextSearch($request->input('search'))
|
||||
$accessory_users = $accessory->users()
|
||||
->where(function ($query) use ($request) {
|
||||
$search_str = '%' . $request->input('search') . '%';
|
||||
$query->where('first_name', 'like', $search_str)
|
||||
->orWhere('last_name', 'like', $search_str)
|
||||
->orWhere('note', 'like', $search_str);
|
||||
})
|
||||
->get();
|
||||
$total = $accessory_checkouts->count();
|
||||
$total = $accessory_users->count();
|
||||
}
|
||||
|
||||
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $accessory_checkouts, $total);
|
||||
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $accessory_users, $total);
|
||||
}
|
||||
|
||||
|
||||
@@ -273,31 +273,43 @@ class AccessoriesController extends Controller
|
||||
* If Slack is enabled and/or asset acceptance is enabled, it will also
|
||||
* trigger a Slack message and send an email.
|
||||
*
|
||||
* @param int $accessoryId
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function checkout(AccessoryCheckoutRequest $request, Accessory $accessory)
|
||||
public function checkout(Request $request, $accessoryId)
|
||||
{
|
||||
$this->authorize('checkout', $accessory);
|
||||
$target = $this->determineCheckoutTarget();
|
||||
$accessory->checkout_qty = $request->input('checkout_qty', 1);
|
||||
|
||||
for ($i = 0; $i < $accessory->checkout_qty; $i++) {
|
||||
AccessoryCheckout::create([
|
||||
'accessory_id' => $accessory->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'created_by' => auth()->id(),
|
||||
'assigned_to' => $target->id,
|
||||
'assigned_type' => $target::class,
|
||||
'note' => $request->input('note'),
|
||||
]);
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory = Accessory::withCount('users as users_count')->find($accessoryId))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.does_not_exist')));
|
||||
}
|
||||
|
||||
// Set this value to be able to pass the qty through to the event
|
||||
event(new CheckoutableCheckedOut($accessory, $target, auth()->user(), $request->input('note')));
|
||||
$this->authorize('checkout', $accessory);
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkout.success')));
|
||||
|
||||
if ($accessory->numRemaining() > 0) {
|
||||
|
||||
if (! $user = User::find($request->input('assigned_to'))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.checkout.user_does_not_exist')));
|
||||
}
|
||||
|
||||
// Update the accessory data
|
||||
$accessory->assigned_to = $request->input('assigned_to');
|
||||
|
||||
$accessory->users()->attach($accessory->id, [
|
||||
'accessory_id' => $accessory->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'user_id' => Auth::id(),
|
||||
'assigned_to' => $request->get('assigned_to'),
|
||||
'note' => $request->get('note'),
|
||||
]);
|
||||
|
||||
event(new CheckoutableCheckedOut($accessory, $user, auth()->user(), $request->input('note')));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkout.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'No accessories remaining'));
|
||||
|
||||
}
|
||||
|
||||
@@ -314,21 +326,29 @@ class AccessoriesController extends Controller
|
||||
*/
|
||||
public function checkin(Request $request, $accessoryUserId = null)
|
||||
{
|
||||
if (is_null($accessory_checkout = AccessoryCheckout::find($accessoryUserId))) {
|
||||
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/accessories/message.does_not_exist')));
|
||||
}
|
||||
|
||||
$accessory = Accessory::find($accessory_checkout->accessory_id);
|
||||
$accessory = Accessory::find($accessory_user->accessory_id);
|
||||
$this->authorize('checkin', $accessory);
|
||||
|
||||
$accessory->logCheckin(User::find($accessory_checkout->assigned_to), $request->input('note'));
|
||||
$logaction = $accessory->logCheckin(User::find($accessory_user->assigned_to), $request->input('note'));
|
||||
|
||||
// Was the accessory updated?
|
||||
if ($accessory_checkout->delete()) {
|
||||
if (! is_null($accessory_checkout->assigned_to)) {
|
||||
$user = User::find($accessory_checkout->assigned_to);
|
||||
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
|
||||
if (! is_null($accessory_user->assigned_to)) {
|
||||
$user = User::find($accessory_user->assigned_to);
|
||||
}
|
||||
|
||||
$data['log_id'] = $logaction->id;
|
||||
$data['first_name'] = $user->first_name;
|
||||
$data['last_name'] = $user->last_name;
|
||||
$data['item_name'] = $accessory->name;
|
||||
$data['checkin_date'] = $logaction->created_at;
|
||||
$data['item_tag'] = '';
|
||||
$data['note'] = $logaction->note;
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkin.success')));
|
||||
}
|
||||
|
||||
|
||||
@@ -34,7 +34,7 @@ class AssetMaintenancesController extends Controller
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
$maintenances = AssetMaintenance::select('asset_maintenances.*')
|
||||
->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.assetstatus', 'adminuser');
|
||||
->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'asset.assetstatus', 'admin');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$maintenances = $maintenances->TextSearch($request->input('search'));
|
||||
@@ -48,10 +48,6 @@ class AssetMaintenancesController extends Controller
|
||||
$maintenances->where('asset_maintenances.supplier_id', '=', $request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('created_by')) {
|
||||
$maintenances->where('asset_maintenances.created_by', '=', $request->input('created_by'));
|
||||
}
|
||||
|
||||
if ($request->filled('asset_maintenance_type')) {
|
||||
$maintenances->where('asset_maintenance_type', '=', $request->input('asset_maintenance_type'));
|
||||
}
|
||||
@@ -73,7 +69,7 @@ class AssetMaintenancesController extends Controller
|
||||
'asset_tag',
|
||||
'asset_name',
|
||||
'serial',
|
||||
'created_by',
|
||||
'user_id',
|
||||
'supplier',
|
||||
'is_warranty',
|
||||
'status_label',
|
||||
@@ -83,8 +79,8 @@ class AssetMaintenancesController extends Controller
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
||||
|
||||
switch ($sort) {
|
||||
case 'created_by':
|
||||
$maintenances = $maintenances->OrderByCreatedBy($order);
|
||||
case 'user_id':
|
||||
$maintenances = $maintenances->OrderAdmin($order);
|
||||
break;
|
||||
case 'supplier':
|
||||
$maintenances = $maintenances->OrderBySupplier($order);
|
||||
@@ -128,7 +124,7 @@ class AssetMaintenancesController extends Controller
|
||||
// create a new model instance
|
||||
$maintenance = new AssetMaintenance();
|
||||
$maintenance->fill($request->all());
|
||||
$maintenance->created_by = auth()->id();
|
||||
$maintenance->user_id = Auth::id();
|
||||
|
||||
// Was the asset maintenance created?
|
||||
if ($maintenance->save()) {
|
||||
@@ -190,9 +186,12 @@ class AssetMaintenancesController extends Controller
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
// Check if the asset maintenance exists
|
||||
|
||||
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
|
||||
|
||||
if (! Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot delete a maintenance for that asset'));
|
||||
}
|
||||
|
||||
$assetMaintenance->delete();
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetMaintenance, trans('admin/asset_maintenances/message.delete.success')));
|
||||
|
||||
@@ -1,200 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Actionlog;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use Symfony\Component\HttpFoundation\BinaryFileResponse;
|
||||
|
||||
|
||||
/**
|
||||
* This class controls file related actions related
|
||||
* to assets for the Snipe-IT Asset Management application.
|
||||
*
|
||||
* Based on the Assets/AssetFilesController by A. Gianotto <snipe@snipe.net>
|
||||
*
|
||||
* @version v1.0
|
||||
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
|
||||
*/
|
||||
class AssetModelFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Accepts a POST to upload a file to the server.
|
||||
*
|
||||
* @param \App\Http\Requests\UploadFileRequest $request
|
||||
* @param int $assetModelId
|
||||
* @since [v7.0.12]
|
||||
* @author [r-xyz]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $assetModelId = null) : JsonResponse
|
||||
{
|
||||
// Start by checking if the asset being acted upon exists
|
||||
if (! $assetModel = AssetModel::find($assetModelId)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.does_not_exist')), 404);
|
||||
}
|
||||
|
||||
// Make sure we are allowed to update this asset
|
||||
$this->authorize('update', $assetModel);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
// If the file storage directory doesn't exist; create it
|
||||
if (! Storage::exists('private_uploads/assetmodels')) {
|
||||
Storage::makeDirectory('private_uploads/assetmodels', 775);
|
||||
}
|
||||
|
||||
// Loop over the attached files and add them to the asset
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/assetmodels/','model-'.$assetModel->id, $file);
|
||||
|
||||
$assetModel->logUpload($file_name, e($request->get('notes')));
|
||||
}
|
||||
|
||||
// All done - report success
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $assetModel, trans('admin/models/message.upload.success')));
|
||||
}
|
||||
|
||||
// We only reach here if no files were included in the POST, so tell the user this
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.upload.nofiles')), 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* List the files for an asset.
|
||||
*
|
||||
* @param int $assetModelId
|
||||
* @since [v7.0.12]
|
||||
* @author [r-xyz]
|
||||
*/
|
||||
public function list($assetModelId = null) : JsonResponse
|
||||
{
|
||||
// Start by checking if the asset being acted upon exists
|
||||
if (! $assetModel = AssetModel::find($assetModelId)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.does_not_exist')), 404);
|
||||
}
|
||||
|
||||
// the asset is valid
|
||||
if (isset($assetModel->id)) {
|
||||
$this->authorize('view', $assetModel);
|
||||
|
||||
// Check that there are some uploads on this asset that can be listed
|
||||
if ($assetModel->uploads->count() > 0) {
|
||||
$files = array();
|
||||
foreach ($assetModel->uploads as $upload) {
|
||||
array_push($files, $upload);
|
||||
}
|
||||
// Give the list of files back to the user
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $files, trans('admin/models/message.upload.success')));
|
||||
}
|
||||
|
||||
// There are no files.
|
||||
return response()->json(Helper::formatStandardApiResponse('success', array(), trans('admin/models/message.upload.success')));
|
||||
}
|
||||
|
||||
// Send back an error message
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.download.error')), 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
*
|
||||
* @param int $assetModelId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v7.0.12]
|
||||
* @author [r-xyz]
|
||||
*/
|
||||
public function show($assetModelId = null, $fileId = null) : JsonResponse | StreamedResponse | Storage | StorageHelper | BinaryFileResponse
|
||||
{
|
||||
// Start by checking if the asset being acted upon exists
|
||||
if (! $assetModel = AssetModel::find($assetModelId)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.does_not_exist')), 404);
|
||||
}
|
||||
|
||||
// the asset is valid
|
||||
if (isset($assetModel->id)) {
|
||||
$this->authorize('view', $assetModel);
|
||||
|
||||
// Check that the file being requested exists for the asset
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $assetModel->id)->find($fileId)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.download.no_match', ['id' => $fileId])), 404);
|
||||
}
|
||||
|
||||
// Form the full filename with path
|
||||
$file = 'private_uploads/assetmodels/'.$log->filename;
|
||||
Log::debug('Checking for '.$file);
|
||||
|
||||
if ($log->action_type == 'audit') {
|
||||
$file = 'private_uploads/audits/'.$log->filename;
|
||||
}
|
||||
|
||||
// Check the file actually exists on the filesystem
|
||||
if (! Storage::exists($file)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.download.does_not_exist', ['id' => $fileId])), 404);
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
|
||||
// Send back an error message
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.download.error', ['id' => $fileId])), 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the associated file
|
||||
*
|
||||
* @param int $assetModelId
|
||||
* @param int $fileId
|
||||
* @since [v7.0.12]
|
||||
* @author [r-xyz]
|
||||
*/
|
||||
public function destroy($assetModelId = null, $fileId = null) : JsonResponse
|
||||
{
|
||||
// Start by checking if the asset being acted upon exists
|
||||
if (! $assetModel = AssetModel::find($assetModelId)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.does_not_exist')), 404);
|
||||
}
|
||||
|
||||
$rel_path = 'private_uploads/assetmodels';
|
||||
|
||||
// the asset is valid
|
||||
if (isset($assetModel->id)) {
|
||||
$this->authorize('update', $assetModel);
|
||||
|
||||
// Check for the file
|
||||
$log = Actionlog::find($fileId);
|
||||
if ($log) {
|
||||
// Check the file actually exists, and delete it
|
||||
if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
Storage::delete($rel_path.'/'.$log->filename);
|
||||
}
|
||||
// Delete the record of the file
|
||||
$log->delete();
|
||||
|
||||
// All deleting done - notify the user of success
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/models/message.deletefile.success')), 200);
|
||||
}
|
||||
|
||||
// The file doesn't seem to really exist, so report an error
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.deletefile.error')), 500);
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/models/message.deletefile.error')), 500);
|
||||
}
|
||||
}
|
||||
@@ -48,8 +48,6 @@ class AssetModelsController extends Controller
|
||||
'assets_count',
|
||||
'category',
|
||||
'fieldset',
|
||||
'deleted_at',
|
||||
'updated_at',
|
||||
];
|
||||
|
||||
$assetmodels = AssetModel::select([
|
||||
@@ -69,7 +67,7 @@ class AssetModelsController extends Controller
|
||||
'models.deleted_at',
|
||||
'models.updated_at',
|
||||
])
|
||||
->with('category', 'depreciation', 'manufacturer', 'fieldset.fields.defaultValues','adminuser')
|
||||
->with('category', 'depreciation', 'manufacturer', 'fieldset.fields.defaultValues')
|
||||
->withCount('assets as assets_count');
|
||||
|
||||
if ($request->input('status')=='deleted') {
|
||||
@@ -80,10 +78,6 @@ class AssetModelsController extends Controller
|
||||
$assetmodels = $assetmodels->where('models.category_id', '=', $request->input('category_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('depreciation_id')) {
|
||||
$assetmodels = $assetmodels->where('models.depreciation_id', '=', $request->input('depreciation_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$assetmodels->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Http\Requests\StoreAssetRequest;
|
||||
use App\Http\Requests\UpdateAssetRequest;
|
||||
use App\Http\Traits\MigratesLegacyAssetLocations;
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\LicenseSeat;
|
||||
@@ -56,12 +55,7 @@ class AssetsController extends Controller
|
||||
public function index(Request $request, $action = null, $upcoming_status = null) : JsonResponse | array
|
||||
{
|
||||
|
||||
|
||||
// This handles the legacy audit endpoints :(
|
||||
if ($action == 'audit') {
|
||||
$action = 'audits';
|
||||
}
|
||||
$filter_non_depreciable_assets = false;
|
||||
$filter_non_deprecable_assets = false;
|
||||
|
||||
/**
|
||||
* This looks MAD janky (and it is), but the AssetsController@index does a LOT of heavy lifting throughout the
|
||||
@@ -75,7 +69,7 @@ class AssetsController extends Controller
|
||||
* which would have been far worse of a mess. *sad face* - snipe (Sept 1, 2021)
|
||||
*/
|
||||
if (Route::currentRouteName()=='api.depreciation-report.index') {
|
||||
$filter_non_depreciable_assets = true;
|
||||
$filter_non_deprecable_assets = true;
|
||||
$transformer = 'App\Http\Transformers\DepreciationReportTransformer';
|
||||
$this->authorize('reports.view');
|
||||
} else {
|
||||
@@ -126,13 +120,13 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
$assets = Asset::select('assets.*')
|
||||
->with('location', 'assetstatus', 'company', 'defaultLoc','assignedTo', 'adminuser','model.depreciation',
|
||||
->with('location', 'assetstatus', 'company', 'defaultLoc','assignedTo',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset','supplier'); //it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
|
||||
|
||||
|
||||
if ($filter_non_depreciable_assets) {
|
||||
$non_depreciable_models = AssetModel::select('id')->whereNotNull('depreciation_id')->get();
|
||||
$assets->InModelList($non_depreciable_models->toArray());
|
||||
if ($filter_non_deprecable_assets) {
|
||||
$non_deprecable_models = AssetModel::select('id')->whereNotNull('depreciation_id')->get();
|
||||
$assets->InModelList($non_deprecable_models->toArray());
|
||||
}
|
||||
|
||||
|
||||
@@ -159,8 +153,8 @@ class AssetsController extends Controller
|
||||
* Handle due and overdue audits and checkin dates
|
||||
*/
|
||||
switch ($action) {
|
||||
// Audit (singular) is left over from earlier legacy APIs
|
||||
case 'audits' :
|
||||
case 'audits':
|
||||
|
||||
switch ($upcoming_status) {
|
||||
case 'due':
|
||||
$assets->DueForAudit($settings);
|
||||
@@ -206,14 +200,18 @@ class AssetsController extends Controller
|
||||
case 'Pending':
|
||||
$assets->join('status_labels AS status_alias', function ($join) {
|
||||
$join->on('status_alias.id', '=', 'assets.status_id')
|
||||
->where('status_alias.status_type', '=', 'pending');
|
||||
->where('status_alias.deployable', '=', 0)
|
||||
->where('status_alias.pending', '=', 1)
|
||||
->where('status_alias.archived', '=', 0);
|
||||
});
|
||||
break;
|
||||
case 'RTD':
|
||||
$assets->whereNull('assets.assigned_to')
|
||||
->join('status_labels AS status_alias', function ($join) {
|
||||
$join->on('status_alias.id', '=', 'assets.status_id')
|
||||
->where('status_alias.status_type', '=', 'deployable');
|
||||
->where('status_alias.deployable', '=', 1)
|
||||
->where('status_alias.pending', '=', 0)
|
||||
->where('status_alias.archived', '=', 0);
|
||||
});
|
||||
break;
|
||||
case 'Undeployable':
|
||||
@@ -222,15 +220,20 @@ class AssetsController extends Controller
|
||||
case 'Archived':
|
||||
$assets->join('status_labels AS status_alias', function ($join) {
|
||||
$join->on('status_alias.id', '=', 'assets.status_id')
|
||||
->where('status_alias.status_type', '=', 'archived');
|
||||
->where('status_alias.deployable', '=', 0)
|
||||
->where('status_alias.pending', '=', 0)
|
||||
->where('status_alias.archived', '=', 1);
|
||||
});
|
||||
break;
|
||||
case 'Requestable':
|
||||
$assets->where('assets.requestable', '=', 1)
|
||||
->join('status_labels AS status_alias', function ($join) {
|
||||
$join->on('status_alias.id', '=', 'assets.status_id')
|
||||
->where('status_alias.status_type', '=', 'deployable');
|
||||
->where('status_alias.deployable', '=', 1)
|
||||
->where('status_alias.pending', '=', 0)
|
||||
->where('status_alias.archived', '=', 0);
|
||||
});
|
||||
|
||||
break;
|
||||
case 'Deployed':
|
||||
// more sad, horrible workarounds for laravel bugs when doing full text searches
|
||||
@@ -247,7 +250,7 @@ class AssetsController extends Controller
|
||||
// terrible workaround for complex-query Laravel bug in fulltext
|
||||
$assets->join('status_labels AS status_alias', function ($join) {
|
||||
$join->on('status_alias.id', '=', 'assets.status_id')
|
||||
->where('status_alias.status_type', '!=', 'archived');
|
||||
->where('status_alias.archived', '=', 0);
|
||||
});
|
||||
|
||||
// If there is a status ID, don't take show_archived_in_list into consideration
|
||||
@@ -256,7 +259,6 @@ class AssetsController extends Controller
|
||||
$join->on('status_alias.id', '=', 'assets.status_id');
|
||||
});
|
||||
}
|
||||
break;
|
||||
|
||||
}
|
||||
|
||||
@@ -368,33 +370,8 @@ class AssetsController extends Controller
|
||||
case 'assigned_to':
|
||||
$assets->OrderAssigned($order);
|
||||
break;
|
||||
case 'created_by':
|
||||
$assets->OrderByCreatedByName($order);
|
||||
break;
|
||||
default:
|
||||
$numeric_sort = false;
|
||||
|
||||
// Search through the custom fields array to see if we're sorting on a custom field
|
||||
if (array_search($column_sort, $all_custom_fields->pluck('db_column')->toArray()) !== false) {
|
||||
|
||||
// Check to see if this is a numeric field type
|
||||
foreach ($all_custom_fields as $field) {
|
||||
if (($field->db_column == $sort_override) && ($field->format == 'NUMERIC')) {
|
||||
$numeric_sort = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// This may not work for all databases, but it works for MySQL
|
||||
if ($numeric_sort) {
|
||||
$assets->orderByRaw(DB::getTablePrefix() . 'assets.' . $sort_override . ' * 1 ' . $order);
|
||||
} else {
|
||||
$assets->orderBy($sort_override, $order);
|
||||
}
|
||||
|
||||
} else {
|
||||
$assets->orderBy($column_sort, $order);
|
||||
}
|
||||
$assets->orderBy($column_sort, $order);
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -566,8 +543,8 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
if ($asset->assetstatus->status_label == 'pending') {
|
||||
$asset->use_text .= '('.$asset->assetstatus->status_label.')';
|
||||
if ($asset->assetstatus->getStatuslabelType() == 'pending') {
|
||||
$asset->use_text .= '('.$asset->assetstatus->getStatuslabelType().')';
|
||||
}
|
||||
|
||||
$asset->use_image = ($asset->getImageUrl()) ? $asset->getImageUrl() : null;
|
||||
@@ -590,7 +567,7 @@ class AssetsController extends Controller
|
||||
$asset->model()->associate(AssetModel::find((int) $request->get('model_id')));
|
||||
|
||||
$asset->fill($request->validated());
|
||||
$asset->created_by = auth()->id();
|
||||
$asset->user_id = Auth::id();
|
||||
|
||||
/**
|
||||
* this is here just legacy reasons. Api\AssetController
|
||||
@@ -624,7 +601,7 @@ class AssetsController extends Controller
|
||||
if ($field->field_encrypted == '1') {
|
||||
Log::debug('This model field is encrypted in this fieldset.');
|
||||
|
||||
if (Gate::allows('assets.view.encrypted_custom_fields')) {
|
||||
if (Gate::allows('admin')) {
|
||||
|
||||
// If input value is null, use custom field's default value
|
||||
if (($field_val == null) && ($request->has('model_id') != '')) {
|
||||
@@ -674,35 +651,36 @@ class AssetsController extends Controller
|
||||
* Accepts a POST request to update an asset
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param \App\Http\Requests\ImageUploadRequest $request
|
||||
* @since [v4.0]
|
||||
*/
|
||||
public function update(UpdateAssetRequest $request, Asset $asset): JsonResponse
|
||||
public function update(ImageUploadRequest $request, $id) : JsonResponse
|
||||
{
|
||||
$asset->fill($request->validated());
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
if ($request->has('model_id')) {
|
||||
$asset->model()->associate(AssetModel::find($request->validated()['model_id']));
|
||||
}
|
||||
if ($request->has('company_id')) {
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->validated()['company_id']);
|
||||
}
|
||||
if ($request->has('rtd_location_id') && !$request->has('location_id')) {
|
||||
$asset->location_id = $request->validated()['rtd_location_id'];
|
||||
}
|
||||
if ($request->input('last_audit_date')) {
|
||||
$asset->last_audit_date = Carbon::parse($request->input('last_audit_date'))->startOfDay()->format('Y-m-d H:i:s');
|
||||
}
|
||||
if ($asset = Asset::find($id)) {
|
||||
$asset->fill($request->all());
|
||||
|
||||
/**
|
||||
* this is here just legacy reasons. Api\AssetController
|
||||
* used image_source once to allow encoded image uploads.
|
||||
*/
|
||||
if ($request->has('image_source')) {
|
||||
$request->offsetSet('image', $request->offsetGet('image_source'));
|
||||
}
|
||||
($request->filled('model_id')) ?
|
||||
$asset->model()->associate(AssetModel::find($request->get('model_id'))) : null;
|
||||
($request->filled('rtd_location_id')) ?
|
||||
$asset->location_id = $request->get('rtd_location_id') : '';
|
||||
($request->filled('company_id')) ?
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : '';
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
$model = $asset->model;
|
||||
($request->filled('rtd_location_id')) ?
|
||||
$asset->location_id = $request->get('rtd_location_id') : null;
|
||||
|
||||
/**
|
||||
* this is here just legacy reasons. Api\AssetController
|
||||
* used image_source once to allow encoded image uploads.
|
||||
*/
|
||||
if ($request->has('image_source')) {
|
||||
$request->offsetSet('image', $request->offsetGet('image_source'));
|
||||
}
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
$model = AssetModel::find($asset->model_id);
|
||||
|
||||
// Update custom fields
|
||||
$problems_updating_encrypted_custom_fields = false;
|
||||
@@ -717,7 +695,7 @@ class AssetsController extends Controller
|
||||
}
|
||||
}
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('assets.view.encrypted_custom_fields')) {
|
||||
if (Gate::allows('admin')) {
|
||||
$field_val = Crypt::encrypt($field_val);
|
||||
} else {
|
||||
$problems_updating_encrypted_custom_fields = true;
|
||||
@@ -728,13 +706,15 @@ class AssetsController extends Controller
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($asset->save()) {
|
||||
if (($request->filled('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
|
||||
$location = $target->location_id;
|
||||
} elseif (($request->filled('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
|
||||
$location = $target->location_id;
|
||||
|
||||
Asset::where('assigned_type', \App\Models\Asset::class)->where('assigned_to', $asset->id)
|
||||
Asset::where('assigned_type', \App\Models\Asset::class)->where('assigned_to', $id)
|
||||
->update(['location_id' => $target->location_id]);
|
||||
} elseif (($request->filled('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
|
||||
$location = $target->id;
|
||||
@@ -748,13 +728,17 @@ class AssetsController extends Controller
|
||||
$asset->image = $asset->getImageUrl();
|
||||
}
|
||||
|
||||
if ($problems_updating_encrypted_custom_fields) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.encrypted_warning')));
|
||||
} else {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
|
||||
if ($problems_updating_encrypted_custom_fields) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.encrypted_warning')));
|
||||
} else {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
|
||||
}
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $asset->getErrors()), 200);
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
}
|
||||
|
||||
|
||||
@@ -772,16 +756,9 @@ class AssetsController extends Controller
|
||||
if ($asset = Asset::find($id)) {
|
||||
$this->authorize('delete', $asset);
|
||||
|
||||
if ($asset->assignedTo) {
|
||||
|
||||
$target = $asset->assignedTo;
|
||||
$checkin_at = date('Y-m-d H:i:s');
|
||||
$originalValues = $asset->getRawOriginal();
|
||||
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), 'Checkin on delete', $checkin_at, $originalValues));
|
||||
DB::table('assets')
|
||||
->where('id', $asset->id)
|
||||
->update(['assigned_to' => null]);
|
||||
}
|
||||
DB::table('assets')
|
||||
->where('id', $asset->id)
|
||||
->update(['assigned_to' => null]);
|
||||
|
||||
$asset->delete();
|
||||
|
||||
@@ -957,7 +934,7 @@ class AssetsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->filled('status_id')) {
|
||||
if ($request->has('status_id')) {
|
||||
$asset->status_id = $request->input('status_id');
|
||||
}
|
||||
|
||||
@@ -1007,7 +984,7 @@ class AssetsController extends Controller
|
||||
public function checkinByTag(Request $request, $tag = null) : JsonResponse
|
||||
{
|
||||
$this->authorize('checkin', Asset::class);
|
||||
if (null == $tag && null !== ($request->input('asset_tag'))) {
|
||||
if(null == $tag && null !== ($request->input('asset_tag'))) {
|
||||
$tag = $request->input('asset_tag');
|
||||
}
|
||||
$asset = Asset::where('asset_tag', $tag)->first();
|
||||
|
||||
@@ -4,22 +4,37 @@ namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\CategoriesTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Models\Category;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
use App\Models\Traits\ApiResponder;
|
||||
use App\Http\Serializers\BootstrapTablesSerializer;
|
||||
use League\Fractal\Resource\Item;
|
||||
use League\Fractal\Resource\Collection;
|
||||
use League\Fractal\Serializer\DataArraySerializer;
|
||||
use League\Fractal\Serializer\ArraySerializer;
|
||||
use App\Http\Transformers\CategoriesTransformer;
|
||||
use League\Fractal\Manager;
|
||||
use League\Fractal\Pagination\IlluminatePaginatorAdapter;
|
||||
use Spatie\Fractalistic\Fractal;
|
||||
use function Illuminate\Events\queueable;
|
||||
|
||||
|
||||
|
||||
class CategoriesController extends Controller
|
||||
{
|
||||
use ApiResponder;
|
||||
|
||||
/**
|
||||
* Display a listing of the resource.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
|
||||
*/
|
||||
public function index(Request $request) : array
|
||||
{
|
||||
@@ -43,7 +58,6 @@ class CategoriesController extends Controller
|
||||
|
||||
$categories = Category::select([
|
||||
'id',
|
||||
'created_by',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'name', 'category_type',
|
||||
@@ -51,10 +65,8 @@ class CategoriesController extends Controller
|
||||
'eula_text',
|
||||
'require_acceptance',
|
||||
'checkin_email',
|
||||
'image',
|
||||
])
|
||||
->with('adminuser')
|
||||
->withCount('accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count');
|
||||
'image'
|
||||
])->withCount('accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count');
|
||||
|
||||
|
||||
/*
|
||||
@@ -94,38 +106,20 @@ class CategoriesController extends Controller
|
||||
$categories->where('checkin_email', '=', $request->input('checkin_email'));
|
||||
}
|
||||
|
||||
if ($request->filled('created_by')) {
|
||||
$categories->where('created_by', '=', $request->input('created_by'));
|
||||
}
|
||||
|
||||
if ($request->filled('created_at')) {
|
||||
$categories->where('created_at', '=', $request->input('created_at'));
|
||||
}
|
||||
|
||||
if ($request->filled('updated_at')) {
|
||||
$categories->where('updated_at', '=', $request->input('updated_at'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $categories->count()) ? $categories->count() : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort_override = $request->input('sort');
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets_count';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count';
|
||||
$categories->orderBy($sort, $order);
|
||||
|
||||
switch ($sort_override) {
|
||||
case 'created_by':
|
||||
$categories = $categories->OrderByCreatedBy($order);
|
||||
break;
|
||||
default:
|
||||
$categories = $categories->orderBy($column_sort, $order);
|
||||
break;
|
||||
}
|
||||
$paginator = $categories->paginate(app('page_number'));
|
||||
$total_results = $paginator->total();
|
||||
$results = $paginator->getCollection();
|
||||
|
||||
$total = $categories->count();
|
||||
$categories = $categories->skip($offset)->take($limit)->get();
|
||||
|
||||
return (new CategoriesTransformer)->transformCategories($categories, $total);
|
||||
return Fractal::create()
|
||||
->collection($results, new CategoriesTransformer())
|
||||
->serializeWith(new BootstrapTablesSerializer())
|
||||
->addMeta(['total' => $total_results])
|
||||
->paginateWith(new IlluminatePaginatorAdapter($paginator))
|
||||
->toArray();
|
||||
|
||||
}
|
||||
|
||||
@@ -164,7 +158,8 @@ class CategoriesController extends Controller
|
||||
{
|
||||
$this->authorize('view', Category::class);
|
||||
$category = Category::withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count')->findOrFail($id);
|
||||
return (new CategoriesTransformer)->transformCategory($category);
|
||||
$transformer = $category->first()->transformer;
|
||||
return $this->transformData($category, $transformer);
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -42,7 +42,7 @@ class CompaniesController extends Controller
|
||||
|
||||
$companies = Company::withCount(['assets as assets_count' => function ($query) {
|
||||
$query->AssetsForShow();
|
||||
}])->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'users as users_count');
|
||||
}])->withCount('licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'users as users_count');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$companies->TextSearch($request->input('search'));
|
||||
@@ -56,29 +56,17 @@ class CompaniesController extends Controller
|
||||
$companies->where('email', '=', $request->input('email'));
|
||||
}
|
||||
|
||||
if ($request->filled('created_by')) {
|
||||
$companies->where('created_by', '=', $request->input('created_by'));
|
||||
}
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $companies->count()) ? $companies->count() : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort_override = $request->input('sort');
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
|
||||
|
||||
switch ($sort_override) {
|
||||
case 'created_by':
|
||||
$companies = $companies->OrderByCreatedBy($order);
|
||||
break;
|
||||
default:
|
||||
$companies = $companies->orderBy($column_sort, $order);
|
||||
break;
|
||||
}
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$companies->orderBy($sort, $order);
|
||||
|
||||
$total = $companies->count();
|
||||
|
||||
$companies = $companies->skip($offset)->take($limit)->get();
|
||||
return (new CompaniesTransformer)->transformCompanies($companies, $total);
|
||||
|
||||
|
||||
@@ -38,7 +38,6 @@ class ComponentsController extends Controller
|
||||
'name',
|
||||
'min_amt',
|
||||
'order_number',
|
||||
'model_number',
|
||||
'serial',
|
||||
'purchase_date',
|
||||
'purchase_cost',
|
||||
@@ -48,7 +47,7 @@ class ComponentsController extends Controller
|
||||
];
|
||||
|
||||
$components = Component::select('components.*')
|
||||
->with('company', 'location', 'category', 'assets', 'supplier', 'adminuser', 'manufacturer');
|
||||
->with('company', 'location', 'category', 'assets', 'supplier');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$components = $components->TextSearch($request->input('search'));
|
||||
@@ -70,14 +69,6 @@ class ComponentsController extends Controller
|
||||
$components->where('supplier_id', '=', $request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('manufacturer_id')) {
|
||||
$components->where('manufacturer_id', '=', $request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('model_number')) {
|
||||
$components->where('model_number', '=', $request->input('model_number'));
|
||||
}
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
$components->where('location_id', '=', $request->input('location_id'));
|
||||
}
|
||||
@@ -107,12 +98,6 @@ class ComponentsController extends Controller
|
||||
case 'supplier':
|
||||
$components = $components->OrderSupplier($order);
|
||||
break;
|
||||
case 'manufacturer':
|
||||
$components = $components->OrderManufacturer($order);
|
||||
break;
|
||||
case 'created_by':
|
||||
$components = $components->OrderByCreatedBy($order);
|
||||
break;
|
||||
default:
|
||||
$components = $components->orderBy($column_sort, $order);
|
||||
break;
|
||||
@@ -285,7 +270,7 @@ class ComponentsController extends Controller
|
||||
'component_id' => $component->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'assigned_qty' => $request->get('assigned_qty', 1),
|
||||
'created_by' => auth()->id(),
|
||||
'user_id' => auth()->id(),
|
||||
'asset_id' => $request->get('assigned_to'),
|
||||
'note' => $request->get('note'),
|
||||
]);
|
||||
|
||||
@@ -86,15 +86,9 @@ class ConsumablesController extends Controller
|
||||
case 'company':
|
||||
$consumables = $consumables->OrderCompany($order);
|
||||
break;
|
||||
case 'remaining':
|
||||
$consumables = $consumables->OrderRemaining($order);
|
||||
break;
|
||||
case 'supplier':
|
||||
$consumables = $consumables->OrderSupplier($order);
|
||||
break;
|
||||
case 'created_by':
|
||||
$consumables = $consumables->OrderByCreatedBy($order);
|
||||
break;
|
||||
default:
|
||||
// This array is what determines which fields should be allowed to be sorted on ON the table itself.
|
||||
// These must match a column on the consumables table directly.
|
||||
@@ -213,7 +207,7 @@ class ConsumablesController extends Controller
|
||||
$consumable = Consumable::with(['consumableAssignments'=> function ($query) {
|
||||
$query->orderBy($query->getModel()->getTable().'.created_at', 'DESC');
|
||||
},
|
||||
'consumableAssignments.adminuser'=> function ($query) {
|
||||
'consumableAssignments.admin'=> function ($query) {
|
||||
},
|
||||
'consumableAssignments.user'=> function ($query) {
|
||||
},
|
||||
@@ -231,8 +225,7 @@ class ConsumablesController extends Controller
|
||||
'name' => ($consumable_assignment->user) ? $consumable_assignment->user->present()->nameUrl() : 'Deleted User',
|
||||
'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'),
|
||||
'note' => ($consumable_assignment->note) ? e($consumable_assignment->note) : null,
|
||||
'admin' => ($consumable_assignment->adminuser) ? $consumable_assignment->adminuser->present()->nameUrl() : null, // legacy, so we don't change the shape of the response
|
||||
'created_by' => ($consumable_assignment->adminuser) ? $consumable_assignment->adminuser->present()->nameUrl() : null,
|
||||
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : null,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -258,8 +251,6 @@ class ConsumablesController extends Controller
|
||||
|
||||
$this->authorize('checkout', $consumable);
|
||||
|
||||
$consumable->checkout_qty = $request->input('checkout_qty', 1);
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/consumables/message.checkout.unavailable')));
|
||||
@@ -270,12 +261,6 @@ class ConsumablesController extends Controller
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.invalid_item_category_single', ['type' => trans('general.consumable')])));
|
||||
}
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0 || $consumable->checkout_qty > $consumable->numRemaining()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/consumables/message.checkout.unavailable', ['requested' => $consumable->checkout_qty, 'remaining' => $consumable->numRemaining() ])));
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Check if the user exists - @TODO: this should probably be handled via validation, not here??
|
||||
if (!$user = User::find($request->input('assigned_to'))) {
|
||||
@@ -286,17 +271,14 @@ class ConsumablesController extends Controller
|
||||
// Update the consumable data
|
||||
$consumable->assigned_to = $request->input('assigned_to');
|
||||
|
||||
for ($i = 0; $i < $consumable->checkout_qty; $i++) {
|
||||
$consumable->users()->attach($consumable->id,
|
||||
$consumable->users()->attach($consumable->id,
|
||||
[
|
||||
'consumable_id' => $consumable->id,
|
||||
'created_by' => $user->id,
|
||||
'user_id' => $user->id,
|
||||
'assigned_to' => $request->input('assigned_to'),
|
||||
'note' => $request->input('note'),
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
event(new CheckoutableCheckedOut($consumable, $user, auth()->user(), $request->input('note')));
|
||||
|
||||
|
||||
@@ -97,7 +97,7 @@ class DepartmentsController extends Controller
|
||||
$department->fill($request->all());
|
||||
$department = $request->handleImages($department);
|
||||
|
||||
$department->created_by = auth()->id();
|
||||
$department->user_id = auth()->id();
|
||||
$department->manager_id = ($request->filled('manager_id') ? $request->input('manager_id') : null);
|
||||
|
||||
if ($department->save()) {
|
||||
|
||||
@@ -20,23 +20,9 @@ class DepreciationsController extends Controller
|
||||
public function index(Request $request) : JsonResponse | array
|
||||
{
|
||||
$this->authorize('view', Depreciation::class);
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
'name',
|
||||
'months',
|
||||
'depreciation_min',
|
||||
'depreciation_type',
|
||||
'created_at',
|
||||
'assets_count',
|
||||
'models_count',
|
||||
'licenses_count',
|
||||
];
|
||||
$allowed_columns = ['id','name','months','depreciation_min','created_at'];
|
||||
|
||||
$depreciations = Depreciation::select('id','name','months','depreciation_min','depreciation_type','created_at','updated_at', 'created_by')
|
||||
->with('adminuser')
|
||||
->withCount('assets as assets_count')
|
||||
->withCount('models as models_count')
|
||||
->withCount('licenses as licenses_count');
|
||||
$depreciations = Depreciation::select('id','name','months','depreciation_min','user_id','created_at','updated_at');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$depreciations = $depreciations->TextSearch($request->input('search'));
|
||||
@@ -45,18 +31,10 @@ class DepreciationsController extends Controller
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $depreciations->count()) ? $depreciations->count() : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort_override = $request->input('sort');
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
|
||||
|
||||
switch ($sort_override) {
|
||||
case 'created_by':
|
||||
$depreciations = $depreciations->OrderByCreatedBy($order);
|
||||
break;
|
||||
default:
|
||||
$depreciations = $depreciations->orderBy($column_sort, $order);
|
||||
break;
|
||||
}
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$depreciations->orderBy($sort, $order);
|
||||
|
||||
$total = $depreciations->count();
|
||||
$depreciations = $depreciations->skip($offset)->take($limit)->get();
|
||||
|
||||
@@ -23,8 +23,9 @@ class GroupsController extends Controller
|
||||
$this->authorize('superadmin');
|
||||
|
||||
$this->authorize('view', Group::class);
|
||||
$allowed_columns = ['id', 'name', 'created_at', 'users_count'];
|
||||
|
||||
$groups = Group::select('id', 'name', 'permissions', 'created_at', 'updated_at', 'created_by')->with('adminuser')->withCount('users as users_count');
|
||||
$groups = Group::select('id', 'name', 'permissions', 'created_at', 'updated_at', 'created_by')->with('admin')->withCount('users as users_count');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$groups = $groups->TextSearch($request->input('search'));
|
||||
@@ -34,29 +35,13 @@ class GroupsController extends Controller
|
||||
$groups->where('name', '=', $request->input('name'));
|
||||
}
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $groups->count()) ? $groups->count() : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
switch ($request->input('sort')) {
|
||||
case 'created_by':
|
||||
$groups = $groups->OrderByCreatedBy($order);
|
||||
break;
|
||||
default:
|
||||
// This array is what determines which fields should be allowed to be sorted on ON the table itself.
|
||||
// These must match a column on the consumables table directly.
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
'name',
|
||||
'created_at',
|
||||
'users_count',
|
||||
];
|
||||
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$groups = $groups->orderBy($sort, $order);
|
||||
break;
|
||||
}
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$groups->orderBy($sort, $order);
|
||||
|
||||
$total = $groups->count();
|
||||
$groups = $groups->skip($offset)->take($limit)->get();
|
||||
|
||||
@@ -107,7 +107,7 @@ class LicenseSeatsController extends Controller
|
||||
|
||||
// attempt to update the license seat
|
||||
$licenseSeat->fill($request->all());
|
||||
$licenseSeat->created_by = auth()->id();
|
||||
$licenseSeat->user_id = auth()->id();
|
||||
|
||||
// check if this update is a checkin operation
|
||||
// 1. are relevant fields touched at all?
|
||||
|
||||
@@ -24,10 +24,10 @@ class LicensesController extends Controller
|
||||
{
|
||||
$this->authorize('view', License::class);
|
||||
|
||||
$licenses = License::with('company', 'manufacturer', 'supplier','category', 'adminuser')->withCount('freeSeats as free_seats_count');
|
||||
$licenses = License::with('company', 'manufacturer', 'supplier','category')->withCount('freeSeats as free_seats_count');
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
$licenses->where('licenses.company_id', '=', $request->input('company_id'));
|
||||
$licenses->where('company_id', '=', $request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('name')) {
|
||||
@@ -70,9 +70,6 @@ class LicensesController extends Controller
|
||||
$licenses->where('depreciation_id', '=', $request->input('depreciation_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('created_by')) {
|
||||
$licenses->where('created_by', '=', $request->input('created_by'));
|
||||
}
|
||||
|
||||
if (($request->filled('maintained')) && ($request->input('maintained')=='true')) {
|
||||
$licenses->where('maintained','=',1);
|
||||
@@ -116,9 +113,6 @@ class LicensesController extends Controller
|
||||
case 'company':
|
||||
$licenses = $licenses->leftJoin('companies', 'licenses.company_id', '=', 'companies.id')->orderBy('companies.name', $order);
|
||||
break;
|
||||
case 'created_by':
|
||||
$licenses = $licenses->OrderByCreatedBy($order);
|
||||
break;
|
||||
default:
|
||||
$allowed_columns =
|
||||
[
|
||||
@@ -182,7 +176,7 @@ class LicensesController extends Controller
|
||||
public function show($id) : JsonResponse | array
|
||||
{
|
||||
$this->authorize('view', License::class);
|
||||
$license = License::withCount('freeSeats as free_seats_count')->findOrFail($id);
|
||||
$license = License::withCount('freeSeats')->findOrFail($id);
|
||||
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
|
||||
|
||||
return (new LicensesTransformer)->transformLicense($license);
|
||||
@@ -220,6 +214,7 @@ class LicensesController extends Controller
|
||||
*/
|
||||
public function destroy($id) : JsonResponse
|
||||
{
|
||||
//
|
||||
$license = License::findOrFail($id);
|
||||
$this->authorize('delete', $license);
|
||||
|
||||
|
||||
@@ -5,10 +5,8 @@ namespace App\Http\Controllers\Api;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\AssetsTransformer;
|
||||
use App\Http\Transformers\LocationsTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Location;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Pagination\LengthAwarePaginator;
|
||||
@@ -224,15 +222,6 @@ class LocationsController extends Controller
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $location->getErrors()));
|
||||
}
|
||||
|
||||
public function assets(Request $request, Location $location) : JsonResponse | array
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
$this->authorize('view', $location);
|
||||
$assets = Asset::where('assigned_to', '=', $location->id)->where('assigned_type', '=', Location::class)->with('model', 'model.category', 'assetstatus', 'location', 'company', 'defaultLoc');
|
||||
$assets = $assets->get();
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
@@ -248,7 +237,6 @@ class LocationsController extends Controller
|
||||
->withCount('rtd_assets as rtd_assets_count')
|
||||
->withCount('children as children_count')
|
||||
->withCount('users as users_count')
|
||||
->withCount('accessories as accessories_count')
|
||||
->findOrFail($id);
|
||||
|
||||
if (! $location->isDeletable()) {
|
||||
|
||||
@@ -25,43 +25,11 @@ class ManufacturersController extends Controller
|
||||
public function index(Request $request) : JsonResponse | array
|
||||
{
|
||||
$this->authorize('view', Manufacturer::class);
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
'name',
|
||||
'url',
|
||||
'support_url',
|
||||
'support_email',
|
||||
'warranty_lookup_url',
|
||||
'support_phone',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'image',
|
||||
'assets_count',
|
||||
'consumables_count',
|
||||
'components_count',
|
||||
'licenses_count'
|
||||
];
|
||||
$allowed_columns = ['id', 'name', 'url', 'support_url', 'support_email', 'warranty_lookup_url', 'support_phone', 'created_at', 'updated_at', 'image', 'assets_count', 'consumables_count', 'components_count', 'licenses_count'];
|
||||
|
||||
$manufacturers = Manufacturer::select([
|
||||
'id',
|
||||
'name',
|
||||
'url',
|
||||
'support_url',
|
||||
'warranty_lookup_url',
|
||||
'support_email',
|
||||
'support_phone',
|
||||
'created_by',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'image',
|
||||
'deleted_at',
|
||||
])
|
||||
->with('adminuser')
|
||||
->withCount('assets as assets_count')
|
||||
->withCount('licenses as licenses_count')
|
||||
->withCount('consumables as consumables_count')
|
||||
->withCount('accessories as accessories_count')
|
||||
->withCount('components as components_count');
|
||||
$manufacturers = Manufacturer::select(
|
||||
['id', 'name', 'url', 'support_url', 'warranty_lookup_url', 'support_email', 'support_phone', 'created_at', 'updated_at', 'image', 'deleted_at']
|
||||
)->withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('consumables as consumables_count')->withCount('accessories as accessories_count');
|
||||
|
||||
if ($request->input('deleted') == 'true') {
|
||||
$manufacturers->onlyTrashed();
|
||||
@@ -98,18 +66,10 @@ class ManufacturersController extends Controller
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $manufacturers->count()) ? $manufacturers->count() : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort_override = $request->input('sort');
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
|
||||
|
||||
switch ($sort_override) {
|
||||
case 'created_by':
|
||||
$manufacturers = $manufacturers->OrderByCreatedBy($order);
|
||||
break;
|
||||
default:
|
||||
$manufacturers = $manufacturers->orderBy($column_sort, $order);
|
||||
break;
|
||||
}
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$manufacturers->orderBy($sort, $order);
|
||||
|
||||
$total = $manufacturers->count();
|
||||
$manufacturers = $manufacturers->skip($offset)->take($limit)->get();
|
||||
@@ -221,7 +181,7 @@ class ManufacturersController extends Controller
|
||||
$logaction->item_type = Manufacturer::class;
|
||||
$logaction->item_id = $manufacturer->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->user_id = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', trans('admin/manufacturers/message.restore.success')), 200);
|
||||
|
||||
@@ -23,8 +23,9 @@ class PredefinedKitsController extends Controller
|
||||
public function index(Request $request) : JsonResponse | array
|
||||
{
|
||||
$this->authorize('view', PredefinedKit::class);
|
||||
$allowed_columns = ['id', 'name'];
|
||||
|
||||
$kits = PredefinedKit::query()->with('adminuser');
|
||||
$kits = PredefinedKit::query();
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$kits = $kits->TextSearch($request->input('search'));
|
||||
@@ -35,25 +36,8 @@ class PredefinedKitsController extends Controller
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$order = $request->input('order') === 'desc' ? 'desc' : 'asc';
|
||||
|
||||
switch ($request->input('sort')) {
|
||||
case 'created_by':
|
||||
$kits = $kits->OrderByCreatedBy($order);
|
||||
break;
|
||||
default:
|
||||
// This array is what determines which fields should be allowed to be sorted on ON the table itself.
|
||||
// These must match a column on the consumables table directly.
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
'name',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
];
|
||||
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$kits = $kits->orderBy($sort, $order);
|
||||
break;
|
||||
}
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'name';
|
||||
$kits->orderBy($sort, $order);
|
||||
|
||||
$total = $kits->count();
|
||||
$kits = $kits->skip($offset)->take($limit)->get();
|
||||
@@ -262,7 +246,7 @@ class PredefinedKitsController extends Controller
|
||||
|
||||
$relation = $kit->models();
|
||||
if ($relation->find($model_id)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, ['model' => trans('admin/kits/general.model_already_attached')]));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, ['model' => 'Model already attached to kit']));
|
||||
}
|
||||
$relation->attach($model_id, ['quantity' => $quantity]);
|
||||
|
||||
|
||||
@@ -20,7 +20,7 @@ class ReportsController extends Controller
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
|
||||
$actionlogs = Actionlog::with('item', 'user', 'adminuser', 'target', 'location');
|
||||
$actionlogs = Actionlog::with('item', 'user', 'admin', 'target', 'location');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$actionlogs = $actionlogs->TextSearch(e($request->input('search')));
|
||||
@@ -48,8 +48,8 @@ class ReportsController extends Controller
|
||||
$actionlogs = $actionlogs->where('action_type', '=', $request->input('action_type'))->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
if ($request->filled('created_by')) {
|
||||
$actionlogs = $actionlogs->where('created_by', '=', $request->input('created_by'));
|
||||
if ($request->filled('user_id')) {
|
||||
$actionlogs = $actionlogs->where('user_id', '=', $request->input('user_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('action_source')) {
|
||||
@@ -68,14 +68,13 @@ class ReportsController extends Controller
|
||||
'id',
|
||||
'created_at',
|
||||
'target_id',
|
||||
'created_by',
|
||||
'user_id',
|
||||
'accept_signature',
|
||||
'action_type',
|
||||
'note',
|
||||
'remote_ip',
|
||||
'user_agent',
|
||||
'action_source',
|
||||
'action_date',
|
||||
];
|
||||
|
||||
|
||||
@@ -84,19 +83,11 @@ class ReportsController extends Controller
|
||||
$offset = ($request->input('offset') > $total) ? $total : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
||||
$order = ($request->input('order') == 'asc') ? 'asc' : 'desc';
|
||||
|
||||
switch ($request->input('sort')) {
|
||||
case 'created_by':
|
||||
$actionlogs->OrderByCreatedBy($order);
|
||||
break;
|
||||
default:
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
||||
$actionlogs = $actionlogs->orderBy($sort, $order);
|
||||
break;
|
||||
}
|
||||
|
||||
$actionlogs = $actionlogs->skip($offset)->take($limit)->get();
|
||||
$actionlogs = $actionlogs->orderBy($sort, $order)->skip($offset)->take($limit)->get();
|
||||
|
||||
return response()->json((new ActionlogsTransformer)->transformActionlogs($actionlogs, $total), 200, ['Content-Type' => 'application/json;charset=utf8'], JSON_UNESCAPED_UNICODE);
|
||||
}
|
||||
|
||||
@@ -8,7 +8,6 @@ use App\Http\Transformers\AssetsTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Http\Transformers\StatuslabelsTransformer;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Statuslabel;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Transformers\PieChartTransformer;
|
||||
@@ -25,18 +24,9 @@ class StatuslabelsController extends Controller
|
||||
public function index(Request $request) : array
|
||||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
'name',
|
||||
'created_at',
|
||||
'assets_count',
|
||||
'color',
|
||||
'notes',
|
||||
'default_label',
|
||||
'status_type',
|
||||
];
|
||||
$allowed_columns = ['id', 'name', 'created_at', 'assets_count', 'color', 'notes', 'default_label'];
|
||||
|
||||
$statuslabels = Statuslabel::with('adminuser')->withCount('assets as assets_count');
|
||||
$statuslabels = Statuslabel::withCount('assets as assets_count');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$statuslabels = $statuslabels->TextSearch($request->input('search'));
|
||||
@@ -50,30 +40,23 @@ class StatuslabelsController extends Controller
|
||||
// if a status_type is passed, filter by that
|
||||
if ($request->filled('status_type')) {
|
||||
if (strtolower($request->input('status_type')) == 'pending') {
|
||||
$statuslabels->where('status_type', '=', 'pending');
|
||||
} elseif (strtolower($request->input('status_type')) == 'archived') $statuslabels->where('status_type', '=', 'archived');
|
||||
elseif (strtolower($request->input('status_type')) == 'deployable') {
|
||||
$statuslabels->where('status_type', '=', 'deployable');
|
||||
$statuslabels = $statuslabels->Pending();
|
||||
} elseif (strtolower($request->input('status_type')) == 'archived') {
|
||||
$statuslabels = $statuslabels->Archived();
|
||||
} elseif (strtolower($request->input('status_type')) == 'deployable') {
|
||||
$statuslabels = $statuslabels->Deployable();
|
||||
} elseif (strtolower($request->input('status_type')) == 'undeployable') {
|
||||
$statuslabels->whereNot('status_type', 'deployable');
|
||||
$statuslabels = $statuslabels->Undeployable();
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $statuslabels->count()) ? $statuslabels->count() : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort_override = $request->input('sort');
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
|
||||
|
||||
switch ($sort_override) {
|
||||
case 'created_by':
|
||||
$statuslabels = $statuslabels->OrderByCreatedBy($order);
|
||||
break;
|
||||
default:
|
||||
$statuslabels = $statuslabels->orderBy($column_sort, $order);
|
||||
break;
|
||||
}
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
$statuslabels->orderBy($sort, $order);
|
||||
|
||||
$total = $statuslabels->count();
|
||||
$statuslabels = $statuslabels->skip($offset)->take($limit)->get();
|
||||
@@ -92,11 +75,19 @@ class StatuslabelsController extends Controller
|
||||
public function store(Request $request) : JsonResponse
|
||||
{
|
||||
$this->authorize('create', Statuslabel::class);
|
||||
$request->except('deployable', 'pending', 'archived');
|
||||
|
||||
if (! $request->filled('type')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, ['type' => ['Status label type is required.']]), 500);
|
||||
}
|
||||
|
||||
$statuslabel = new Statuslabel;
|
||||
$statuslabel->fill($request->all());
|
||||
$statuslabel->status_type = $request->input('status_type');
|
||||
|
||||
$statusType = Statuslabel::getStatuslabelTypesForDB($request->input('type'));
|
||||
$statuslabel->deployable = $statusType['deployable'];
|
||||
$statuslabel->pending = $statusType['pending'];
|
||||
$statuslabel->archived = $statusType['archived'];
|
||||
$statuslabel->color = $request->input('color');
|
||||
$statuslabel->show_in_nav = $request->input('show_in_nav', 0);
|
||||
$statuslabel->default_label = $request->input('default_label', 0);
|
||||
@@ -137,12 +128,20 @@ class StatuslabelsController extends Controller
|
||||
{
|
||||
$this->authorize('update', Statuslabel::class);
|
||||
$statuslabel = Statuslabel::findOrFail($id);
|
||||
|
||||
$request->except('deployable', 'pending', 'archived');
|
||||
|
||||
|
||||
if (! $request->filled('type')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Status label type is required.'));
|
||||
}
|
||||
|
||||
$statuslabel->fill($request->all());
|
||||
|
||||
$statusType = Statuslabel::getStatuslabelTypesForDB($request->input('type'));
|
||||
$statuslabel->status_type = $request->input('status_type');
|
||||
$statuslabel->deployable = $statusType['deployable'];
|
||||
$statuslabel->pending = $statusType['pending'];
|
||||
$statuslabel->archived = $statusType['archived'];
|
||||
$statuslabel->color = $request->input('color');
|
||||
$statuslabel->show_in_nav = $request->input('show_in_nav', 0);
|
||||
$statuslabel->default_label = $request->input('default_label', 0);
|
||||
@@ -188,14 +187,8 @@ class StatuslabelsController extends Controller
|
||||
public function getAssetCountByStatuslabel() : array
|
||||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
|
||||
if (Setting::getSettings()->show_archived_in_list == 0 ) {
|
||||
$statuslabels = Statuslabel::withCount('assets')->whereNot('status_type','archived')->get();
|
||||
} else {
|
||||
$statuslabels = Statuslabel::withCount('assets')->get();
|
||||
}
|
||||
|
||||
$total = [];
|
||||
$statuslabels = Statuslabel::withCount('assets')->get();
|
||||
$total = Array();
|
||||
|
||||
foreach ($statuslabels as $statuslabel) {
|
||||
|
||||
@@ -284,7 +277,7 @@ class StatuslabelsController extends Controller
|
||||
public function checkIfDeployable($id) : string
|
||||
{
|
||||
$statuslabel = Statuslabel::findOrFail($id);
|
||||
if ($statuslabel->status_type == 'deployable') {
|
||||
if ($statuslabel->getStatuslabelType() == 'deployable') {
|
||||
return '1';
|
||||
}
|
||||
|
||||
@@ -302,22 +295,22 @@ class StatuslabelsController extends Controller
|
||||
{
|
||||
|
||||
$this->authorize('view.selectlists');
|
||||
$statuslabels = Statuslabel::orderBy('default_label', 'desc')->orderBy('name', 'asc')->orderBy('status_type', 'desc');
|
||||
$statuslabels = Statuslabel::orderBy('default_label', 'desc')->orderBy('name', 'asc')->orderBy('deployable', 'desc');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$statuslabels = $statuslabels->where('name', 'LIKE', '%'.$request->get('search').'%');
|
||||
}
|
||||
|
||||
if ($request->filled('deployable')) {
|
||||
$statuslabels = $statuslabels->where('status_type', '=', 'deployable');
|
||||
$statuslabels = $statuslabels->where('deployable', '=', '1');
|
||||
}
|
||||
|
||||
if ($request->filled('pending')) {
|
||||
$statuslabels = $statuslabels->where('status_type', '=', 'pending');
|
||||
$statuslabels = $statuslabels->where('pending', '=', '1');
|
||||
}
|
||||
|
||||
if ($request->filled('archived')) {
|
||||
$statuslabels = $statuslabels->where('status_type', '=', 'archived');
|
||||
$statuslabels = $statuslabels->where('archived', '=', '1');
|
||||
}
|
||||
|
||||
$statuslabels = $statuslabels->orderBy('name', 'ASC')->paginate(50);
|
||||
|
||||
@@ -14,7 +14,6 @@ use App\Http\Transformers\UsersTransformer;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Company;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
@@ -43,14 +42,13 @@ class UsersController extends Controller
|
||||
|
||||
$users = User::select([
|
||||
'users.activated',
|
||||
'users.created_by',
|
||||
'users.address',
|
||||
'users.avatar',
|
||||
'users.city',
|
||||
'users.company_id',
|
||||
'users.country',
|
||||
'users.created_by',
|
||||
'users.created_at',
|
||||
'users.updated_at',
|
||||
'users.deleted_at',
|
||||
'users.department_id',
|
||||
'users.email',
|
||||
@@ -69,6 +67,7 @@ class UsersController extends Controller
|
||||
'users.state',
|
||||
'users.two_factor_enrolled',
|
||||
'users.two_factor_optin',
|
||||
'users.updated_at',
|
||||
'users.username',
|
||||
'users.zip',
|
||||
'users.remote',
|
||||
@@ -207,10 +206,6 @@ class UsersController extends Controller
|
||||
$users->where('autoassign_licenses', '=', $request->input('autoassign_licenses'));
|
||||
}
|
||||
|
||||
if ($request->filled('locale')) {
|
||||
$users = $users->where('users.locale', '=', $request->input('locale'));
|
||||
}
|
||||
|
||||
|
||||
if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
|
||||
$users = $users->onlyTrashed();
|
||||
@@ -256,7 +251,6 @@ class UsersController extends Controller
|
||||
'groups',
|
||||
'activated',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'two_factor_enrolled',
|
||||
'two_factor_optin',
|
||||
'last_login',
|
||||
@@ -282,7 +276,6 @@ class UsersController extends Controller
|
||||
'end_date',
|
||||
'autoassign_licenses',
|
||||
'website',
|
||||
'locale',
|
||||
];
|
||||
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'first_name';
|
||||
@@ -372,7 +365,6 @@ class UsersController extends Controller
|
||||
|
||||
$user = new User;
|
||||
$user->fill($request->all());
|
||||
$user->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$user->created_by = auth()->id();
|
||||
|
||||
if ($request->has('permissions')) {
|
||||
@@ -435,10 +427,13 @@ class UsersController extends Controller
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
*/
|
||||
public function update(SaveUserRequest $request, User $user): JsonResponse
|
||||
public function update(SaveUserRequest $request, $id) : JsonResponse
|
||||
{
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
if ($user = User::find($id)) {
|
||||
|
||||
|
||||
$this->authorize('update', $user);
|
||||
|
||||
/**
|
||||
@@ -448,15 +443,13 @@ class UsersController extends Controller
|
||||
*
|
||||
*/
|
||||
|
||||
if ((($user->id == 1) || ($user->id == 2)) && (config('app.lock_passwords'))) {
|
||||
|
||||
if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.'));
|
||||
}
|
||||
|
||||
$user->fill($request->all());
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
$user->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
}
|
||||
$user->fill($request->all());
|
||||
|
||||
if ($user->id == $request->input('manager_id')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
|
||||
@@ -480,13 +473,16 @@ class UsersController extends Controller
|
||||
$user->permissions = $permissions_array;
|
||||
}
|
||||
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
|
||||
|
||||
|
||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
|
||||
|
||||
if ($user->save()) {
|
||||
|
||||
// Check if the request has groups passed and has a value, AND that the user us a superuser
|
||||
if (($request->has('groups')) && (auth()->user()->isSuperUser())) {
|
||||
|
||||
@@ -500,10 +496,18 @@ class UsersController extends Controller
|
||||
|
||||
// Sync the groups since the user is a superuser and the groups pass validation
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -698,7 +702,7 @@ class UsersController extends Controller
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->item_id = $user->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->user_id = auth()->id();
|
||||
$logaction->logaction('2FA reset');
|
||||
|
||||
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_success')], 200);
|
||||
@@ -748,7 +752,7 @@ class UsersController extends Controller
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->item_id = $user->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->user_id = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.restored')), 200);
|
||||
|
||||
@@ -109,7 +109,7 @@ class AssetMaintenancesController extends Controller
|
||||
$assetMaintenance->title = $request->input('title');
|
||||
$assetMaintenance->start_date = $request->input('start_date');
|
||||
$assetMaintenance->completion_date = $request->input('completion_date');
|
||||
$assetMaintenance->created_by = auth()->id();
|
||||
$assetMaintenance->user_id = Auth::id();
|
||||
|
||||
if (($assetMaintenance->completion_date !== null)
|
||||
&& ($assetMaintenance->start_date !== '')
|
||||
|
||||
@@ -78,7 +78,7 @@ class AssetModelsController extends Controller
|
||||
$model->manufacturer_id = $request->input('manufacturer_id');
|
||||
$model->category_id = $request->input('category_id');
|
||||
$model->notes = $request->input('notes');
|
||||
$model->created_by = auth()->id();
|
||||
$model->user_id = Auth::id();
|
||||
$model->requestable = $request->has('requestable');
|
||||
|
||||
if ($request->input('fieldset_id') != '') {
|
||||
@@ -151,17 +151,17 @@ class AssetModelsController extends Controller
|
||||
$model->notes = $request->input('notes');
|
||||
$model->requestable = $request->input('requestable', '0');
|
||||
|
||||
$this->removeCustomFieldsDefaultValues($model);
|
||||
|
||||
$model->fieldset_id = $request->input('fieldset_id');
|
||||
|
||||
if ($model->save()) {
|
||||
$this->removeCustomFieldsDefaultValues($model);
|
||||
|
||||
if ($this->shouldAddDefaultValues($request->input())) {
|
||||
if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))) {
|
||||
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.fieldset_default_value.error'));
|
||||
}
|
||||
if ($this->shouldAddDefaultValues($request->input())) {
|
||||
if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){
|
||||
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.fieldset_default_value.error'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($model->save()) {
|
||||
if ($model->wasChanged('eol')) {
|
||||
if ($model->eol > 0) {
|
||||
$newEol = $model->eol;
|
||||
@@ -202,7 +202,6 @@ class AssetModelsController extends Controller
|
||||
if ($model->image) {
|
||||
try {
|
||||
Storage::disk('public')->delete('models/'.$model->image);
|
||||
$model->update(['image' => null]);
|
||||
} catch (\Exception $e) {
|
||||
Log::info($e);
|
||||
}
|
||||
@@ -234,10 +233,10 @@ class AssetModelsController extends Controller
|
||||
|
||||
if ($model->restore()) {
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = AssetModel::class;
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->item_id = $model->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->user_id = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
|
||||
|
||||
@@ -11,6 +11,7 @@ use App\Models\Asset;
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\LicenseSeat;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use \Illuminate\Http\RedirectResponse;
|
||||
@@ -82,6 +83,7 @@ class AssetCheckinController extends Controller
|
||||
}
|
||||
|
||||
$asset->expected_checkin = null;
|
||||
//$asset->last_checkout = null;
|
||||
$asset->last_checkin = now();
|
||||
$asset->assignedTo()->disassociate($asset);
|
||||
$asset->accepted = null;
|
||||
@@ -126,12 +128,12 @@ class AssetCheckinController extends Controller
|
||||
$acceptance->delete();
|
||||
});
|
||||
|
||||
session()->put('redirect_option', $request->get('redirect_option'));
|
||||
|
||||
Session::put('redirect_option', $request->get('redirect_option'));
|
||||
// Was the asset updated?
|
||||
if ($asset->save()) {
|
||||
|
||||
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), $request->input('note'), $checkin_at, $originalValues));
|
||||
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))->with('success', trans('admin/hardware/message.checkin.success'));
|
||||
return Helper::getRedirectOption($asset, $assetId, 'Assets');
|
||||
}
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.error').$asset->getErrors());
|
||||
|
||||
@@ -109,11 +109,10 @@ class AssetCheckoutController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
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'));
|
||||
return Helper::getRedirectOption($request, $assetId, 'Assets');
|
||||
}
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('admin/hardware/message.checkout.error').$asset->getErrors());
|
||||
|
||||
@@ -61,30 +61,43 @@ class AssetFilesController extends Controller
|
||||
*/
|
||||
public function show($assetId = null, $fileId = null) : View | RedirectResponse | Response | StreamedResponse | BinaryFileResponse
|
||||
{
|
||||
if ($asset = Asset::find($assetId)) {
|
||||
|
||||
$asset = Asset::find($assetId);
|
||||
// the asset is valid
|
||||
if (isset($asset->id)) {
|
||||
$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)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
return redirect()->route('hardware.show', ['hardware' => $asset])->with('error', trans('general.log_record_not_found'));
|
||||
$file = 'private_uploads/assets/'.$log->filename;
|
||||
|
||||
if ($log->action_type == 'audit') {
|
||||
$file = 'private_uploads/audits/'.$log->filename;
|
||||
}
|
||||
|
||||
if (! Storage::exists($file)) {
|
||||
return response('File '.$file.' not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/hardware/message.does_not_exist', ['id' => $fileId]);
|
||||
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
|
||||
// Redirect to the hardware management page
|
||||
return redirect()->route('hardware.index')->with('error', $error);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Http\Controllers\Assets;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
@@ -17,6 +16,7 @@ use App\Models\Location;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\View\Label;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -111,10 +111,8 @@ class AssetsController extends Controller
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
$successes = [];
|
||||
$failures = [];
|
||||
$success = false;
|
||||
$serials = $request->input('serials');
|
||||
$asset = null;
|
||||
|
||||
for ($a = 1; $a <= count($asset_tags); $a++) {
|
||||
$asset = new Asset();
|
||||
@@ -134,7 +132,7 @@ class AssetsController extends Controller
|
||||
$asset->model_id = $request->input('model_id');
|
||||
$asset->order_number = $request->input('order_number');
|
||||
$asset->notes = $request->input('notes');
|
||||
$asset->created_by = auth()->id();
|
||||
$asset->user_id = Auth::id();
|
||||
$asset->status_id = request('status_id');
|
||||
$asset->warranty_months = request('warranty_months', null);
|
||||
$asset->purchase_cost = request('purchase_cost');
|
||||
@@ -167,7 +165,7 @@ class AssetsController extends Controller
|
||||
if (($model) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('assets.view.encrypted_custom_fields')) {
|
||||
if (Gate::allows('admin')) {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = Crypt::encrypt(implode(', ', $request->input($field->db_column)));
|
||||
} else {
|
||||
@@ -201,35 +199,16 @@ 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>";
|
||||
|
||||
} else {
|
||||
$failures[] = join(",", $asset->getErrors()->all());
|
||||
$success = true;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
|
||||
|
||||
|
||||
if ($successes) {
|
||||
if ($failures) {
|
||||
//some succeeded, some failed
|
||||
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets')) //FIXME - not tested
|
||||
->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['links' => join(", ", $successes)]))
|
||||
->with('warning', trans_choice('admin/hardware/message.create.partial_failure', $failures, ['failures' => join("; ", $failures)]));
|
||||
} else {
|
||||
if (count($successes) == 1) {
|
||||
//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)]));
|
||||
} else {
|
||||
//multi-success
|
||||
return redirect()->to(Helper::getRedirectOption($request, $asset->id, 'Assets'))
|
||||
->with('success-unescaped', trans_choice('admin/hardware/message.create.multi_success_linked', $successes, ['links' => join(", ", $successes)]));
|
||||
}
|
||||
}
|
||||
|
||||
if ($success) {
|
||||
return redirect()->route('hardware.index')
|
||||
->with('success-unescaped', trans('admin/hardware/message.create.success_linked', ['link' => route('hardware.show', $asset->id), 'id', 'tag' => e($asset->asset_tag)]));
|
||||
|
||||
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($asset->getErrors());
|
||||
@@ -310,7 +289,6 @@ class AssetsController extends Controller
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $assetId = null) : RedirectResponse
|
||||
{
|
||||
|
||||
// Check if the asset exists
|
||||
if (! $asset = Asset::find($assetId)) {
|
||||
// Redirect to the asset management page with error
|
||||
@@ -345,21 +323,16 @@ class AssetsController extends Controller
|
||||
}
|
||||
$asset->supplier_id = $request->input('supplier_id', null);
|
||||
$asset->expected_checkin = $request->input('expected_checkin', null);
|
||||
$asset->requestable = $request->input('requestable', 0);
|
||||
|
||||
// If the box isn't checked, it's not in the request at all.
|
||||
$asset->requestable = $request->filled('requestable');
|
||||
$asset->rtd_location_id = $request->input('rtd_location_id', null);
|
||||
$asset->byod = $request->input('byod', 0);
|
||||
|
||||
$status = Statuslabel::find($request->input('status_id'));
|
||||
$status = Statuslabel::find($asset->status_id);
|
||||
|
||||
// This is a non-deployable status label - we should check the asset back in.
|
||||
if (($status && $status->status_type != 'deployable') && ($target = $asset->assignedTo)) {
|
||||
|
||||
$originalValues = $asset->getRawOriginal();
|
||||
if($status->archived){
|
||||
$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));
|
||||
}
|
||||
|
||||
if ($asset->assigned_to == '') {
|
||||
@@ -377,26 +350,14 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
// Update the asset data
|
||||
|
||||
$asset_tag = $request->input('asset_tags');
|
||||
$serial = $request->input('serials');
|
||||
$asset->serial = $request->input('serials');
|
||||
|
||||
if (is_array($request->input('serials'))) {
|
||||
$asset->serial = $serial[1];
|
||||
}
|
||||
|
||||
$asset->name = $request->input('name');
|
||||
$asset->serial = $serial[1];
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$asset->model_id = $request->input('model_id');
|
||||
$asset->order_number = $request->input('order_number');
|
||||
|
||||
$asset_tags = $request->input('asset_tags');
|
||||
$asset->asset_tag = $request->input('asset_tags');
|
||||
|
||||
if (is_array($request->input('asset_tags'))) {
|
||||
$asset->asset_tag = $asset_tags[1];
|
||||
}
|
||||
|
||||
$asset->asset_tag = $asset_tag[1];
|
||||
$asset->notes = $request->input('notes');
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
@@ -408,9 +369,8 @@ class AssetsController extends Controller
|
||||
$model = AssetModel::find($request->get('model_id'));
|
||||
if (($model) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('assets.view.encrypted_custom_fields')) {
|
||||
if (Gate::allows('admin')) {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = Crypt::encrypt(implode(', ', $request->input($field->db_column)));
|
||||
} else {
|
||||
@@ -427,10 +387,9 @@ 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()->route('hardware.show', $assetId)
|
||||
->with('success', trans('admin/hardware/message.update.success'));
|
||||
}
|
||||
|
||||
@@ -444,7 +403,7 @@ class AssetsController extends Controller
|
||||
* @param int $assetId
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function destroy(Request $request, $assetId) : RedirectResponse
|
||||
public function destroy($assetId) : RedirectResponse
|
||||
{
|
||||
// Check if the asset exists
|
||||
if (is_null($asset = Asset::find($assetId))) {
|
||||
@@ -454,17 +413,9 @@ class AssetsController extends Controller
|
||||
|
||||
$this->authorize('delete', $asset);
|
||||
|
||||
if ($asset->assignedTo) {
|
||||
|
||||
$target = $asset->assignedTo;
|
||||
$checkin_at = date('Y-m-d H:i:s');
|
||||
$originalValues = $asset->getRawOriginal();
|
||||
event(new CheckoutableCheckedIn($asset, $target, auth()->user(), 'Checkin on delete', $checkin_at, $originalValues));
|
||||
DB::table('assets')
|
||||
->where('id', $asset->id)
|
||||
->update(['assigned_to' => null]);
|
||||
}
|
||||
|
||||
DB::table('assets')
|
||||
->where('id', $asset->id)
|
||||
->update(['assigned_to' => null]);
|
||||
|
||||
if ($asset->image) {
|
||||
try {
|
||||
@@ -508,16 +459,9 @@ class AssetsController extends Controller
|
||||
$tag = $tag ? $tag : $request->get('assetTag');
|
||||
$topsearch = ($request->get('topsearch') == 'true');
|
||||
|
||||
// Search for an exact and unique asset tag match
|
||||
$assets = Asset::where('asset_tag', '=', $tag);
|
||||
|
||||
// If not a unique result, redirect to the index view
|
||||
if ($assets->count() != 1) {
|
||||
return redirect()->route('hardware.index')
|
||||
->with('search', $tag)
|
||||
->with('warning', trans('admin/hardware/message.does_not_exist_var', [ 'asset_tag' => $tag ]));
|
||||
if (! $asset = Asset::where('asset_tag', '=', $tag)->first()) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
$asset = $assets->first();
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
return redirect()->route('hardware.show', $asset->id)->with('topsearch', $topsearch);
|
||||
@@ -632,20 +576,26 @@ class AssetsController extends Controller
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function getClone(Asset $asset)
|
||||
public function getClone($assetId = null)
|
||||
{
|
||||
$this->authorize('create', $asset);
|
||||
$cloned = clone $asset;
|
||||
$cloned->id = null;
|
||||
$cloned->asset_tag = '';
|
||||
$cloned->serial = '';
|
||||
$cloned->assigned_to = '';
|
||||
$cloned->deleted_at = '';
|
||||
// Check if the asset exists
|
||||
if (is_null($asset_to_clone = Asset::find($assetId))) {
|
||||
// Redirect to the asset management page
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('create', $asset_to_clone);
|
||||
|
||||
$asset = clone $asset_to_clone;
|
||||
$asset->id = null;
|
||||
$asset->asset_tag = '';
|
||||
$asset->serial = '';
|
||||
$asset->assigned_to = '';
|
||||
|
||||
return view('hardware/edit')
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
->with('statuslabel_types', Helper::statusTypeList())
|
||||
->with('item', $cloned);
|
||||
->with('item', $asset);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -769,7 +719,7 @@ class AssetsController extends Controller
|
||||
Actionlog::firstOrCreate([
|
||||
'item_id' => $asset->id,
|
||||
'item_type' => Asset::class,
|
||||
'created_by' => auth()->id(),
|
||||
'user_id' => auth()->id(),
|
||||
'note' => 'Checkout imported by '.auth()->user()->present()->fullName().' from history importer',
|
||||
'target_id' => $item[$asset_tag][$batch_counter]['user_id'],
|
||||
'target_type' => User::class,
|
||||
@@ -797,7 +747,7 @@ class AssetsController extends Controller
|
||||
Actionlog::firstOrCreate([
|
||||
'item_id' => $item[$asset_tag][$batch_counter]['asset_id'],
|
||||
'item_type' => Asset::class,
|
||||
'created_by' => auth()->id(),
|
||||
'user_id' => auth()->id(),
|
||||
'note' => 'Checkin imported by '.auth()->user()->present()->fullName().' from history importer',
|
||||
'target_id' => null,
|
||||
'created_at' => $checkin_date,
|
||||
@@ -874,7 +824,7 @@ class AssetsController extends Controller
|
||||
{
|
||||
$this->authorize('checkin', Asset::class);
|
||||
|
||||
return view('hardware/quickscan-checkin')->with('statusLabel_list', Helper::statusLabelList());
|
||||
return view('hardware/quickscan-checkin');
|
||||
}
|
||||
|
||||
public function audit($id)
|
||||
|
||||
@@ -10,7 +10,6 @@ use App\Models\AssetModel;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\Setting;
|
||||
use App\View\Label;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -52,10 +51,6 @@ class BulkAssetsController extends Controller
|
||||
}
|
||||
|
||||
$asset_ids = $request->input('ids');
|
||||
if ($request->input('bulk_actions') === 'checkout') {
|
||||
$request->session()->flashInput(['selected_assets' => $asset_ids]);
|
||||
return redirect()->route('hardware.bulkcheckout.show');
|
||||
}
|
||||
|
||||
// Figure out where we need to send the user after the update is complete, and store that in the session
|
||||
$bulk_back_url = request()->headers->get('referer');
|
||||
@@ -97,9 +92,7 @@ class BulkAssetsController extends Controller
|
||||
// This handles all of the pivot sorting below (versus the assets.* fields in the allowed_columns array)
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.id';
|
||||
|
||||
$assets = Asset::with('assignedTo', 'location', 'model')
|
||||
->whereIn('assets.id', $asset_ids)
|
||||
->withTrashed();
|
||||
$assets = Asset::with('assignedTo', 'location', 'model')->whereIn('assets.id', $asset_ids);
|
||||
|
||||
$assets = $assets->get();
|
||||
|
||||
@@ -232,8 +225,7 @@ class BulkAssetsController extends Controller
|
||||
* its checkout status.
|
||||
*/
|
||||
|
||||
if (($request->filled('name'))
|
||||
|| ($request->filled('purchase_date'))
|
||||
if (($request->filled('purchase_date'))
|
||||
|| ($request->filled('expected_checkin'))
|
||||
|| ($request->filled('purchase_cost'))
|
||||
|| ($request->filled('supplier_id'))
|
||||
@@ -245,7 +237,6 @@ class BulkAssetsController extends Controller
|
||||
|| ($request->filled('status_id'))
|
||||
|| ($request->filled('model_id'))
|
||||
|| ($request->filled('next_audit_date'))
|
||||
|| ($request->filled('null_name'))
|
||||
|| ($request->filled('null_purchase_date'))
|
||||
|| ($request->filled('null_expected_checkin_date'))
|
||||
|| ($request->filled('null_next_audit_date'))
|
||||
@@ -258,14 +249,13 @@ class BulkAssetsController extends Controller
|
||||
$this->update_array = [];
|
||||
|
||||
/**
|
||||
* Leave out model_id and status here because we do math on that later. We have to do some
|
||||
* extra validation and checks on those two.
|
||||
* Leave out model_id and status here because we do math on that later. We have to do some extra
|
||||
* validation and checks on those two.
|
||||
*
|
||||
* It's tempting to make these match the request check above, but some of these values require
|
||||
* extra work to make sure the data makes sense.
|
||||
*/
|
||||
$this->conditionallyAddItem('name')
|
||||
->conditionallyAddItem('purchase_date')
|
||||
$this->conditionallyAddItem('purchase_date')
|
||||
->conditionallyAddItem('expected_checkin')
|
||||
->conditionallyAddItem('order_number')
|
||||
->conditionallyAddItem('requestable')
|
||||
@@ -276,36 +266,11 @@ class BulkAssetsController extends Controller
|
||||
$this->conditionallyAddItem($custom_field_column);
|
||||
}
|
||||
|
||||
if (!($asset->eol_explicit)) {
|
||||
if ($request->filled('model_id')) {
|
||||
$model = AssetModel::find($request->input('model_id'));
|
||||
if ($model->eol > 0) {
|
||||
if ($request->filled('purchase_date')) {
|
||||
$this->update_array['asset_eol_date'] = Carbon::parse($request->input('purchase_date'))->addMonths($model->eol)->format('Y-m-d');
|
||||
} else {
|
||||
$this->update_array['asset_eol_date'] = Carbon::parse($asset->purchase_date)->addMonths($model->eol)->format('Y-m-d');
|
||||
}
|
||||
} else {
|
||||
$this->update_array['asset_eol_date'] = null;
|
||||
}
|
||||
} elseif (($request->filled('purchase_date')) && ($asset->model->eol > 0)) {
|
||||
$this->update_array['asset_eol_date'] = Carbon::parse($request->input('purchase_date'))->addMonths($asset->model->eol)->format('Y-m-d');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Blank out fields that were requested to be blanked out via checkbox
|
||||
*/
|
||||
if ($request->input('null_name')=='1') {
|
||||
|
||||
$this->update_array['name'] = null;
|
||||
}
|
||||
|
||||
if ($request->input('null_purchase_date')=='1') {
|
||||
$this->update_array['purchase_date'] = null;
|
||||
if (!($asset->eol_explicit)) {
|
||||
$this->update_array['asset_eol_date'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->input('null_expected_checkin_date')=='1') {
|
||||
@@ -518,7 +483,12 @@ class BulkAssetsController extends Controller
|
||||
if ($request->filled('ids')) {
|
||||
$assets = Asset::find($request->get('ids'));
|
||||
foreach ($assets as $asset) {
|
||||
$asset->delete();
|
||||
$update_array['deleted_at'] = date('Y-m-d H:i:s');
|
||||
$update_array['assigned_to'] = null;
|
||||
|
||||
DB::table('assets')
|
||||
->where('id', $asset->id)
|
||||
->update($update_array);
|
||||
} // endforeach
|
||||
|
||||
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.delete.success'));
|
||||
@@ -575,34 +545,31 @@ class BulkAssetsController extends Controller
|
||||
}
|
||||
|
||||
$errors = [];
|
||||
DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, &$errors, $asset_ids, $request) { //NOTE: $errors is passsed by reference!
|
||||
DB::transaction(function () use ($target, $admin, $checkout_at, $expected_checkin, $errors, $asset_ids, $request) {
|
||||
foreach ($asset_ids as $asset_id) {
|
||||
$asset = Asset::findOrFail($asset_id);
|
||||
$this->authorize('checkout', $asset);
|
||||
|
||||
$checkout_success = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null);
|
||||
$error = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null);
|
||||
|
||||
//TODO - I think this logic is duplicated in the checkOut method?
|
||||
if ($target->location_id != '') {
|
||||
$asset->location_id = $target->location_id;
|
||||
// TODO - I don't know why this is being saved without events
|
||||
$asset::withoutEvents(function () use ($asset) {
|
||||
$asset->save();
|
||||
});
|
||||
$asset->unsetEventDispatcher();
|
||||
$asset->save();
|
||||
}
|
||||
|
||||
if (!$checkout_success) {
|
||||
$errors = array_merge_recursive($errors, $asset->getErrors()->toArray());
|
||||
if ($error) {
|
||||
array_merge_recursive($errors, $asset->getErrors()->toArray());
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
if (! $errors) {
|
||||
// Redirect to the new asset page
|
||||
return redirect()->to('hardware')->with('success', trans_choice('admin/hardware/message.multi-checkout.success', $asset_ids));
|
||||
return redirect()->to('hardware')->with('success', trans('admin/hardware/message.checkout.success'));
|
||||
}
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('hardware.bulkcheckout.show')->withInput()->with('error', trans_choice('admin/hardware/message.multi-checkout.error', $asset_ids))->withErrors($errors);
|
||||
return redirect()->route('hardware.bulkcheckout.show')->with('error', trans('admin/hardware/message.checkout.error'))->withErrors($errors);
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return redirect()->route('hardware.bulkcheckout.show')->with('error', $e->getErrors());
|
||||
}
|
||||
|
||||
@@ -508,8 +508,8 @@ class LoginController extends Controller
|
||||
protected function validator(array $data)
|
||||
{
|
||||
return Validator::make($data, [
|
||||
'username' => 'required|not_array',
|
||||
'password' => 'required|not_array',
|
||||
'username' => 'required',
|
||||
'password' => 'required',
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
@@ -87,7 +87,7 @@ class ResetPasswordController extends Controller
|
||||
'password.not_in' => trans('validation.disallow_same_pwd_as_user_fields'),
|
||||
];
|
||||
|
||||
$request->validate($this->rules());
|
||||
$request->validate($this->rules(), $request->all(), $this->validationErrorMessages());
|
||||
|
||||
Log::debug('Checking if '.$request->input('username').' exists');
|
||||
// Check to see if the user even exists - we'll treat the response the same to prevent user sniffing
|
||||
|
||||
@@ -99,18 +99,12 @@ class SamlController extends Controller
|
||||
{
|
||||
$saml = $this->saml;
|
||||
$auth = $saml->getAuth();
|
||||
$saml_exception = false;
|
||||
try {
|
||||
$auth->processResponse();
|
||||
} catch (\Exception $e) {
|
||||
Log::warning("Exception caught in SAML login: " . $e->getMessage());
|
||||
$saml_exception = true;
|
||||
}
|
||||
$auth->processResponse();
|
||||
$errors = $auth->getErrors();
|
||||
|
||||
if (!empty($errors) || $saml_exception) {
|
||||
Log::warning('There was an error with SAML ACS: ' . implode(', ', $errors));
|
||||
Log::warning('Reason: ' . $auth->getLastErrorReason());
|
||||
if (! empty($errors)) {
|
||||
Log::error('There was an error with SAML ACS: '.implode(', ', $errors));
|
||||
Log::error('Reason: '.$auth->getLastErrorReason());
|
||||
|
||||
return redirect()->route('login')->with('error', trans('auth/message.signin.error'));
|
||||
}
|
||||
@@ -138,18 +132,12 @@ class SamlController extends Controller
|
||||
{
|
||||
$auth = $this->saml->getAuth();
|
||||
$retrieveParametersFromServer = $this->saml->getSetting('retrieveParametersFromServer', false);
|
||||
$saml_exception = false;
|
||||
try {
|
||||
$sloUrl = $auth->processSLO(true, null, $retrieveParametersFromServer, null, true);
|
||||
} catch (\Exception $e) {
|
||||
Log::warning("Exception caught in SAML single-logout: " . $e->getMessage());
|
||||
$saml_exception = true;
|
||||
}
|
||||
$sloUrl = $auth->processSLO(true, null, $retrieveParametersFromServer, null, true);
|
||||
$errors = $auth->getErrors();
|
||||
|
||||
if (!empty($errors) || $saml_exception) {
|
||||
Log::warning('There was an error with SAML SLS: ' . implode(', ', $errors));
|
||||
Log::warning('Reason: ' . $auth->getLastErrorReason());
|
||||
if (! empty($errors)) {
|
||||
Log::error('There was an error with SAML SLS: '.implode(', ', $errors));
|
||||
Log::error('Reason: '.$auth->getLastErrorReason());
|
||||
|
||||
return view('errors.403');
|
||||
}
|
||||
|
||||
@@ -69,7 +69,7 @@ class CategoriesController extends Controller
|
||||
$category->use_default_eula = $request->input('use_default_eula', '0');
|
||||
$category->require_acceptance = $request->input('require_acceptance', '0');
|
||||
$category->checkin_email = $request->input('checkin_email', '0');
|
||||
$category->created_by = auth()->id();
|
||||
$category->user_id = Auth::id();
|
||||
|
||||
$category = $request->handleImages($category);
|
||||
if ($category->save()) {
|
||||
|
||||
@@ -20,7 +20,7 @@ trait CheckInOutRequest
|
||||
return Location::findOrFail(request('assigned_location'));
|
||||
case 'asset':
|
||||
return Asset::findOrFail(request('assigned_asset'));
|
||||
default:
|
||||
case 'user':
|
||||
return User::findOrFail(request('assigned_user'));
|
||||
}
|
||||
|
||||
|
||||
@@ -60,7 +60,6 @@ final class CompaniesController extends Controller
|
||||
$company->phone = $request->input('phone');
|
||||
$company->fax = $request->input('fax');
|
||||
$company->email = $request->input('email');
|
||||
$company->created_by = auth()->id();
|
||||
|
||||
$company = $request->handleImages($company);
|
||||
|
||||
|
||||
@@ -4,7 +4,6 @@ namespace App\Http\Controllers\Components;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Events\ComponentCheckedIn;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Component;
|
||||
@@ -97,10 +96,12 @@ class ComponentCheckinController extends Controller
|
||||
$asset = Asset::find($component_assets->asset_id);
|
||||
|
||||
event(new CheckoutableCheckedIn($component, $asset, auth()->user(), $request->input('note'), Carbon::now()));
|
||||
if ($backto == 'asset'){
|
||||
return redirect()->route('hardware.show', $asset->id)->with('success',
|
||||
trans('admin/components/message.checkin.success'));
|
||||
}
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
return redirect()->to(Helper::getRedirectOption($request, $component->id, 'Components'))->with('success',
|
||||
return redirect()->route('components.index')->with('success',
|
||||
trans('admin/components/message.checkin.success'));
|
||||
}
|
||||
|
||||
|
||||
@@ -4,11 +4,9 @@ namespace App\Http\Controllers\Components;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Events\ComponentCheckedOut;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Component;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
@@ -95,18 +93,14 @@ class ComponentCheckoutController extends Controller
|
||||
->withInput();
|
||||
}
|
||||
|
||||
// Check if the asset exists
|
||||
// Check if the user exists
|
||||
$asset = Asset::find($request->input('asset_id'));
|
||||
|
||||
if ((Setting::getSettings()->full_multiple_companies_support) && $component->company_id !== $asset->company_id) {
|
||||
return redirect()->route('components.checkout.show', $componentId)->with('error', trans('general.error_user_company'));
|
||||
}
|
||||
|
||||
// Update the component data
|
||||
$component->asset_id = $request->input('asset_id');
|
||||
$component->assets()->attach($component->id, [
|
||||
'component_id' => $component->id,
|
||||
'created_by' => auth()->user()->id,
|
||||
'user_id' => auth()->user(),
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'assigned_qty' => $request->input('assigned_qty'),
|
||||
'asset_id' => $request->input('asset_id'),
|
||||
@@ -115,11 +109,6 @@ class ComponentCheckoutController extends Controller
|
||||
|
||||
event(new CheckoutableCheckedOut($component, $asset, auth()->user(), $request->input('note')));
|
||||
|
||||
$request->request->add(['checkout_to_type' => 'asset']);
|
||||
$request->request->add(['assigned_asset' => $asset->id]);
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
|
||||
|
||||
return redirect()->to(Helper::getRedirectOption($request, $component->id, 'Components'))->with('success', trans('admin/components/message.checkout.success'));
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -73,8 +73,6 @@ class ComponentsController extends Controller
|
||||
$component->name = $request->input('name');
|
||||
$component->category_id = $request->input('category_id');
|
||||
$component->supplier_id = $request->input('supplier_id');
|
||||
$component->manufacturer_id = $request->input('manufacturer_id');
|
||||
$component->model_number = $request->input('model_number');
|
||||
$component->location_id = $request->input('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$component->order_number = $request->input('order_number', null);
|
||||
@@ -83,15 +81,13 @@ class ComponentsController extends Controller
|
||||
$component->purchase_date = $request->input('purchase_date', null);
|
||||
$component->purchase_cost = $request->input('purchase_cost', null);
|
||||
$component->qty = $request->input('qty');
|
||||
$component->created_by = auth()->id();
|
||||
$component->user_id = Auth::id();
|
||||
$component->notes = $request->input('notes');
|
||||
|
||||
$component = $request->handleImages($component);
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($component->save()) {
|
||||
return redirect()->to(Helper::getRedirectOption($request, $component->id, 'Components'))->with('success', trans('admin/components/message.create.success'));
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.create.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($component->getErrors());
|
||||
@@ -152,8 +148,6 @@ class ComponentsController extends Controller
|
||||
$component->name = $request->input('name');
|
||||
$component->category_id = $request->input('category_id');
|
||||
$component->supplier_id = $request->input('supplier_id');
|
||||
$component->manufacturer_id = $request->input('manufacturer_id');
|
||||
$component->model_number = $request->input('model_number');
|
||||
$component->location_id = $request->input('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$component->order_number = $request->input('order_number');
|
||||
@@ -166,10 +160,8 @@ class ComponentsController extends Controller
|
||||
|
||||
$component = $request->handleImages($component);
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($component->save()) {
|
||||
return redirect()->to(Helper::getRedirectOption($request, $component->id, 'Components'))->with('success', trans('admin/components/message.update.success'));
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.update.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($component->getErrors());
|
||||
|
||||
@@ -112,25 +112,40 @@ class ComponentsFilesController extends Controller
|
||||
public function show($componentId = null, $fileId = null)
|
||||
{
|
||||
Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||
|
||||
$component = Component::find($componentId);
|
||||
|
||||
// the component is valid
|
||||
if ($component = Component::find($componentId)) {
|
||||
if (isset($component->id)) {
|
||||
$this->authorize('view', $component);
|
||||
$this->authorize('components.files', $component);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $component->id)->find($fileId)) {
|
||||
|
||||
$file = 'private_uploads/components/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('components.show', ['component' => $component])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $component->id)->find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
return redirect()->route('components.show', ['component' => $component])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
$file = 'private_uploads/components/'.$log->filename;
|
||||
|
||||
if (Storage::missing($file)) {
|
||||
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||
Log::debug('URL should be '.Storage::url($file));
|
||||
|
||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Http\Controllers\Consumables;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
@@ -34,7 +33,7 @@ class ConsumableCheckoutController extends Controller
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0){
|
||||
return redirect()->route('consumables.index')
|
||||
->with('error', trans('admin/consumables/message.checkout.unavailable', ['requested' => 1, 'remaining' => $consumable->numRemaining()]));
|
||||
->with('error', trans('admin/consumables/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
// Return the checkout view
|
||||
@@ -70,14 +69,14 @@ class ConsumableCheckoutController extends Controller
|
||||
$this->authorize('checkout', $consumable);
|
||||
|
||||
// If the quantity is not present in the request or is not a positive integer, set it to 1
|
||||
$quantity = $request->input('checkout_qty');
|
||||
$quantity = $request->input('qty');
|
||||
if (!isset($quantity) || !ctype_digit((string)$quantity) || $quantity <= 0) {
|
||||
$quantity = 1;
|
||||
}
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0 || $quantity > $consumable->numRemaining()) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable', ['requested' => $quantity, 'remaining' => $consumable->numRemaining() ]));
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
$admin_user = auth()->user();
|
||||
@@ -92,25 +91,17 @@ class ConsumableCheckoutController extends Controller
|
||||
// Update the consumable data
|
||||
$consumable->assigned_to = e($request->input('assigned_to'));
|
||||
|
||||
for ($i = 0; $i < $quantity; $i++){
|
||||
for($i = 0; $i < $quantity; $i++){
|
||||
$consumable->users()->attach($consumable->id, [
|
||||
'consumable_id' => $consumable->id,
|
||||
'created_by' => $admin_user->id,
|
||||
'user_id' => $admin_user->id,
|
||||
'assigned_to' => e($request->input('assigned_to')),
|
||||
'note' => $request->input('note'),
|
||||
]);
|
||||
}
|
||||
|
||||
$consumable->checkout_qty = $quantity;
|
||||
event(new CheckoutableCheckedOut($consumable, $user, auth()->user(), $request->input('note')));
|
||||
|
||||
$request->request->add(['checkout_to_type' => 'user']);
|
||||
$request->request->add(['assigned_user' => $user->id]);
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => $request->get('checkout_to_type')]);
|
||||
|
||||
|
||||
// Redirect to the new consumable page
|
||||
return redirect()->to(Helper::getRedirectOption($request, $consumable->id, 'Consumables'))->with('success', trans('admin/consumables/message.checkout.success'));
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.checkout.success'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -81,16 +81,14 @@ class ConsumablesController extends Controller
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = $request->input('purchase_cost');
|
||||
$consumable->qty = $request->input('qty');
|
||||
$consumable->created_by = auth()->id();
|
||||
$consumable->user_id = Auth::id();
|
||||
$consumable->notes = $request->input('notes');
|
||||
|
||||
|
||||
$consumable = $request->handleImages($consumable);
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($consumable->save()) {
|
||||
return redirect()->to(Helper::getRedirectOption($request, $consumable->id, 'Consumables'))->with('success', trans('admin/consumables/message.create.success'));
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.create.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($consumable->getErrors());
|
||||
@@ -162,10 +160,8 @@ class ConsumablesController extends Controller
|
||||
|
||||
$consumable = $request->handleImages($consumable);
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($consumable->save()) {
|
||||
return redirect()->to(Helper::getRedirectOption($request, $consumable->id, 'Consumables'))->with('success', trans('admin/consumables/message.update.success'));
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.update.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($consumable->getErrors());
|
||||
@@ -204,7 +200,7 @@ class ConsumablesController extends Controller
|
||||
*/
|
||||
public function show($consumableId = null)
|
||||
{
|
||||
$consumable = Consumable::withCount('users as users_consumables')->find($consumableId);
|
||||
$consumable = Consumable::find($consumableId);
|
||||
$this->authorize($consumable);
|
||||
if (isset($consumable->id)) {
|
||||
return view('consumables/view', compact('consumable'));
|
||||
@@ -213,16 +209,4 @@ class ConsumablesController extends Controller
|
||||
return redirect()->route('consumables.index')
|
||||
->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
}
|
||||
|
||||
public function clone(Consumable $consumable) : View
|
||||
{
|
||||
$this->authorize('create', $consumable);
|
||||
$consumable_to_close = $consumable;
|
||||
$consumable = clone $consumable_to_close;
|
||||
$consumable->id = null;
|
||||
$consumable->image = null;
|
||||
$consumable->created_by = null;
|
||||
|
||||
return view('consumables/edit')->with('item', $consumable);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -104,6 +104,7 @@ class ConsumablesFilesController extends Controller
|
||||
* @since [v1.4]
|
||||
* @param int $consumableId
|
||||
* @param int $fileId
|
||||
* @return \Symfony\Consumable\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($consumableId = null, $fileId = null)
|
||||
@@ -115,18 +116,36 @@ class ConsumablesFilesController extends Controller
|
||||
$this->authorize('view', $consumable);
|
||||
$this->authorize('consumables.files', $consumable);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $consumable->id)->find($fileId)) {
|
||||
$file = 'private_uploads/consumables/'.$log->filename;
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $consumable->id)->find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('consumables.show', ['consumable' => $consumable])->with('error', trans('general.file_not_found'));
|
||||
$file = 'private_uploads/consumables/'.$log->filename;
|
||||
|
||||
if (Storage::missing($file)) {
|
||||
Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||
Log::debug('URL should be '.Storage::url($file));
|
||||
|
||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
|
||||
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
|
||||
// won't work, as they're not accessible via the web
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
}
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('consumables.show', ['consumable' => $consumable])->with('error', trans('general.log_record_not_found'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
|
||||
@@ -104,7 +104,7 @@ 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),
|
||||
"user_id" => auth()->id()
|
||||
"user_id" => Auth::id()
|
||||
]);
|
||||
|
||||
|
||||
@@ -248,7 +248,7 @@ class CustomFieldsController extends Controller
|
||||
$field->name = trim(e($request->get("name")));
|
||||
$field->element = e($request->get("element"));
|
||||
$field->field_values = $request->get("field_values");
|
||||
$field->created_by = auth()->id();
|
||||
$field->user_id = Auth::id();
|
||||
$field->help_text = $request->get("help_text");
|
||||
$field->show_in_email = $show_in_email;
|
||||
$field->is_unique = $request->get("is_unique", 0);
|
||||
|
||||
@@ -90,7 +90,7 @@ class CustomFieldsetsController extends Controller
|
||||
|
||||
$fieldset = new CustomFieldset([
|
||||
'name' => $request->get('name'),
|
||||
'created_by' => auth()->id(),
|
||||
'user_id' => auth()->id(),
|
||||
]);
|
||||
|
||||
$validator = Validator::make($request->all(), $fieldset->rules);
|
||||
@@ -211,7 +211,7 @@ class CustomFieldsetsController extends Controller
|
||||
return redirect()->route('fieldsets.show', [$id])->with('success', trans('admin/custom_fields/message.field.create.assoc_success'));
|
||||
}
|
||||
|
||||
return redirect()->route('fieldsets.show', [$id])->with('error', trans('admin/custom_fields/message.field.none_selected'));
|
||||
return redirect()->route('fieldsets.show', [$id])->with('error', 'No field selected.');
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,7 +5,6 @@ namespace App\Http\Controllers;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
|
||||
|
||||
/**
|
||||
@@ -45,8 +44,6 @@ class DashboardController extends Controller
|
||||
|
||||
return view('dashboard')->with('asset_stats', $asset_stats)->with('counts', $counts);
|
||||
} else {
|
||||
Session::reflash();
|
||||
|
||||
// Redirect to the profile page
|
||||
return redirect()->intended('account/view-assets');
|
||||
}
|
||||
|
||||
@@ -51,7 +51,7 @@ class DepartmentsController extends Controller
|
||||
$this->authorize('create', Department::class);
|
||||
$department = new Department;
|
||||
$department->fill($request->all());
|
||||
$department->created_by = auth()->id();
|
||||
$department->user_id = auth()->id();
|
||||
$department->manager_id = ($request->filled('manager_id') ? $request->input('manager_id') : null);
|
||||
$department->location_id = ($request->filled('location_id') ? $request->input('location_id') : null);
|
||||
$department->company_id = ($request->filled('company_id') ? $request->input('company_id') : null);
|
||||
|
||||
@@ -61,21 +61,7 @@ class DepreciationsController extends Controller
|
||||
// Depreciation data
|
||||
$depreciation->name = $request->input('name');
|
||||
$depreciation->months = $request->input('months');
|
||||
$depreciation->created_by = auth()->id();
|
||||
|
||||
$request->validate([
|
||||
'depreciation_min' => [
|
||||
'required',
|
||||
'numeric',
|
||||
function ($attribute, $value, $fail) use ($request) {
|
||||
if ($request->input('depreciation_type') == 'percent' && ($value < 0 || $value > 100)) {
|
||||
$fail(trans('validation.percent'));
|
||||
}
|
||||
},
|
||||
],
|
||||
'depreciation_type' => 'required|in:amount,percent',
|
||||
]);
|
||||
$depreciation->depreciation_type = $request->input('depreciation_type');
|
||||
$depreciation->user_id = Auth::id();
|
||||
$depreciation->depreciation_min = $request->input('depreciation_min');
|
||||
|
||||
// Was the asset created?
|
||||
@@ -130,20 +116,6 @@ class DepreciationsController extends Controller
|
||||
// Depreciation data
|
||||
$depreciation->name = $request->input('name');
|
||||
$depreciation->months = $request->input('months');
|
||||
|
||||
$request->validate([
|
||||
'depreciation_min' => [
|
||||
'required',
|
||||
'numeric',
|
||||
function ($attribute, $value, $fail) use ($request) {
|
||||
if ($request->input('depreciation_type') == 'percent' && ($value < 0 || $value > 100)) {
|
||||
$fail(trans('validation.percent'));
|
||||
}
|
||||
},
|
||||
],
|
||||
'depreciation_type' => 'required|in:amount,percent',
|
||||
]);
|
||||
$depreciation->depreciation_type = $request->input('depreciation_type');
|
||||
$depreciation->depreciation_min = $request->input('depreciation_min');
|
||||
|
||||
// Was the asset created?
|
||||
@@ -193,20 +165,13 @@ class DepreciationsController extends Controller
|
||||
*/
|
||||
public function show($id) : View | RedirectResponse
|
||||
{
|
||||
$depreciation = Depreciation::withCount('assets as assets_count')
|
||||
->withCount('models as models_count')
|
||||
->withCount('licenses as licenses_count')
|
||||
->find($id);
|
||||
if (is_null($depreciation = Depreciation::find($id))) {
|
||||
// Redirect to the blogs management page
|
||||
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('view', $depreciation);
|
||||
|
||||
if ($depreciation) {
|
||||
return view('depreciations/view', compact('depreciation'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.does_not_exist'));
|
||||
|
||||
|
||||
return view('depreciations/view', compact('depreciation'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Routing\Controller as BaseController;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
|
||||
/**
|
||||
* This controller provide the health route for
|
||||
@@ -16,35 +15,13 @@ use Illuminate\Support\Facades\DB;
|
||||
*/
|
||||
class HealthController extends BaseController
|
||||
{
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('health');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a fixed JSON content ({ "status": "ok"}) which indicate the app is up and running
|
||||
*/
|
||||
public function get()
|
||||
{
|
||||
try {
|
||||
|
||||
if (DB::select('select 2 + 2')) {
|
||||
return response()->json([
|
||||
'status' => 'ok',
|
||||
]);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::error('Could not connect to database');
|
||||
return response()->json([
|
||||
'status' => 'database connection failed',
|
||||
], 500);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
return response()->json([
|
||||
'status' => 'ok',
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -62,10 +62,10 @@ class CheckoutKitController extends Controller
|
||||
|
||||
$checkout_result = $this->kitService->checkout($request, $kit, $user);
|
||||
if (Arr::has($checkout_result, 'errors') && count($checkout_result['errors']) > 0) {
|
||||
return redirect()->back()->with('error', trans('admin/kits/general.checkout_error'))->with('error_messages', $checkout_result['errors']);
|
||||
return redirect()->back()->with('error', trans('general.checkout_error'))->with('error_messages', $checkout_result['errors']);
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', trans('admin/kits/general.checkout_success'))
|
||||
return redirect()->back()->with('success', trans('general.checkout_success'))
|
||||
->with('assets', Arr::get($checkout_result, 'assets', null))
|
||||
->with('accessories', Arr::get($checkout_result, 'accessories', null))
|
||||
->with('consumables', Arr::get($checkout_result, 'consumables', null));
|
||||
|
||||
@@ -55,7 +55,6 @@ class PredefinedKitsController extends Controller
|
||||
// Create a new Predefined Kit
|
||||
$kit = new PredefinedKit;
|
||||
$kit->name = $request->input('name');
|
||||
$kit->created_by = auth()->id();
|
||||
|
||||
if (! $kit->save()) {
|
||||
return redirect()->back()->withInput()->withErrors($kit->getErrors());
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Http\Controllers\Licenses;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
@@ -101,15 +100,15 @@ class LicenseCheckinController extends Controller
|
||||
$licenseSeat->asset_id = null;
|
||||
$licenseSeat->notes = $request->input('notes');
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
|
||||
// Was the asset updated?
|
||||
if ($licenseSeat->save()) {
|
||||
event(new CheckoutableCheckedIn($licenseSeat, $return_to, auth()->user(), $request->input('notes')));
|
||||
|
||||
if ($backTo == 'user') {
|
||||
return redirect()->route('users.show', $return_to->id)->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
}
|
||||
|
||||
return redirect()->to(Helper::getRedirectOption($request, $license->id, 'Licenses'))->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
return redirect()->route('licenses.show', $licenseSeat->license_id)->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
}
|
||||
|
||||
// Redirect to the license page with error
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Http\Controllers\Licenses;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\LicenseCheckoutRequest;
|
||||
use App\Models\Accessory;
|
||||
@@ -77,32 +76,15 @@ class LicenseCheckoutController extends Controller
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
$licenseSeat = $this->findLicenseSeatToCheckout($license, $seatId);
|
||||
$licenseSeat->created_by = auth()->id();
|
||||
$licenseSeat->user_id = Auth::id();
|
||||
$licenseSeat->notes = $request->input('notes');
|
||||
|
||||
|
||||
$checkoutMethod = 'checkoutTo'.ucwords(request('checkout_to_type'));
|
||||
|
||||
if ($request->filled('asset_id')) {
|
||||
|
||||
$checkoutTarget = $this->checkoutToAsset($licenseSeat);
|
||||
$request->request->add(['assigned_asset' => $checkoutTarget->id]);
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => 'asset']);
|
||||
|
||||
} elseif ($request->filled('assigned_to')) {
|
||||
$checkoutTarget = $this->checkoutToUser($licenseSeat);
|
||||
$request->request->add(['assigned_user' => $checkoutTarget->id]);
|
||||
session()->put(['redirect_option' => $request->get('redirect_option'), 'checkout_to_type' => 'user']);
|
||||
if ($this->$checkoutMethod($licenseSeat)) {
|
||||
return redirect()->route('licenses.index')->with('success', trans('admin/licenses/message.checkout.success'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($checkoutTarget) {
|
||||
return redirect()->to(Helper::getRedirectOption($request, $license->id, 'Licenses'))->with('success', trans('admin/licenses/message.checkout.success'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('Something went wrong handling this checkout.'));
|
||||
}
|
||||
|
||||
@@ -112,14 +94,14 @@ class LicenseCheckoutController extends Controller
|
||||
|
||||
if (! $licenseSeat) {
|
||||
if ($seatId) {
|
||||
throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.unavailable')));
|
||||
throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', 'This Seat is not available for checkout.'));
|
||||
}
|
||||
|
||||
throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.not_enough_seats')));
|
||||
throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', 'There are no available seats for this license.'));
|
||||
}
|
||||
|
||||
if (! $licenseSeat->license->is($license)) {
|
||||
throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.mismatch')));
|
||||
throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', 'The license seat provided does not match the license.'));
|
||||
}
|
||||
|
||||
return $licenseSeat;
|
||||
@@ -138,7 +120,8 @@ class LicenseCheckoutController extends Controller
|
||||
}
|
||||
if ($licenseSeat->save()) {
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, auth()->user(), request('notes')));
|
||||
return $target;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
@@ -154,7 +137,8 @@ class LicenseCheckoutController extends Controller
|
||||
|
||||
if ($licenseSeat->save()) {
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, auth()->user(), request('notes')));
|
||||
return $target;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -112,19 +112,37 @@ class LicenseFilesController extends Controller
|
||||
$this->authorize('view', $license);
|
||||
$this->authorize('licenses.files', $license);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $license->id)->find($fileId)) {
|
||||
$file = 'private_uploads/licenses/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('licenses.show', ['licenses' => $license])->with('error', trans('general.file_not_found'));
|
||||
}
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $license->id)->find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
// The log record doesn't exist somehow
|
||||
return redirect()->route('licenses.show', ['licenses' => $license])->with('error', trans('general.log_record_not_found'));
|
||||
$file = 'private_uploads/licenses/'.$log->filename;
|
||||
|
||||
if (Storage::missing($file)) {
|
||||
Log::debug('NOT EXISTS for '.$file);
|
||||
Log::debug('NOT EXISTS URL should be '.Storage::url($file));
|
||||
|
||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
|
||||
// won't work, as they're not accessible via the web
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
|
||||
|
||||
@@ -99,13 +99,11 @@ class LicensesController extends Controller
|
||||
$license->supplier_id = $request->input('supplier_id');
|
||||
$license->category_id = $request->input('category_id');
|
||||
$license->termination_date = $request->input('termination_date');
|
||||
$license->created_by = auth()->id();
|
||||
$license->user_id = Auth::id();
|
||||
$license->min_amt = $request->input('min_amt');
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($license->save()) {
|
||||
return redirect()->to(Helper::getRedirectOption($request, $license->id, 'Licenses'))->with('success', trans('admin/licenses/message.create.success'));
|
||||
return redirect()->route('licenses.index')->with('success', trans('admin/licenses/message.create.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($license->getErrors());
|
||||
@@ -182,10 +180,8 @@ class LicensesController extends Controller
|
||||
$license->category_id = $request->input('category_id');
|
||||
$license->min_amt = $request->input('min_amt');
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($license->save()) {
|
||||
return redirect()->to(Helper::getRedirectOption($request, $license->id, 'Licenses'))->with('success', trans('admin/licenses/message.update.success'));
|
||||
return redirect()->route('licenses.show', ['license' => $licenseId])->with('success', trans('admin/licenses/message.update.success'));
|
||||
}
|
||||
// If we can't adjust the number of seats, the error is flashed to the session by the event handler in License.php
|
||||
return redirect()->back()->withInput()->withErrors($license->getErrors());
|
||||
|
||||
@@ -3,7 +3,6 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Location;
|
||||
use App\Models\User;
|
||||
@@ -75,7 +74,7 @@ class LocationsController extends Controller
|
||||
$location->zip = $request->input('zip');
|
||||
$location->ldap_ou = $request->input('ldap_ou');
|
||||
$location->manager_id = $request->input('manager_id');
|
||||
$location->created_by = auth()->id();
|
||||
$location->user_id = auth()->id();
|
||||
$location->phone = request('phone');
|
||||
$location->fax = request('fax');
|
||||
|
||||
@@ -194,13 +193,7 @@ class LocationsController extends Controller
|
||||
*/
|
||||
public function show($id = null) : View | RedirectResponse
|
||||
{
|
||||
$location = Location::withCount('assignedAssets as assigned_assets_count')
|
||||
->withCount('assets as assets_count')
|
||||
->withCount('rtd_assets as rtd_assets_count')
|
||||
->withCount('children as children_count')
|
||||
->withCount('users as users_count')
|
||||
->withTrashed()
|
||||
->find($id);
|
||||
$location = Location::find($id);
|
||||
|
||||
if (isset($location->id)) {
|
||||
return view('locations/view', compact('location'));
|
||||
@@ -256,41 +249,6 @@ class LocationsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Restore a given Asset Model (mark as un-deleted)
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $id
|
||||
*/
|
||||
public function postRestore($id) : RedirectResponse
|
||||
{
|
||||
$this->authorize('create', Location::class);
|
||||
|
||||
if ($location = Location::withTrashed()->find($id)) {
|
||||
|
||||
if ($location->deleted_at == '') {
|
||||
return redirect()->back()->with('error', trans('general.not_deleted', ['item_type' => trans('general.location')]));
|
||||
}
|
||||
|
||||
if ($location->restore()) {
|
||||
$logaction = new Actionlog();
|
||||
$logaction->item_type = Location::class;
|
||||
$logaction->item_id = $location->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
return redirect()->route('locations.index')->with('success', trans('admin/locations/message.restore.success'));
|
||||
}
|
||||
|
||||
// Check validation
|
||||
return redirect()->back()->with('error', trans('general.could_not_restore', ['item_type' => trans('general.location'), 'error' => $location->getErrors()->first()]));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', trans('admin/models/message.does_not_exist'));
|
||||
|
||||
}
|
||||
public function print_all_assigned($id) : View | RedirectResponse
|
||||
{
|
||||
if ($location = Location::where('id', $id)->first()) {
|
||||
|
||||
@@ -61,7 +61,7 @@ class ManufacturersController extends Controller
|
||||
$this->authorize('create', Manufacturer::class);
|
||||
$manufacturer = new Manufacturer;
|
||||
$manufacturer->name = $request->input('name');
|
||||
$manufacturer->created_by = auth()->id();
|
||||
$manufacturer->user_id = Auth::id();
|
||||
$manufacturer->url = $request->input('url');
|
||||
$manufacturer->support_url = $request->input('support_url');
|
||||
$manufacturer->warranty_lookup_url = $request->input('warranty_lookup_url');
|
||||
@@ -219,7 +219,7 @@ class ManufacturersController extends Controller
|
||||
$logaction->item_type = Manufacturer::class;
|
||||
$logaction->item_id = $manufacturer->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->user_id = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
// Redirect them to the deleted page if there are more, otherwise the section index
|
||||
|
||||
@@ -40,7 +40,7 @@ class ModalController extends Controller
|
||||
$view = view("modals.${type}");
|
||||
|
||||
if ($type == "statuslabel") {
|
||||
$view->with('status_types', Helper::statusTypeList());
|
||||
$view->with('statuslabel_types', Helper::statusTypeList());
|
||||
}
|
||||
if (in_array($type, ['kit-model', 'kit-license', 'kit-consumable', 'kit-accessory'])) {
|
||||
$view->with('kitId', $itemId);
|
||||
|
||||
@@ -49,8 +49,6 @@ class ProfileController extends Controller
|
||||
$user->gravatar = $request->input('gravatar');
|
||||
$user->skin = $request->input('skin');
|
||||
$user->phone = $request->input('phone');
|
||||
$user->enable_sounds = $request->input('enable_sounds', false);
|
||||
$user->enable_confetti = $request->input('enable_confetti', false);
|
||||
|
||||
if (! config('app.lock_passwords')) {
|
||||
$user->locale = $request->input('locale', 'en-US');
|
||||
@@ -194,14 +192,14 @@ class ProfileController extends Controller
|
||||
*/
|
||||
public function printInventory() : View
|
||||
{
|
||||
$show_users = User::where('id',auth()->user()->id)->get();
|
||||
$show_user = auth()->user();
|
||||
|
||||
return view('users/print')
|
||||
->with('assets', auth()->user()->assets())
|
||||
->with('licenses', auth()->user()->licenses()->get())
|
||||
->with('accessories', auth()->user()->accessories()->get())
|
||||
->with('consumables', auth()->user()->consumables()->get())
|
||||
->with('users', $show_users)
|
||||
->with('assets', auth()->user()->assets)
|
||||
->with('licenses', $show_user->licenses()->get())
|
||||
->with('accessories', $show_user->accessories()->get())
|
||||
->with('consumables', $show_user->consumables()->get())
|
||||
->with('show_user', $show_user)
|
||||
->with('settings', Setting::getSettings());
|
||||
}
|
||||
|
||||
@@ -222,12 +220,7 @@ class ProfileController extends Controller
|
||||
return redirect()->back()->with('error', trans('admin/users/message.user_has_no_email'));
|
||||
}
|
||||
|
||||
try {
|
||||
$user->notify((new CurrentInventory($user)));
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
|
||||
$user->notify((new CurrentInventory($user)));
|
||||
return redirect()->back()->with('success', trans('admin/users/general.user_notified'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -703,10 +703,6 @@ class ReportsController extends Controller
|
||||
$assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]);
|
||||
}
|
||||
|
||||
if (($request->filled('asset_eol_date_start')) && ($request->filled('asset_eol_date_end'))) {
|
||||
$assets->whereBetween('assets.asset_eol_date', [$request->input('asset_eol_date_start'), $request->input('asset_eol_date_end')]);
|
||||
}
|
||||
|
||||
if (($request->filled('last_audit_start')) && ($request->filled('last_audit_end'))) {
|
||||
$last_audit_start = Carbon::parse($request->input('last_audit_start'))->startOfDay();
|
||||
$last_audit_end = Carbon::parse($request->input('last_audit_end'))->endOfDay();
|
||||
@@ -782,7 +778,7 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('eol')) {
|
||||
$row[] = ($asset->purchase_date != '') ? $asset->asset_eol_date : '';
|
||||
$row[] = ($asset->asset_eol_date) ? $asset->asset_eol_date : '';
|
||||
}
|
||||
|
||||
if ($request->filled('order')) {
|
||||
|
||||
@@ -7,11 +7,6 @@ use App\Helpers\StorageHelper;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Requests\SettingsSamlRequest;
|
||||
use App\Http\Requests\SetupUserRequest;
|
||||
use App\Http\Requests\StoreLdapSettings;
|
||||
use App\Http\Requests\StoreLocalizationSettings;
|
||||
use App\Http\Requests\StoreNotificationSettings;
|
||||
use App\Http\Requests\StoreLabelSettings;
|
||||
use App\Http\Requests\StoreSecuritySettings;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Group;
|
||||
use App\Models\Setting;
|
||||
@@ -19,6 +14,7 @@ use App\Models\Asset;
|
||||
use App\Models\User;
|
||||
use App\Notifications\FirstAdminNotification;
|
||||
use App\Notifications\MailTest;
|
||||
use Illuminate\Http\Client\HttpClientException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -133,11 +129,11 @@ class SettingsController extends Controller
|
||||
protected function dotEnvFileIsExposed() : bool
|
||||
{
|
||||
try {
|
||||
return Http::withoutVerifying()->timeout(10)
|
||||
return Http::timeout(10)
|
||||
->accept('*/*')
|
||||
->get(URL::to('.env'))
|
||||
->successful();
|
||||
} catch (\Exception $e) {
|
||||
} catch (HttpClientException $e) {
|
||||
Log::debug($e->getMessage());
|
||||
return true;
|
||||
}
|
||||
@@ -186,7 +182,7 @@ class SettingsController extends Controller
|
||||
$settings->brand = 1;
|
||||
$settings->locale = $request->input('locale', 'en-US');
|
||||
$settings->default_currency = $request->input('default_currency', 'USD');
|
||||
$settings->created_by = 1;
|
||||
$settings->user_id = 1;
|
||||
$settings->email_domain = $request->input('email_domain');
|
||||
$settings->email_format = $request->input('email_format');
|
||||
$settings->next_auto_tag_base = 1;
|
||||
@@ -278,6 +274,20 @@ class SettingsController extends Controller
|
||||
return view('settings/index', compact('settings'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the admin settings page.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function getEdit() : View
|
||||
|
||||
{
|
||||
$setting = Setting::getSettings();
|
||||
|
||||
return view('settings/general', compact('setting'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a form to allow a super admin to update settings.
|
||||
@@ -315,7 +325,6 @@ class SettingsController extends Controller
|
||||
|
||||
$setting->full_multiple_companies_support = $request->input('full_multiple_companies_support', '0');
|
||||
$setting->unique_serial = $request->input('unique_serial', '0');
|
||||
$setting->shortcuts_enabled = $request->input('shortcuts_enabled', '0');
|
||||
$setting->show_images_in_email = $request->input('show_images_in_email', '0');
|
||||
$setting->show_archived_in_list = $request->input('show_archived_in_list', '0');
|
||||
$setting->dashboard_message = $request->input('dashboard_message');
|
||||
@@ -405,7 +414,10 @@ class SettingsController extends Controller
|
||||
$setting = $request->handleImages($setting, 600, 'logo', '', 'logo');
|
||||
|
||||
if ($request->input('clear_logo') == '1') {
|
||||
$setting = $request->deleteExistingImage($setting, '', 'logo');
|
||||
|
||||
if (($setting->logo) && (Storage::exists($setting->logo))) {
|
||||
Storage::disk('public')->delete($setting->logo);
|
||||
}
|
||||
$setting->logo = null;
|
||||
$setting->brand = 1;
|
||||
}
|
||||
@@ -413,38 +425,43 @@ class SettingsController extends Controller
|
||||
// Email logo upload
|
||||
$setting = $request->handleImages($setting, 600, 'email_logo', '', 'email_logo');
|
||||
if ($request->input('clear_email_logo') == '1') {
|
||||
$setting = $request->deleteExistingImage($setting, '', 'email_logo');
|
||||
|
||||
if (($setting->email_logo) && (Storage::exists($setting->email_logo))) {
|
||||
Storage::disk('public')->delete($setting->email_logo);
|
||||
}
|
||||
$setting->email_logo = null;
|
||||
// If they are uploading an image, validate it and upload it
|
||||
}
|
||||
|
||||
// Label logo upload
|
||||
$setting = $request->handleImages($setting, 600, 'label_logo', '', 'label_logo');
|
||||
|
||||
if ($request->input('clear_label_logo') == '1') {
|
||||
$setting = $request->deleteExistingImage($setting, '', 'label_logo');
|
||||
|
||||
if (($setting->label_logo) && (Storage::exists($setting->label_logo))) {
|
||||
Storage::disk('public')->delete($setting->label_logo);
|
||||
}
|
||||
$setting->label_logo = null;
|
||||
}
|
||||
|
||||
// Favicon upload
|
||||
$setting = $request->handleImages($setting, 100, 'favicon', '', 'favicon');
|
||||
if ('1' == $request->input('clear_favicon')) {
|
||||
$setting = $request->deleteExistingImage($setting, '', 'favicon');
|
||||
|
||||
if (($setting->favicon) && (Storage::exists($setting->favicon))) {
|
||||
Storage::disk('public')->delete($setting->favicon);
|
||||
}
|
||||
$setting->favicon = null;
|
||||
}
|
||||
|
||||
// Default avatar upload
|
||||
$setting = $request->handleImages($setting, 500, 'default_avatar', 'avatars', 'default_avatar');
|
||||
if ($request->input('clear_default_avatar') == '1') {
|
||||
// Don't delete the file, just update the field if this is the default
|
||||
if ($setting->default_avatar!='default.png') {
|
||||
$setting = $request->deleteExistingImage($setting, 'avatars', 'default_avatar');
|
||||
if ($request->input('clear_default_avatar') == '1') {
|
||||
|
||||
if (($setting->default_avatar) && (Storage::exists('avatars/'.$setting->default_avatar))) {
|
||||
Storage::disk('public')->delete('avatars/'.$setting->default_avatar);
|
||||
}
|
||||
$setting->default_avatar = null;
|
||||
}
|
||||
|
||||
if ($request->input('restore_default_avatar') == '1') {
|
||||
$setting->default_avatar = 'default.png';
|
||||
}
|
||||
}
|
||||
|
||||
if ($setting->save()) {
|
||||
@@ -477,7 +494,7 @@ class SettingsController extends Controller
|
||||
*
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function postSecurity(StoreSecuritySettings $request) : RedirectResponse
|
||||
public function postSecurity(Request $request) : RedirectResponse
|
||||
{
|
||||
$this->validate($request, [
|
||||
'pwd_secure_complexity' => 'array',
|
||||
@@ -547,7 +564,7 @@ class SettingsController extends Controller
|
||||
*
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function postLocalization(StoreLocalizationSettings $request) : RedirectResponse
|
||||
public function postLocalization(Request $request) : RedirectResponse
|
||||
{
|
||||
if (is_null($setting = Setting::getSettings())) {
|
||||
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
|
||||
@@ -590,7 +607,7 @@ class SettingsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function postAlerts(StoreNotificationSettings $request) : RedirectResponse
|
||||
public function postAlerts(Request $request) : RedirectResponse
|
||||
{
|
||||
if (is_null($setting = Setting::getSettings())) {
|
||||
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
|
||||
@@ -628,7 +645,6 @@ class SettingsController extends Controller
|
||||
$setting->alert_threshold = $request->input('alert_threshold');
|
||||
$setting->audit_interval = $request->input('audit_interval');
|
||||
$setting->audit_warning_days = $request->input('audit_warning_days');
|
||||
$setting->due_checkin_days = $request->input('due_checkin_days');
|
||||
$setting->show_alerts_in_menu = $request->input('show_alerts_in_menu', '0');
|
||||
|
||||
if ($setting->save()) {
|
||||
@@ -771,7 +787,7 @@ class SettingsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
*/
|
||||
public function postLabels(StoreLabelSettings $request) : RedirectResponse
|
||||
public function postLabels(Request $request) : RedirectResponse
|
||||
{
|
||||
if (is_null($setting = Setting::getSettings())) {
|
||||
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
|
||||
@@ -850,7 +866,26 @@ class SettingsController extends Controller
|
||||
{
|
||||
$setting = Setting::getSettings();
|
||||
$groups = Group::pluck('name', 'id');
|
||||
return view('settings.ldap', compact('setting', 'groups'));
|
||||
|
||||
|
||||
/**
|
||||
* This validator is only temporary (famous last words.) - @snipe
|
||||
*/
|
||||
$messages = [
|
||||
'ldap_username_field.not_in' => '<code>sAMAccountName</code> (mixed case) will likely not work. You should use <code>samaccountname</code> (lowercase) instead. ',
|
||||
'ldap_auth_filter_query.not_in' => '<code>uid=samaccountname</code> is probably not a valid auth filter. You probably want <code>uid=</code> ',
|
||||
'ldap_filter.regex' => 'This value should probably not be wrapped in parentheses.',
|
||||
];
|
||||
|
||||
$validator = Validator::make($setting->toArray(), [
|
||||
'ldap_username_field' => 'not_in:sAMAccountName',
|
||||
'ldap_auth_filter_query' => 'not_in:uid=samaccountname|required_if:ldap_enabled,1',
|
||||
'ldap_filter' => 'nullable|regex:"^[^(]"|required_if:ldap_enabled,1',
|
||||
], $messages);
|
||||
|
||||
|
||||
|
||||
return view('settings.ldap', compact('setting', 'groups'))->withErrors($validator);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -859,7 +894,7 @@ class SettingsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
*/
|
||||
public function postLdapSettings(StoreLdapSettings $request) : RedirectResponse
|
||||
public function postLdapSettings(Request $request) : RedirectResponse
|
||||
{
|
||||
if (is_null($setting = Setting::getSettings())) {
|
||||
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
|
||||
@@ -1176,7 +1211,7 @@ class SettingsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v6.0]
|
||||
*/
|
||||
public function postRestore(Request $request, $filename = null): RedirectResponse
|
||||
public function postRestore($filename = null) : RedirectResponse
|
||||
{
|
||||
|
||||
if (! config('app.lock_passwords')) {
|
||||
@@ -1196,29 +1231,13 @@ class SettingsController extends Controller
|
||||
|
||||
Log::debug('Attempting to restore from: '. storage_path($path).'/'.$filename);
|
||||
|
||||
$restore_params = [
|
||||
'--force' => true,
|
||||
'--no-progress' => true,
|
||||
'filename' => storage_path($path) . '/' . $filename
|
||||
];
|
||||
|
||||
if ($request->input('clean')) {
|
||||
Log::debug("Attempting 'clean' - first, guessing prefix...");
|
||||
Artisan::call('snipeit:restore', [
|
||||
'--sanitize-guess-prefix' => true,
|
||||
'filename' => storage_path($path) . '/' . $filename
|
||||
]);
|
||||
$guess_prefix_output = Artisan::output();
|
||||
Log::debug("Sanitize output is: $guess_prefix_output");
|
||||
list($prefix, $_output) = explode("\n", $guess_prefix_output);
|
||||
Log::debug("prefix is: '$prefix'");
|
||||
$restore_params['--sanitize-with-prefix'] = $prefix;
|
||||
}
|
||||
|
||||
// run the restore command
|
||||
Artisan::call('snipeit:restore',
|
||||
$restore_params
|
||||
);
|
||||
[
|
||||
'--force' => true,
|
||||
'--no-progress' => true,
|
||||
'filename' => storage_path($path).'/'.$filename
|
||||
]);
|
||||
|
||||
// If it's greater than 300, it probably worked
|
||||
$output = Artisan::output();
|
||||
@@ -1245,7 +1264,7 @@ class SettingsController extends Controller
|
||||
DB::table('users')->update(['remember_token' => null]);
|
||||
Auth::logout();
|
||||
|
||||
return redirect()->route('login')->with('success', trans('admin/settings/message.restore.success'));
|
||||
return redirect()->route('login')->with('success', 'Your system has been restored. Please login again.');
|
||||
} else {
|
||||
return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found'));
|
||||
}
|
||||
|
||||
@@ -47,7 +47,7 @@ class StatuslabelsController extends Controller
|
||||
|
||||
return view('statuslabels/edit')
|
||||
->with('item', new Statuslabel)
|
||||
->with('status_types', Helper::statusTypeList());
|
||||
->with('statuslabel_types', Helper::statusTypeList());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -61,11 +61,19 @@ class StatuslabelsController extends Controller
|
||||
// create a new model instance
|
||||
$statusLabel = new Statuslabel();
|
||||
|
||||
if ($request->missing('statuslabel_types')) {
|
||||
return redirect()->back()->withInput()->withErrors(['statuslabel_types' => trans('validation.statuslabel_type')]);
|
||||
}
|
||||
|
||||
$statusType = Statuslabel::getStatuslabelTypesForDB($request->input('statuslabel_types'));
|
||||
|
||||
// Save the Statuslabel data
|
||||
$statusLabel->name = $request->input('name');
|
||||
$statusLabel->created_by = auth()->id();
|
||||
$statusLabel->user_id = Auth::id();
|
||||
$statusLabel->notes = $request->input('notes');
|
||||
$statusLabel->status_type = $request->input('status_type');
|
||||
$statusLabel->deployable = $statusType['deployable'];
|
||||
$statusLabel->pending = $statusType['pending'];
|
||||
$statusLabel->archived = $statusType['archived'];
|
||||
$statusLabel->color = $request->input('color');
|
||||
$statusLabel->show_in_nav = $request->input('show_in_nav', 0);
|
||||
$statusLabel->default_label = $request->input('default_label', 0);
|
||||
@@ -92,7 +100,11 @@ class StatuslabelsController extends Controller
|
||||
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist'));
|
||||
}
|
||||
|
||||
return view('statuslabels/edit', compact('item'))->with('status_types', Helper::statusTypeList());;
|
||||
$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);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -109,10 +121,17 @@ class StatuslabelsController extends Controller
|
||||
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')]);
|
||||
}
|
||||
|
||||
// Update the Statuslabel data
|
||||
$statustype = Statuslabel::getStatuslabelTypesForDB($request->input('statuslabel_types'));
|
||||
$statuslabel->name = $request->input('name');
|
||||
$statuslabel->notes = $request->input('notes');
|
||||
$statuslabel->status_type = $request->input('status_type');
|
||||
$statuslabel->deployable = $statustype['deployable'];
|
||||
$statuslabel->pending = $statustype['pending'];
|
||||
$statuslabel->archived = $statustype['archived'];
|
||||
$statuslabel->color = $request->input('color');
|
||||
$statuslabel->show_in_nav = $request->input('show_in_nav', 0);
|
||||
$statuslabel->default_label = $request->input('default_label', 0);
|
||||
|
||||
@@ -62,7 +62,7 @@ class SuppliersController extends Controller
|
||||
$supplier->email = request('email');
|
||||
$supplier->notes = request('notes');
|
||||
$supplier->url = $supplier->addhttp(request('url'));
|
||||
$supplier->created_by = auth()->id();
|
||||
$supplier->user_id = Auth::id();
|
||||
$supplier = $request->handleImages($supplier);
|
||||
|
||||
if ($supplier->save()) {
|
||||
|
||||
@@ -13,11 +13,9 @@ use App\Models\Group;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\ConsumableAssignment;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
@@ -31,12 +29,12 @@ class BulkUsersController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.7]
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\View | \Illuminate\Http\RedirectResponse
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit(Request $request)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
// Make sure there were users selected
|
||||
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
|
||||
@@ -48,18 +46,16 @@ class BulkUsersController extends Controller
|
||||
|
||||
// bulk edit, display the bulk edit form
|
||||
if ($request->input('bulk_actions') == 'edit') {
|
||||
$this->authorize('update', User::class);
|
||||
return view('users/bulk-edit', compact('users'))
|
||||
->with('groups', Group::pluck('name', 'id'));
|
||||
|
||||
// bulk delete, display the bulk delete confirmation form
|
||||
} elseif ($request->input('bulk_actions') == 'delete') {
|
||||
$this->authorize('delete', User::class);
|
||||
return view('users/confirm-bulk-delete')->with('users', $users)->with('statuslabel_list', Helper::statusLabelList());
|
||||
|
||||
// merge, confirm they have at least 2 users selected and display the merge screen
|
||||
} elseif ($request->input('bulk_actions') == 'merge') {
|
||||
$this->authorize('delete', User::class);
|
||||
|
||||
if (($request->filled('ids')) && (count($request->input('ids')) > 1)) {
|
||||
return view('users/confirm-merge')->with('users', $users);
|
||||
// Not enough users selected, send them back
|
||||
@@ -79,33 +75,6 @@ class BulkUsersController extends Controller
|
||||
}
|
||||
return redirect()->back()->with('success', trans('admin/users/message.password_resets_sent'));
|
||||
|
||||
} elseif ($request->input('bulk_actions') == 'print') {
|
||||
$users = User::query()
|
||||
->with([
|
||||
'assets.assetlog',
|
||||
'assets.assignedAssets.assetlog',
|
||||
'assets.assignedAssets.defaultLoc',
|
||||
'assets.assignedAssets.location',
|
||||
'assets.assignedAssets.model.category',
|
||||
'assets.defaultLoc',
|
||||
'assets.location',
|
||||
'assets.model.category',
|
||||
'accessories.assetlog',
|
||||
'accessories.category',
|
||||
'accessories.manufacturer',
|
||||
'consumables.assetlog',
|
||||
'consumables.category',
|
||||
'consumables.manufacturer',
|
||||
'licenses.category',
|
||||
])
|
||||
->withTrashed()
|
||||
->findMany($request->input('ids'));
|
||||
|
||||
$users->each(fn($user) => $this->authorize('view', $user));
|
||||
|
||||
return view('users.print')
|
||||
->with('users', $users)
|
||||
->with('settings', Setting::getSettings());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -131,7 +100,7 @@ class BulkUsersController extends Controller
|
||||
$user_raw_array = $request->input('ids');
|
||||
|
||||
// Remove the user from any updates.
|
||||
$user_raw_array = array_diff($user_raw_array, [auth()->id()]);
|
||||
$user_raw_array = array_diff($user_raw_array, [Auth::id()]);
|
||||
$manager_conflict = false;
|
||||
$users = User::whereIn('id', $user_raw_array)->where('id', '!=', auth()->id())->get();
|
||||
|
||||
@@ -146,9 +115,6 @@ class BulkUsersController extends Controller
|
||||
->conditionallyAddItem('remote')
|
||||
->conditionallyAddItem('ldap_import')
|
||||
->conditionallyAddItem('activated')
|
||||
->conditionallyAddItem('start_date')
|
||||
->conditionallyAddItem('end_date')
|
||||
->conditionallyAddItem('city')
|
||||
->conditionallyAddItem('autoassign_licenses');
|
||||
|
||||
|
||||
@@ -179,24 +145,13 @@ class BulkUsersController extends Controller
|
||||
$this->update_array['company_id'] = null;
|
||||
}
|
||||
|
||||
if ($request->input('null_start_date')=='1') {
|
||||
$this->update_array['start_date'] = null;
|
||||
}
|
||||
|
||||
if ($request->input('null_end_date')=='1') {
|
||||
$this->update_array['end_date'] = null;
|
||||
}
|
||||
|
||||
if ($request->input('null_locale')=='1') {
|
||||
$this->update_array['locale'] = null;
|
||||
}
|
||||
|
||||
|
||||
if (! $manager_conflict) {
|
||||
$this->conditionallyAddItem('manager_id');
|
||||
}
|
||||
// Save the updated info
|
||||
User::whereIn('id', $user_raw_array)
|
||||
->where('id', '!=', auth()->id())->update($this->update_array);
|
||||
->where('id', '!=', Auth::id())->update($this->update_array);
|
||||
|
||||
if (array_key_exists('location_id', $this->update_array)){
|
||||
Asset::where('assigned_type', User::class)
|
||||
@@ -258,24 +213,26 @@ class BulkUsersController extends Controller
|
||||
|
||||
$user_raw_array = request('ids');
|
||||
|
||||
if (($key = array_search(auth()->id(), $user_raw_array)) !== false) {
|
||||
if (($key = array_search(Auth::id(), $user_raw_array)) !== false) {
|
||||
unset($user_raw_array[$key]);
|
||||
}
|
||||
|
||||
$users = User::whereIn('id', $user_raw_array)->get();
|
||||
$assets = Asset::whereIn('assigned_to', $user_raw_array)->where('assigned_type', User::class)->get();
|
||||
$accessoryUserRows = DB::table('accessories_checkout')->where('assigned_type', User::class)->whereIn('assigned_to', $user_raw_array)->get();
|
||||
$assets = Asset::whereIn('assigned_to', $user_raw_array)->where('assigned_type', \App\Models\User::class)->get();
|
||||
$accessories = DB::table('accessories_users')->whereIn('assigned_to', $user_raw_array)->get();
|
||||
$licenses = DB::table('license_seats')->whereIn('assigned_to', $user_raw_array)->get();
|
||||
$consumableUserRows = DB::table('consumables_users')->whereIn('assigned_to', $user_raw_array)->get();
|
||||
$consumables = DB::table('consumables_users')->whereIn('assigned_to', $user_raw_array)->get();
|
||||
|
||||
if ((($assets->count() > 0) && ((!$request->filled('status_id')) || ($request->input('status_id') == '')))) {
|
||||
return redirect()->route('users.index')->with('error', 'No status selected');
|
||||
}
|
||||
|
||||
|
||||
$this->logItemCheckinAndDelete($assets, Asset::class);
|
||||
$this->logAccessoriesCheckin($accessoryUserRows);
|
||||
$this->logItemCheckinAndDelete($accessories, Accessory::class);
|
||||
$this->logItemCheckinAndDelete($licenses, License::class);
|
||||
$this->logConsumablesCheckin($consumableUserRows);
|
||||
$this->logItemCheckinAndDelete($consumables, Consumable::class);
|
||||
|
||||
|
||||
Asset::whereIn('id', $assets->pluck('id'))->update([
|
||||
'status_id' => e(request('status_id')),
|
||||
@@ -284,14 +241,19 @@ class BulkUsersController extends Controller
|
||||
'expected_checkin' => null,
|
||||
]);
|
||||
|
||||
|
||||
LicenseSeat::whereIn('id', $licenses->pluck('id'))->update(['assigned_to' => null]);
|
||||
ConsumableAssignment::whereIn('id', $consumableUserRows->pluck('id'))->delete();
|
||||
ConsumableAssignment::whereIn('id', $consumables->pluck('id'))->delete();
|
||||
|
||||
|
||||
foreach ($users as $user) {
|
||||
|
||||
$user->consumables()->sync([]);
|
||||
$user->accessories()->sync([]);
|
||||
if ($request->input('delete_user')=='1') {
|
||||
$user->delete();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$msg = trans('general.bulk_checkin_success');
|
||||
@@ -317,41 +279,13 @@ class BulkUsersController extends Controller
|
||||
if ($itemType == License::class){
|
||||
$item_id = $item->license_id;
|
||||
}
|
||||
|
||||
|
||||
$logAction->item_id = $item_id;
|
||||
// We can't rely on get_class here because the licenses/accessories fetched above are not eloquent models, but simply arrays.
|
||||
$logAction->item_type = $itemType;
|
||||
$logAction->target_id = $item->assigned_to;
|
||||
$logAction->target_type = User::class;
|
||||
$logAction->created_at = auth()->id();
|
||||
$logAction->note = 'Bulk checkin items';
|
||||
$logAction->logaction('checkin from');
|
||||
}
|
||||
}
|
||||
|
||||
private function logAccessoriesCheckin(Collection $accessoryUserRows): void
|
||||
{
|
||||
foreach ($accessoryUserRows as $accessoryUserRow) {
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $accessoryUserRow->accessory_id;
|
||||
$logAction->item_type = Accessory::class;
|
||||
$logAction->target_id = $accessoryUserRow->assigned_to;
|
||||
$logAction->target_type = User::class;
|
||||
$logAction->created_at = auth()->id();
|
||||
$logAction->note = 'Bulk checkin items';
|
||||
$logAction->logaction('checkin from');
|
||||
}
|
||||
}
|
||||
|
||||
private function logConsumablesCheckin(Collection $consumableUserRows): void
|
||||
{
|
||||
foreach ($consumableUserRows as $consumableUserRow) {
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $consumableUserRow->consumable_id;
|
||||
$logAction->item_type = Consumable::class;
|
||||
$logAction->target_id = $consumableUserRow->assigned_to;
|
||||
$logAction->target_type = User::class;
|
||||
$logAction->created_at = auth()->id();
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->note = 'Bulk checkin items';
|
||||
$logAction->logaction('checkin from');
|
||||
}
|
||||
|
||||
@@ -7,6 +7,9 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
@@ -43,7 +46,7 @@ class UserFilesController extends Controller
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->created_by = auth()->id();
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->note = $request->input('notes');
|
||||
$logAction->target_id = null;
|
||||
$logAction->created_at = date("Y-m-d H:i:s");
|
||||
@@ -113,30 +116,31 @@ class UserFilesController extends Controller
|
||||
public function show($userId = null, $fileId = null)
|
||||
{
|
||||
|
||||
|
||||
if (empty($fileId)) {
|
||||
return redirect()->route('users.show')->with('error', 'Invalid file request');
|
||||
}
|
||||
|
||||
if ($user = User::find($userId)) {
|
||||
$user = User::find($userId);
|
||||
|
||||
// the license is valid
|
||||
if (isset($user->id)) {
|
||||
|
||||
$this->authorize('view', $user);
|
||||
|
||||
if ($log = Actionlog::whereNotNull('filename')->where('item_id', $user->id)->find($fileId)) {
|
||||
$file = 'private_uploads/users/'.$log->filename;
|
||||
|
||||
try {
|
||||
return StorageHelper::showOrDownloadFile($file, $log->filename);
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('users.show', ['user' => $user])->with('error', trans('general.file_not_found'));
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download('private_uploads/users/'.$log->filename, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return Storage::download('private_uploads/users/'.$log->filename);
|
||||
}
|
||||
|
||||
// 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'));
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.log_record_not_found'));
|
||||
}
|
||||
|
||||
// Redirect to the user management page if the user doesn't exist
|
||||
|
||||
@@ -133,8 +133,6 @@ class UsersController extends Controller
|
||||
// we have to invoke the
|
||||
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($user->save()) {
|
||||
if ($request->filled('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
@@ -154,7 +152,7 @@ class UsersController extends Controller
|
||||
$user->notify(new WelcomeNotification($data));
|
||||
}
|
||||
|
||||
return redirect()->to(Helper::getRedirectOption($request, $user->id, 'Users'))->with('success', trans('admin/users/message.success.create'));
|
||||
return redirect()->route('users.index')->with('success', trans('admin/users/message.success.create'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($user->getErrors());
|
||||
@@ -186,7 +184,7 @@ class UsersController extends Controller
|
||||
{
|
||||
|
||||
$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($id);
|
||||
|
||||
if ($user) {
|
||||
|
||||
@@ -214,79 +212,83 @@ class UsersController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(SaveUserRequest $request, User $user)
|
||||
public function update(SaveUserRequest $request, $id = null)
|
||||
{
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
// This is a janky hack to prevent people from changing admin demo user data on the public demo.
|
||||
// The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder.
|
||||
// Thanks, jerks. You are why we can't have nice things. - snipe
|
||||
if ((($user->id == 1) || ($user->id == 2)) && (config('app.lock_passwords'))) {
|
||||
|
||||
if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) {
|
||||
return redirect()->route('users.index')->with('error', trans('general.permission_denied_superuser_demo'));
|
||||
}
|
||||
|
||||
|
||||
// We need to reverse the UI specific logic for our
|
||||
// permissions here before we update the user.
|
||||
$permissions = $request->input('permissions', []);
|
||||
app('request')->request->set('permissions', $permissions);
|
||||
|
||||
$user->load(['assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc'])->withTrashed();
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id);
|
||||
|
||||
$this->authorize('update', $user);
|
||||
// User is valid - continue...
|
||||
if ($user) {
|
||||
$this->authorize('update', $user);
|
||||
|
||||
// Figure out of this user was an admin before this edit
|
||||
$orig_permissions_array = $user->decodePermissions();
|
||||
$orig_superuser = '0';
|
||||
if (is_array($orig_permissions_array)) {
|
||||
if (array_key_exists('superuser', $orig_permissions_array)) {
|
||||
$orig_superuser = $orig_permissions_array['superuser'];
|
||||
// Figure out of this user was an admin before this edit
|
||||
$orig_permissions_array = $user->decodePermissions();
|
||||
$orig_superuser = '0';
|
||||
if (is_array($orig_permissions_array)) {
|
||||
if (array_key_exists('superuser', $orig_permissions_array)) {
|
||||
$orig_superuser = $orig_permissions_array['superuser'];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Only save groups if the user is a superuser
|
||||
if (auth()->user()->isSuperUser()) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
}
|
||||
// Only save groups if the user is a superuser
|
||||
if (auth()->user()->isSuperUser()) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
}
|
||||
|
||||
// Update the user fields
|
||||
$user->username = trim($request->input('username'));
|
||||
$user->email = trim($request->input('email'));
|
||||
$user->first_name = $request->input('first_name');
|
||||
$user->last_name = $request->input('last_name');
|
||||
$user->two_factor_optin = $request->input('two_factor_optin') ?: 0;
|
||||
$user->locale = $request->input('locale');
|
||||
$user->employee_num = $request->input('employee_num');
|
||||
$user->activated = $request->input('activated', 0);
|
||||
$user->jobtitle = $request->input('jobtitle', null);
|
||||
$user->phone = $request->input('phone');
|
||||
$user->location_id = $request->input('location_id', null);
|
||||
$user->company_id = Company::getIdForUser($request->input('company_id', null));
|
||||
$user->manager_id = $request->input('manager_id', null);
|
||||
$user->notes = $request->input('notes');
|
||||
$user->department_id = $request->input('department_id', null);
|
||||
$user->address = $request->input('address', null);
|
||||
$user->city = $request->input('city', null);
|
||||
$user->state = $request->input('state', null);
|
||||
$user->country = $request->input('country', null);
|
||||
// if a user is editing themselves we should always keep activated true
|
||||
$user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 0);
|
||||
$user->zip = $request->input('zip', null);
|
||||
$user->remote = $request->input('remote', 0);
|
||||
$user->vip = $request->input('vip', 0);
|
||||
$user->website = $request->input('website', null);
|
||||
$user->start_date = $request->input('start_date', null);
|
||||
$user->end_date = $request->input('end_date', null);
|
||||
$user->autoassign_licenses = $request->input('autoassign_licenses', 0);
|
||||
// Update the user fields
|
||||
$user->username = trim($request->input('username'));
|
||||
$user->email = trim($request->input('email'));
|
||||
$user->first_name = $request->input('first_name');
|
||||
$user->last_name = $request->input('last_name');
|
||||
$user->two_factor_optin = $request->input('two_factor_optin') ?: 0;
|
||||
$user->locale = $request->input('locale');
|
||||
$user->employee_num = $request->input('employee_num');
|
||||
$user->activated = $request->input('activated', 0);
|
||||
$user->jobtitle = $request->input('jobtitle', null);
|
||||
$user->phone = $request->input('phone');
|
||||
$user->location_id = $request->input('location_id', null);
|
||||
$user->company_id = Company::getIdForUser($request->input('company_id', null));
|
||||
$user->manager_id = $request->input('manager_id', null);
|
||||
$user->notes = $request->input('notes');
|
||||
$user->department_id = $request->input('department_id', null);
|
||||
$user->address = $request->input('address', null);
|
||||
$user->city = $request->input('city', null);
|
||||
$user->state = $request->input('state', null);
|
||||
$user->country = $request->input('country', null);
|
||||
// if a user is editing themselves we should always keep activated true
|
||||
$user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 0);
|
||||
$user->zip = $request->input('zip', null);
|
||||
$user->remote = $request->input('remote', 0);
|
||||
$user->vip = $request->input('vip', 0);
|
||||
$user->website = $request->input('website', null);
|
||||
$user->start_date = $request->input('start_date', null);
|
||||
$user->end_date = $request->input('end_date', null);
|
||||
$user->autoassign_licenses = $request->input('autoassign_licenses', 0);
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)
|
||||
->update(['location_id' => $request->input('location_id', null)]);
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)
|
||||
->update(['location_id' => $request->input('location_id', null)]);
|
||||
|
||||
// Do we want to update the user password?
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
// Do we want to update the user password?
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
@@ -307,14 +309,19 @@ class UsersController extends Controller
|
||||
|
||||
// Handle uploaded avatar
|
||||
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
session()->put(['redirect_option' => $request->get('redirect_option')]);
|
||||
|
||||
if ($user->save()) {
|
||||
// Redirect to the user page
|
||||
return redirect()->to(Helper::getRedirectOption($request, $user->id, 'Users'))
|
||||
return redirect()->route('users.index')
|
||||
->with('success', trans('admin/users/message.success.update'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($user->getErrors());
|
||||
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', compact('id')));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -372,7 +379,7 @@ class UsersController extends Controller
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->item_id = $user->id;
|
||||
$logaction->created_at = date('Y-m-d H:i:s');
|
||||
$logaction->created_by = auth()->id();
|
||||
$logaction->user_id = auth()->id();
|
||||
$logaction->logaction('restore');
|
||||
|
||||
// Redirect them to the deleted page if there are more, otherwise the section index
|
||||
@@ -591,43 +598,29 @@ class UsersController extends Controller
|
||||
/**
|
||||
* Print inventory
|
||||
*
|
||||
* @since [v1.8]
|
||||
* @author Aladin Alaily
|
||||
* @since [v1.8]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function printInventory($id)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$user = User::where('id', $id)->withTrashed()->first();
|
||||
|
||||
|
||||
$user = User::where('id', $id)
|
||||
->with([
|
||||
'assets.assetlog',
|
||||
'assets.assignedAssets.assetlog',
|
||||
'assets.assignedAssets.defaultLoc',
|
||||
'assets.assignedAssets.location',
|
||||
'assets.assignedAssets.model.category',
|
||||
'assets.defaultLoc',
|
||||
'assets.location',
|
||||
'assets.model.category',
|
||||
'accessories.assetlog',
|
||||
'accessories.category',
|
||||
'accessories.manufacturer',
|
||||
'consumables.assetlog',
|
||||
'consumables.category',
|
||||
'consumables.manufacturer',
|
||||
'licenses.category',
|
||||
])
|
||||
->withTrashed()
|
||||
->first();
|
||||
// Make sure they can view this particular user
|
||||
$this->authorize('view', $user);
|
||||
|
||||
if ($user) {
|
||||
$this->authorize('view', $user);
|
||||
$assets = Asset::where('assigned_to', $id)->where('assigned_type', User::class)->with('model', 'model.category')->get();
|
||||
$accessories = $user->accessories()->get();
|
||||
$consumables = $user->consumables()->get();
|
||||
|
||||
return view('users.print')
|
||||
->with('users', [$user])
|
||||
->with('settings', Setting::getSettings());
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', compact('id')));
|
||||
return view('users/print')->with('assets', $assets)
|
||||
->with('licenses', $user->licenses()->get())
|
||||
->with('accessories', $accessories)
|
||||
->with('consumables', $consumables)
|
||||
->with('show_user', $user)
|
||||
->with('settings', Setting::getSettings());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -13,7 +13,6 @@ use App\Notifications\RequestAssetNotification;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Http\RedirectResponse;
|
||||
use \Illuminate\Contracts\View\View;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to the ability for users
|
||||
@@ -180,11 +179,8 @@ class ViewAssetsController extends Controller
|
||||
$asset->decrement('requests_counter', 1);
|
||||
|
||||
$logaction->logaction('request canceled');
|
||||
try {
|
||||
$settings->notify(new RequestAssetCancelation($data));
|
||||
} catch (\Exception $e) {
|
||||
Log::warning($e);
|
||||
}
|
||||
$settings->notify(new RequestAssetCancelation($data));
|
||||
|
||||
return redirect()->route('requestable-assets')
|
||||
->with('success')->with('success', trans('admin/hardware/message.requests.canceled'));
|
||||
}
|
||||
@@ -192,11 +188,7 @@ class ViewAssetsController extends Controller
|
||||
$logaction->logaction('requested');
|
||||
$asset->request();
|
||||
$asset->increment('requests_counter', 1);
|
||||
try {
|
||||
$settings->notify(new RequestAssetNotification($data));
|
||||
} catch (\Exception $e) {
|
||||
Log::warning($e);
|
||||
}
|
||||
$settings->notify(new RequestAssetNotification($data));
|
||||
|
||||
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.success'));
|
||||
}
|
||||
|
||||
@@ -14,7 +14,6 @@ class Kernel extends HttpKernel
|
||||
* @var array
|
||||
*/
|
||||
protected $middleware = [
|
||||
\App\Http\Middleware\TrustProxies::class,
|
||||
\App\Http\Middleware\NoSessionStore::class,
|
||||
\Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
@@ -22,7 +21,6 @@ class Kernel extends HttpKernel
|
||||
\App\Http\Middleware\CheckForSetup::class,
|
||||
\App\Http\Middleware\CheckForDebug::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
\App\Http\Middleware\TrimStrings::class,
|
||||
\App\Http\Middleware\SecurityHeaders::class,
|
||||
\App\Http\Middleware\PreventBackHistory::class,
|
||||
\Illuminate\Http\Middleware\HandleCors::class,
|
||||
@@ -45,17 +43,10 @@ class Kernel extends HttpKernel
|
||||
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
|
||||
\App\Http\Middleware\AssetCountForSidebar::class,
|
||||
\Illuminate\Session\Middleware\AuthenticateSession::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
],
|
||||
|
||||
'api' => [
|
||||
'auth:api',
|
||||
\App\Http\Middleware\CheckLocale::class,
|
||||
\Illuminate\Routing\Middleware\SubstituteBindings::class,
|
||||
],
|
||||
|
||||
'health' => [
|
||||
|
||||
],
|
||||
];
|
||||
|
||||
@@ -73,6 +64,5 @@ class Kernel extends HttpKernel
|
||||
'can' => \Illuminate\Auth\Middleware\Authorize::class,
|
||||
'guest' => \App\Http\Middleware\RedirectIfAuthenticated::class,
|
||||
'throttle' => \Illuminate\Routing\Middleware\ThrottleRequests::class,
|
||||
'health' => null,
|
||||
];
|
||||
}
|
||||
|
||||
@@ -7,19 +7,14 @@ use Closure;
|
||||
|
||||
class CheckForSetup
|
||||
{
|
||||
|
||||
protected $except = [
|
||||
'_debugbar*',
|
||||
'health'
|
||||
];
|
||||
|
||||
public function handle($request, Closure $next, $guard = null)
|
||||
{
|
||||
|
||||
/**
|
||||
* Skip this middleware for the debugbar and health check
|
||||
* This is dumb
|
||||
* @todo Check on removing this, not sure if it's still needed
|
||||
*/
|
||||
if ($request->is($this->except)) {
|
||||
if ($request->is('_debugbar*')) {
|
||||
return $next($request);
|
||||
}
|
||||
|
||||
@@ -30,7 +25,7 @@ class CheckForSetup
|
||||
return $next($request);
|
||||
}
|
||||
} else {
|
||||
if (! ($request->is('setup*')) && ! ($request->is('.env'))) {
|
||||
if (! ($request->is('setup*')) && ! ($request->is('.env')) && ! ($request->is('health'))) {
|
||||
return redirect(config('app.url').'/setup');
|
||||
}
|
||||
|
||||
|
||||
@@ -20,5 +20,5 @@ class EncryptCookies extends BaseEncrypter
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
protected static $serialize = false;
|
||||
protected static $serialize = true;
|
||||
}
|
||||
|
||||
@@ -1,76 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
class AccessoryCheckoutRequest extends ImageUploadRequest
|
||||
{
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return Gate::allows('checkout', new Accessory);
|
||||
}
|
||||
|
||||
public function prepareForValidation(): void
|
||||
{
|
||||
|
||||
if ($this->accessory) {
|
||||
|
||||
$this->diff = ($this->accessory->numRemaining() - $this->checkout_qty);
|
||||
$this->merge([
|
||||
'checkout_qty' => $this->checkout_qty ?? 1,
|
||||
'number_remaining_after_checkout' => (int) ($this->accessory->numRemaining() - $this->checkout_qty),
|
||||
'number_currently_remaining' => (int) $this->accessory->numRemaining(),
|
||||
'checkout_difference' => (int) $this->diff,
|
||||
]);
|
||||
|
||||
\Log::debug('---------------------------------------------');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
|
||||
return array_merge(
|
||||
[
|
||||
'assigned_user' => 'required_without_all:assigned_asset,assigned_location',
|
||||
'assigned_asset' => 'required_without_all:assigned_user,assigned_location',
|
||||
'assigned_location' => 'required_without_all:assigned_user,assigned_asset',
|
||||
|
||||
'number_remaining_after_checkout' => [
|
||||
'min:0',
|
||||
'required',
|
||||
'integer',
|
||||
],
|
||||
|
||||
'checkout_qty' => [
|
||||
'integer',
|
||||
'lte:number_currently_remaining',
|
||||
'min:1',
|
||||
],
|
||||
],
|
||||
);
|
||||
}
|
||||
|
||||
public function messages(): array
|
||||
{
|
||||
$messages = [
|
||||
'checkout_qty.lte' => trans_choice('admin/accessories/message.checkout.checkout_qty.lte', $this->number_currently_remaining, [
|
||||
'number_currently_remaining' => $this->number_currently_remaining,
|
||||
'checkout_qty' => $this->checkout_qty,
|
||||
]),
|
||||
];
|
||||
return $messages;
|
||||
}
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user