diff --git a/.all-contributorsrc b/.all-contributorsrc
index 146f6178ce..a4002a4841 100644
--- a/.all-contributorsrc
+++ b/.all-contributorsrc
@@ -3018,6 +3018,151 @@
"contributions": [
"code"
]
+ },
+ {
+ "login": "koiakoia",
+ "name": "koiakoia",
+ "avatar_url": "https://avatars.githubusercontent.com/u/60405354?v=4",
+ "profile": "https://github.com/koiakoia",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "mustafa-online",
+ "name": "Mustafa Online",
+ "avatar_url": "https://avatars.githubusercontent.com/u/5323832?v=4",
+ "profile": "https://github.com/mustafa-online",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "franceslui",
+ "name": "franceslui",
+ "avatar_url": "https://avatars.githubusercontent.com/u/104601439?v=4",
+ "profile": "https://github.com/franceslui",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Q4kK",
+ "name": "Q4kK",
+ "avatar_url": "https://avatars.githubusercontent.com/u/125313163?v=4",
+ "profile": "https://github.com/Q4kK",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "squintfox",
+ "name": "squintfox",
+ "avatar_url": "https://avatars.githubusercontent.com/u/55590532?v=4",
+ "profile": "https://github.com/squintfox",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "jeffclay",
+ "name": "Jeff Clay",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1380084?v=4",
+ "profile": "https://github.com/jeffclay",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "PP-JN-RL",
+ "name": "Phil J R",
+ "avatar_url": "https://avatars.githubusercontent.com/u/52716446?v=4",
+ "profile": "https://github.com/PP-JN-RL",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "chandanchowdhury",
+ "name": "i_virus",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1496725?v=4",
+ "profile": "https://www.corelight.com/",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "gitgrimbo",
+ "name": "Paul Grime",
+ "avatar_url": "https://avatars.githubusercontent.com/u/1020541?v=4",
+ "profile": "https://github.com/gitgrimbo",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "LeePorte",
+ "name": "Lee Porte",
+ "avatar_url": "https://avatars.githubusercontent.com/u/922815?v=4",
+ "profile": "https://leeporte.co.uk",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "bryanlopezinc",
+ "name": "BRYAN ",
+ "avatar_url": "https://avatars.githubusercontent.com/u/23613427?v=4",
+ "profile": "https://github.com/bryanlopezinc",
+ "contributions": [
+ "code",
+ "test"
+ ]
+ },
+ {
+ "login": "U-H-T",
+ "name": "U-H-T",
+ "avatar_url": "https://avatars.githubusercontent.com/u/64061710?v=4",
+ "profile": "https://github.com/U-H-T",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "Tyree",
+ "name": "Matt Tyree",
+ "avatar_url": "https://avatars.githubusercontent.com/u/5395363?v=4",
+ "profile": "https://github.com/Tyree",
+ "contributions": [
+ "doc"
+ ]
+ },
+ {
+ "login": "FlorentDotMe",
+ "name": "Florent Bervas",
+ "avatar_url": "https://avatars.githubusercontent.com/u/292081?v=4",
+ "profile": "http://spoontux.net",
+ "contributions": [
+ "code"
+ ]
+ },
+ {
+ "login": "dbakan",
+ "name": "Daniel Albertsen",
+ "avatar_url": "https://avatars.githubusercontent.com/u/4498077?v=4",
+ "profile": "https://ditscheri.com",
+ "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"
+ ]
}
]
}
diff --git a/.env.dev.docker b/.env.dev.docker
new file mode 100644
index 0000000000..7b9e2000cf
--- /dev/null
+++ b/.env.dev.docker
@@ -0,0 +1,166 @@
+# --------------------------------------------
+# REQUIRED: DB SETUP
+# --------------------------------------------
+MYSQL_DATABASE=snipeit
+MYSQL_USER=snipeit
+MYSQL_PASSWORD=changeme1234
+MYSQL_ROOT_PASSWORD=changeme1234
+# --------------------------------------------
+# REQUIRED: BASIC APP SETTINGS
+# --------------------------------------------
+APP_ENV=develop
+APP_DEBUG=false
+# please regenerate the APP_KEY value by calling `docker-compose run --rm snipeit bash` and then `php artisan key:generate --show` and then copy paste the value here
+APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
+APP_URL=http://localhost:8000
+APP_TIMEZONE='UTC'
+APP_LOCALE=en
+MAX_RESULTS=500
+
+# --------------------------------------------
+# REQUIRED: UPLOADED FILE STORAGE SETTINGS
+# --------------------------------------------
+PRIVATE_FILESYSTEM_DISK=local
+PUBLIC_FILESYSTEM_DISK=local_public
+
+# --------------------------------------------
+# REQUIRED: DATABASE SETTINGS
+# --------------------------------------------
+DB_CONNECTION=mysql
+DB_HOST=mariadb
+DB_DATABASE=snipeit
+DB_USERNAME=snipeit
+DB_PASSWORD=changeme1234
+DB_PREFIX=null
+DB_DUMP_PATH='/usr/bin'
+DB_CHARSET=utf8mb4
+DB_COLLATION=utf8mb4_unicode_ci
+
+# --------------------------------------------
+# OPTIONAL: SSL DATABASE SETTINGS
+# --------------------------------------------
+DB_SSL=false
+DB_SSL_IS_PAAS=false
+DB_SSL_KEY_PATH=null
+DB_SSL_CERT_PATH=null
+DB_SSL_CA_PATH=null
+DB_SSL_CIPHER=null
+DB_SSL_VERIFY_SERVER=null
+
+# --------------------------------------------
+# REQUIRED: OUTGOING MAIL SERVER SETTINGS
+# --------------------------------------------
+MAIL_DRIVER=smtp
+MAIL_HOST=mailhog
+MAIL_PORT=1025
+MAIL_USERNAME=null
+MAIL_PASSWORD=null
+MAIL_ENCRYPTION=null
+MAIL_FROM_ADDR=you@example.com
+MAIL_FROM_NAME='Snipe-IT'
+MAIL_REPLYTO_ADDR=you@example.com
+MAIL_REPLYTO_NAME='Snipe-IT'
+MAIL_AUTO_EMBED_METHOD='attachment'
+
+# --------------------------------------------
+# REQUIRED: IMAGE LIBRARY
+# This should be gd or imagick
+# --------------------------------------------
+IMAGE_LIB=gd
+
+
+# --------------------------------------------
+# OPTIONAL: BACKUP SETTINGS
+# --------------------------------------------
+MAIL_BACKUP_NOTIFICATION_DRIVER=null
+MAIL_BACKUP_NOTIFICATION_ADDRESS=null
+BACKUP_ENV=true
+
+
+# --------------------------------------------
+# OPTIONAL: SESSION SETTINGS
+# --------------------------------------------
+SESSION_LIFETIME=12000
+EXPIRE_ON_CLOSE=false
+ENCRYPT=false
+COOKIE_NAME=snipeit_session
+COOKIE_DOMAIN=null
+SECURE_COOKIES=false
+API_TOKEN_EXPIRATION_YEARS=40
+
+# --------------------------------------------
+# OPTIONAL: SECURITY HEADER SETTINGS
+# --------------------------------------------
+APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
+ALLOW_IFRAMING=false
+REFERRER_POLICY=same-origin
+ENABLE_CSP=false
+CORS_ALLOWED_ORIGINS=null
+ENABLE_HSTS=false
+
+# --------------------------------------------
+# OPTIONAL: CACHE SETTINGS
+# --------------------------------------------
+CACHE_DRIVER=file
+SESSION_DRIVER=file
+QUEUE_DRIVER=sync
+CACHE_PREFIX=snipeit
+
+# --------------------------------------------
+# OPTIONAL: REDIS SETTINGS
+# --------------------------------------------
+REDIS_HOST=redis
+REDIS_PASSWORD=null
+REDIS_PORT=6379
+
+# --------------------------------------------
+# OPTIONAL: MEMCACHED SETTINGS
+# --------------------------------------------
+MEMCACHED_HOST=null
+MEMCACHED_PORT=null
+
+# --------------------------------------------
+# OPTIONAL: PUBLIC S3 Settings
+# --------------------------------------------
+PUBLIC_AWS_SECRET_ACCESS_KEY=null
+PUBLIC_AWS_ACCESS_KEY_ID=null
+PUBLIC_AWS_DEFAULT_REGION=null
+PUBLIC_AWS_BUCKET=null
+PUBLIC_AWS_URL=null
+PUBLIC_AWS_BUCKET_ROOT=null
+
+# --------------------------------------------
+# OPTIONAL: PRIVATE S3 Settings
+# --------------------------------------------
+PRIVATE_AWS_ACCESS_KEY_ID=null
+PRIVATE_AWS_SECRET_ACCESS_KEY=null
+PRIVATE_AWS_DEFAULT_REGION=null
+PRIVATE_AWS_BUCKET=null
+PRIVATE_AWS_URL=null
+PRIVATE_AWS_BUCKET_ROOT=null
+
+# --------------------------------------------
+# OPTIONAL: AWS Settings
+# --------------------------------------------
+AWS_ACCESS_KEY_ID=null
+AWS_SECRET_ACCESS_KEY=null
+AWS_DEFAULT_REGION=null
+
+# --------------------------------------------
+# OPTIONAL: LOGIN THROTTLING
+# --------------------------------------------
+LOGIN_MAX_ATTEMPTS=5
+LOGIN_LOCKOUT_DURATION=60
+RESET_PASSWORD_LINK_EXPIRES=900
+
+# --------------------------------------------
+# OPTIONAL: MISC
+# --------------------------------------------
+LOG_CHANNEL=stderr
+LOG_MAX_DAYS=10
+APP_LOCKED=false
+APP_CIPHER=AES-256-CBC
+APP_FORCE_TLS=false
+GOOGLE_MAPS_API=
+LDAP_MEM_LIM=500M
+LDAP_TIME_LIM=600
diff --git a/.env.docker b/.env.docker
index 87897b10db..35c10bfde1 100644
--- a/.env.docker
+++ b/.env.docker
@@ -1,18 +1,18 @@
# --------------------------------------------
-# REQUIRED: DB SETUP
+# REQUIRED: DOCKER SPECIFIC SETTINGS
# --------------------------------------------
-MYSQL_DATABASE=snipeit
-MYSQL_USER=snipeit
-MYSQL_PASSWORD=changeme1234
-MYSQL_ROOT_PASSWORD=changeme1234
+APP_VERSION=v6.4.1
+APP_PORT=8000
+
# --------------------------------------------
# REQUIRED: BASIC APP SETTINGS
# --------------------------------------------
-APP_ENV=develop
+APP_ENV=production
APP_DEBUG=false
-# please regenerate the APP_KEY value by calling `docker-compose run --rm snipeit bash` and then `php artisan key:generate --show` and then copy paste the value here
+# Please regenerate the APP_KEY value by calling `docker compose run --rm snipeit php artisan key:generate --show`. Copy paste the value here
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
MAX_RESULTS=500
@@ -27,10 +27,12 @@ PUBLIC_FILESYSTEM_DISK=local_public
# REQUIRED: DATABASE SETTINGS
# --------------------------------------------
DB_CONNECTION=mysql
-DB_HOST=mariadb
+DB_HOST=db
+DB_PORT='3306'
DB_DATABASE=snipeit
DB_USERNAME=snipeit
DB_PASSWORD=changeme1234
+MYSQL_ROOT_PASSWORD=changeme1234
DB_PREFIX=null
DB_DUMP_PATH='/usr/bin'
DB_CHARSET=utf8mb4
@@ -45,29 +47,35 @@ DB_SSL_KEY_PATH=null
DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
DB_SSL_CIPHER=null
+DB_SSL_VERIFY_SERVER=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
-MAIL_DRIVER=smtp
+MAIL_MAILER=smtp
MAIL_HOST=mailhog
MAIL_PORT=1025
MAIL_USERNAME=null
MAIL_PASSWORD=null
-MAIL_ENCRYPTION=null
+MAIL_TLS_VERIFY_PEER=true
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME='Snipe-IT'
MAIL_REPLYTO_ADDR=you@example.com
MAIL_REPLYTO_NAME='Snipe-IT'
MAIL_AUTO_EMBED_METHOD='attachment'
+# --------------------------------------------
+# REQUIRED: DATA PROTECTION
+# --------------------------------------------
+ALLOW_BACKUP_DELETE=false
+ALLOW_DATA_PURGE=false
+
# --------------------------------------------
# REQUIRED: IMAGE LIBRARY
# This should be gd or imagick
# --------------------------------------------
IMAGE_LIB=gd
-
# --------------------------------------------
# OPTIONAL: BACKUP SETTINGS
# --------------------------------------------
@@ -75,7 +83,6 @@ MAIL_BACKUP_NOTIFICATION_DRIVER=null
MAIL_BACKUP_NOTIFICATION_ADDRESS=null
BACKUP_ENV=true
-
# --------------------------------------------
# OPTIONAL: SESSION SETTINGS
# --------------------------------------------
@@ -90,7 +97,7 @@ API_TOKEN_EXPIRATION_YEARS=40
# --------------------------------------------
# OPTIONAL: SECURITY HEADER SETTINGS
# --------------------------------------------
-APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
+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
@@ -108,7 +115,7 @@ CACHE_PREFIX=snipeit
# --------------------------------------------
# OPTIONAL: REDIS SETTINGS
# --------------------------------------------
-REDIS_HOST=redis
+REDIS_HOST=null
REDIS_PASSWORD=null
REDIS_PORT=6379
diff --git a/.env.dusk.example b/.env.dusk.example
index 074f6fc3d7..2f16f44c7a 100644
--- a/.env.dusk.example
+++ b/.env.dusk.example
@@ -36,11 +36,12 @@ DB_SSL_KEY_PATH=null
DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
DB_SSL_CIPHER=null
+DB_SSL_VERIFY_SERVER=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
-MAIL_DRIVER="log"
+MAIL_MAILER="log"
# --------------------------------------------
diff --git a/.env.example b/.env.example
index fd90391973..5c0a0b8abc 100644
--- a/.env.example
+++ b/.env.example
@@ -42,21 +42,26 @@ DB_SSL_KEY_PATH=null
DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
DB_SSL_CIPHER=null
+DB_SSL_VERIFY_SERVER=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
-MAIL_DRIVER=smtp
+MAIL_MAILER=smtp
MAIL_HOST=email-smtp.us-west-2.amazonaws.com
MAIL_PORT=587
MAIL_USERNAME=YOURUSERNAME
MAIL_PASSWORD=YOURPASSWORD
-MAIL_ENCRYPTION=null
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME='Snipe-IT'
MAIL_REPLYTO_ADDR=you@example.com
MAIL_REPLYTO_NAME='Snipe-IT'
MAIL_AUTO_EMBED_METHOD='attachment'
+MAIL_TLS_VERIFY_PEER=true
+
+# MAIL_ENCRYPTION is no longer supported. SymfonyMailer will use tls if it's
+# advertised, and won't if it's not. If you want to use your mail server's IP but it's failing
+# because of certificate errors, set MAIL_TLS_VERIFY_PEER-true
# --------------------------------------------
# REQUIRED: IMAGE LIBRARY
@@ -95,6 +100,7 @@ APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
ALLOW_IFRAMING=false
REFERRER_POLICY=same-origin
ENABLE_CSP=false
+ADDITIONAL_CSP_URLS=null
CORS_ALLOWED_ORIGINS=null
ENABLE_HSTS=false
@@ -177,6 +183,7 @@ REPORT_TIME_LIMIT=12000
REQUIRE_SAML=false
API_THROTTLE_PER_MINUTE=120
CSV_ESCAPE_FORMULAS=true
+LIVEWIRE_URL_PREFIX=null
# --------------------------------------------
# OPTIONAL: HASHING
@@ -191,4 +198,4 @@ ARGON_TIME=2
# OPTIONAL: SCIM
# --------------------------------------------
SCIM_TRACE=false
-SCIM_STANDARDS_COMPLIANCE=false
\ No newline at end of file
+SCIM_STANDARDS_COMPLIANCE=false
diff --git a/.env.testing-ci b/.env.testing-ci
index f17a5c6c30..3e00eb3fa3 100644
--- a/.env.testing-ci
+++ b/.env.testing-ci
@@ -22,7 +22,7 @@ DB_PASSWORD=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
-MAIL_DRIVER=log
+MAIL_MAILER=log
# --------------------------------------------
diff --git a/.env.tests b/.env.tests
index 038884e5dd..8128d22b55 100644
--- a/.env.tests
+++ b/.env.tests
@@ -18,6 +18,6 @@ APP_KEY=base64:tu9NRh/a6+dCXBDGvg0Gv/0TcABnFsbT4AKxrr8mwQo=
LOGIN_MAX_ATTEMPTS=1000000
LOGIN_LOCKOUT_DURATION=100000000
-MAIL_DRIVER=log
+MAIL_MAILER=log
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME=Snipe-IT
diff --git a/.env.unit-tests b/.env.unit-tests
index 3a7263f86a..28177839dd 100644
--- a/.env.unit-tests
+++ b/.env.unit-tests
@@ -15,6 +15,6 @@ APP_KEY=base64:tu9NRh/a6+dCXBDGvg0Gv/0TcABnFsbT4AKxrr8mwQo=
LOGIN_MAX_ATTEMPTS=1000000
LOGIN_LOCKOUT_DURATION=100000000
-MAIL_DRIVER=log
+MAIL_MAILER=log
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME=Snipe-IT
diff --git a/.github/workflows/codacy-analysis.yml b/.github/workflows/codacy-analysis.yml
index d7438a7ae9..e3e9356425 100644
--- a/.github/workflows/codacy-analysis.yml
+++ b/.github/workflows/codacy-analysis.yml
@@ -36,7 +36,7 @@ jobs:
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
- name: Run Codacy Analysis CLI
- uses: codacy/codacy-analysis-cli-action@v4.4.0
+ uses: codacy/codacy-analysis-cli-action@v4.4.5
with:
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
# You can also omit the token and run the tools that support default configurations
diff --git a/.github/workflows/crowdin-upload.yml b/.github/workflows/crowdin-upload.yml
index 3255934534..7b9331c97d 100644
--- a/.github/workflows/crowdin-upload.yml
+++ b/.github/workflows/crowdin-upload.yml
@@ -12,7 +12,7 @@ jobs:
uses: actions/checkout@v4
- name: Crowdin push
- uses: crowdin/github-action@v1
+ uses: crowdin/github-action@v2
with:
upload_sources: true
upload_translations: false
diff --git a/.github/workflows/docker-alpine.yml b/.github/workflows/docker-alpine.yml
index 7223ab30dc..bd46f9567b 100644
--- a/.github/workflows/docker-alpine.yml
+++ b/.github/workflows/docker-alpine.yml
@@ -73,7 +73,7 @@ jobs:
# https://github.com/docker/build-push-action
- name: Build and push 'snipe-it' image
id: docker_build
- uses: docker/build-push-action@v5
+ uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile.alpine
diff --git a/.github/workflows/docker.yml b/.github/workflows/docker.yml
index 18d055627f..adb87f3a5d 100644
--- a/.github/workflows/docker.yml
+++ b/.github/workflows/docker.yml
@@ -73,7 +73,7 @@ jobs:
# https://github.com/docker/build-push-action
- name: Build and push 'snipe-it' image
id: docker_build
- uses: docker/build-push-action@v5
+ uses: docker/build-push-action@v6
with:
context: .
file: ./Dockerfile
diff --git a/.github/workflows/tests-mysql.yml b/.github/workflows/tests-mysql.yml
index 4731585837..737a86dca3 100644
--- a/.github/workflows/tests-mysql.yml
+++ b/.github/workflows/tests-mysql.yml
@@ -25,9 +25,9 @@ jobs:
fail-fast: false
matrix:
php-version:
- - "7.4"
- - "8.0"
- - "8.1.1"
+ - "8.1"
+ - "8.2"
+ - "8.3"
name: PHP ${{ matrix.php-version }}
@@ -58,11 +58,17 @@ jobs:
- name: Install Dependencies
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
- - name: Generate key
- run: php artisan key:generate
-
- - name: Directory Permissions
- run: chmod -R 777 storage bootstrap/cache
+ - name: Setup Laravel
+ env:
+ DB_CONNECTION: mysql
+ DB_DATABASE: snipeit
+ DB_PORT: ${{ job.services.mysql.ports[3306] }}
+ DB_USERNAME: root
+ run: |
+ php artisan key:generate
+ php artisan migrate --force
+ php artisan passport:install
+ chmod -R 777 storage bootstrap/cache
- name: Execute tests (Unit and Feature tests) via PHPUnit
env:
diff --git a/.github/workflows/tests-postgres.yml b/.github/workflows/tests-postgres.yml
new file mode 100644
index 0000000000..0c361511b8
--- /dev/null
+++ b/.github/workflows/tests-postgres.yml
@@ -0,0 +1,77 @@
+name: Tests in Postgres
+
+on: workflow_dispatch
+
+jobs:
+ tests:
+ runs-on: ubuntu-latest
+
+ services:
+ postgresql:
+ image: postgres
+ env:
+ POSTGRES_DB: snipeit
+ POSTGRES_USER: snipeit
+ POSTGRES_PASSWORD: password
+ ports:
+ - 5432:5432
+ options: --health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3
+
+ strategy:
+ fail-fast: false
+ matrix:
+ php-version:
+ - "8.1"
+ - "8.2"
+ - "8.3"
+
+ name: PHP ${{ matrix.php-version }}
+
+ steps:
+ - uses: shivammathur/setup-php@v2
+ with:
+ php-version: "${{ matrix.php-version }}"
+ coverage: none
+
+ - uses: actions/checkout@v4
+
+ - name: Get Composer Cache Directory
+ id: composer-cache
+ run: |
+ echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
+ - uses: actions/cache@v4
+ with:
+ path: ${{ steps.composer-cache.outputs.dir }}
+ key: ${{ runner.os }}-${{ matrix.php-version }}-composer-${{ hashFiles('**/composer.lock') }}
+ restore-keys: |
+ ${{ runner.os }}-composer-
+
+ - name: Copy .env
+ run: |
+ cp -v .env.testing.example .env
+ cp -v .env.testing.example .env.testing
+
+ - name: Install Dependencies
+ run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
+
+ - name: Setup Laravel
+ env:
+ DB_CONNECTION: pgsql
+ DB_DATABASE: snipeit
+ DB_PORT: ${{ job.services.postgresql.ports[5432] }}
+ DB_USERNAME: snipeit
+ DB_PASSWORD: password
+ run: |
+ php artisan key:generate
+ php artisan migrate --force
+ php artisan passport:install
+ chmod -R 777 storage bootstrap/cache
+
+ - name: Execute tests (Unit and Feature tests) via PHPUnit
+ env:
+ DB_CONNECTION: pgsql
+ DB_DATABASE: snipeit
+ DB_PORT: ${{ job.services.postgresql.ports[5432] }}
+ DB_USERNAME: snipeit
+ DB_PASSWORD: password
+ run: php artisan test --parallel
diff --git a/.github/workflows/tests-sqlite.yml b/.github/workflows/tests-sqlite.yml
index 405dc92134..49c7c92d8e 100644
--- a/.github/workflows/tests-sqlite.yml
+++ b/.github/workflows/tests-sqlite.yml
@@ -49,6 +49,9 @@ jobs:
- name: Generate key
run: php artisan key:generate
+ - name: Setup Passport
+ run: php artisan passport:keys
+
- name: Directory Permissions
run: chmod -R 777 storage bootstrap/cache
diff --git a/.nvmrc b/.nvmrc
index 27bbca7450..8ddbc0c64a 100644
--- a/.nvmrc
+++ b/.nvmrc
@@ -1 +1 @@
-v12.22.1
+v18.16.0
diff --git a/.upgrade_requirements.json b/.upgrade_requirements.json
index 6fe066f8ea..53d7337b62 100644
--- a/.upgrade_requirements.json
+++ b/.upgrade_requirements.json
@@ -3,8 +3,8 @@
"DOC2": "In other words, what you see locally are the requirements for your _current_ install",
"DOC3": "Please don't rely on these versions for planning upgrades unless you've fetched the most recent version",
"DOC4": "You should really just ignore it and run upgrade.php. Really",
- "php_min_version": "7.4.0",
- "php_max_major_minor": "8.1",
- "php_max_wontwork": "8.2.0",
- "current_snipeit_version": "6.3"
+ "php_min_version": "8.1.0",
+ "php_max_major_minor": "8.3",
+ "php_max_wontwork": "8.4.0",
+ "current_snipeit_version": "7.0"
}
diff --git a/CONTRIBUTORS.md b/CONTRIBUTORS.md
index afaad9a7a6..5d7fe25ff7 100644
--- a/CONTRIBUTORS.md
+++ b/CONTRIBUTORS.md
@@ -1,444 +1,57 @@
Thanks goes to all of these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)) who have helped Snipe-IT get this far:
-
-
-
-
-
-
-
+| [
snipe](http://www.snipe.net)
[💻](https://github.com/snipe/snipe-it/commits?author=snipe "Code") [🚇](#infra-snipe "Infrastructure (Hosting, Build-Tools, etc)") [📖](https://github.com/snipe/snipe-it/commits?author=snipe "Documentation") [⚠️](https://github.com/snipe/snipe-it/commits?author=snipe "Tests") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Asnipe "Bug reports") [🎨](#design-snipe "Design") [👀](#review-snipe "Reviewed Pull Requests") | [
Brady Wetherington](http://www.uberbrady.com)
[💻](https://github.com/snipe/snipe-it/commits?author=uberbrady "Code") [📖](https://github.com/snipe/snipe-it/commits?author=uberbrady "Documentation") [🚇](#infra-uberbrady "Infrastructure (Hosting, Build-Tools, etc)") [👀](#review-uberbrady "Reviewed Pull Requests") | [
Daniel Meltzer](https://github.com/dmeltzer)
[💻](https://github.com/snipe/snipe-it/commits?author=dmeltzer "Code") [⚠️](https://github.com/snipe/snipe-it/commits?author=dmeltzer "Tests") [📖](https://github.com/snipe/snipe-it/commits?author=dmeltzer "Documentation") | [
Michael T](http://www.tuckertechonline.com)
[💻](https://github.com/snipe/snipe-it/commits?author=mtucker6784 "Code") | [
madd15](https://github.com/madd15)
[📖](https://github.com/snipe/snipe-it/commits?author=madd15 "Documentation") [💬](#question-madd15 "Answering Questions") | [
Vincent Sposato](https://github.com/vsposato)
[💻](https://github.com/snipe/snipe-it/commits?author=vsposato "Code") | [
Andrea Bergamasco](https://github.com/vjandrea)
[💻](https://github.com/snipe/snipe-it/commits?author=vjandrea "Code") |
+| :---: | :---: | :---: | :---: | :---: | :---: | :---: |
+| [
Karol](https://github.com/kpawelski)
[🌍](#translation-kpawelski "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=kpawelski "Code") | [
morph027](http://blog.morph027.de/)
[💻](https://github.com/snipe/snipe-it/commits?author=morph027 "Code") | [
fvleminckx](https://github.com/fvleminckx)
[🚇](#infra-fvleminckx "Infrastructure (Hosting, Build-Tools, etc)") | [
itsupportcmsukorg](https://github.com/itsupportcmsukorg)
[💻](https://github.com/snipe/snipe-it/commits?author=itsupportcmsukorg "Code") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Aitsupportcmsukorg "Bug reports") | [
Frank](https://override.io)
[💻](https://github.com/snipe/snipe-it/commits?author=base-zero "Code") | [
Deleted user](https://github.com/ghost)
[🌍](#translation-ghost "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=ghost "Code") | [
tiagom62](https://github.com/tiagom62)
[💻](https://github.com/snipe/snipe-it/commits?author=tiagom62 "Code") [🚇](#infra-tiagom62 "Infrastructure (Hosting, Build-Tools, etc)") |
+| [
Ryan Stafford](https://github.com/rystaf)
[💻](https://github.com/snipe/snipe-it/commits?author=rystaf "Code") | [
Eammon Hanlon](https://github.com/ehanlon)
[💻](https://github.com/snipe/snipe-it/commits?author=ehanlon "Code") | [
zjean](https://github.com/zjean)
[💻](https://github.com/snipe/snipe-it/commits?author=zjean "Code") | [
Matthias Frei](http://www.frei.media)
[💻](https://github.com/snipe/snipe-it/commits?author=FREImedia "Code") | [
opsydev](https://github.com/opsydev)
[💻](https://github.com/snipe/snipe-it/commits?author=opsydev "Code") | [
Daniel Dreier](http://www.ddreier.com)
[💻](https://github.com/snipe/snipe-it/commits?author=ddreier "Code") | [
Nikolai Prokoschenko](http://rassie.org)
[💻](https://github.com/snipe/snipe-it/commits?author=rassie "Code") |
+| [
Drew](https://github.com/YetAnotherCodeMonkey)
[💻](https://github.com/snipe/snipe-it/commits?author=YetAnotherCodeMonkey "Code") | [
Walter](https://github.com/merid14)
[💻](https://github.com/snipe/snipe-it/commits?author=merid14 "Code") | [
Petr Baloun](https://github.com/balous)
[💻](https://github.com/snipe/snipe-it/commits?author=balous "Code") | [
reidblomquist](https://github.com/reidblomquist)
[📖](https://github.com/snipe/snipe-it/commits?author=reidblomquist "Documentation") | [
Mathieu Kooiman](https://github.com/mathieuk)
[💻](https://github.com/snipe/snipe-it/commits?author=mathieuk "Code") | [
csayre](https://github.com/csayre)
[📖](https://github.com/snipe/snipe-it/commits?author=csayre "Documentation") | [
Adam Dunson](https://github.com/adamdunson)
[💻](https://github.com/snipe/snipe-it/commits?author=adamdunson "Code") |
+| [
Hereward](https://github.com/thehereward)
[💻](https://github.com/snipe/snipe-it/commits?author=thehereward "Code") | [
swoopdk](https://github.com/swoopdk)
[💻](https://github.com/snipe/snipe-it/commits?author=swoopdk "Code") | [
Abdullah Alansari](https://linkedin.com/in/ahimta)
[💻](https://github.com/snipe/snipe-it/commits?author=Ahimta "Code") | [
Micael Rodrigues](https://github.com/MicaelRodrigues)
[💻](https://github.com/snipe/snipe-it/commits?author=MicaelRodrigues "Code") | [
Patrick Gallagher](http://macadmincorner.com)
[📖](https://github.com/snipe/snipe-it/commits?author=patgmac "Documentation") | [
Miliamber](https://github.com/Miliamber)
[💻](https://github.com/snipe/snipe-it/commits?author=Miliamber "Code") | [
hawk554](https://github.com/hawk554)
[💻](https://github.com/snipe/snipe-it/commits?author=hawk554 "Code") |
+| [
Justin Kerr](http://jbirdkerr.net)
[💻](https://github.com/snipe/snipe-it/commits?author=jbirdkerr "Code") | [
Ira W. Snyder](http://www.irasnyder.com/devel/)
[📖](https://github.com/snipe/snipe-it/commits?author=irasnyd "Documentation") | [
Aladin Alaily](https://github.com/aalaily)
[💻](https://github.com/snipe/snipe-it/commits?author=aalaily "Code") | [
Chase Hansen](https://github.com/kobie-chasehansen)
[💻](https://github.com/snipe/snipe-it/commits?author=kobie-chasehansen "Code") [💬](#question-kobie-chasehansen "Answering Questions") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3Akobie-chasehansen "Bug reports") | [
IDM Helpdesk](https://github.com/IDM-Helpdesk)
[💻](https://github.com/snipe/snipe-it/commits?author=IDM-Helpdesk "Code") | [
Kai](http://balticer.de)
[💻](https://github.com/snipe/snipe-it/commits?author=balticer "Code") | [
Michael Daniels](http://www.michaeldaniels.me)
[💻](https://github.com/snipe/snipe-it/commits?author=mdaniels5757 "Code") |
+| [
Tom Castleman](http://tomcastleman.me)
[💻](https://github.com/snipe/snipe-it/commits?author=tomcastleman "Code") | [
Daniel Nemanic](https://github.com/DanielNemanic)
[💻](https://github.com/snipe/snipe-it/commits?author=DanielNemanic "Code") | [
SouthWolf](https://github.com/southwolf)
[💻](https://github.com/snipe/snipe-it/commits?author=southwolf "Code") | [
Ivar Nesje](https://github.com/ivarne)
[💻](https://github.com/snipe/snipe-it/commits?author=ivarne "Code") | [
Jérémy Benoist](http://www.j0k3r.net)
[📖](https://github.com/snipe/snipe-it/commits?author=j0k3r "Documentation") | [
Chris Leathley](https://github.com/cleathley)
[🚇](#infra-cleathley "Infrastructure (Hosting, Build-Tools, etc)") | [
splaer](https://github.com/splaer)
[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Asplaer "Bug reports") [💻](https://github.com/snipe/snipe-it/commits?author=splaer "Code") |
+| [
Joe Ferguson](http://www.joeferguson.me)
[💻](https://github.com/snipe/snipe-it/commits?author=svpernova09 "Code") | [
diwanicki](https://github.com/diwanicki)
[💻](https://github.com/snipe/snipe-it/commits?author=diwanicki "Code") [📖](https://github.com/snipe/snipe-it/commits?author=diwanicki "Documentation") | [
Lee Thoong Ching](https://github.com/pakkua80)
[📖](https://github.com/snipe/snipe-it/commits?author=pakkua80 "Documentation") [💻](https://github.com/snipe/snipe-it/commits?author=pakkua80 "Code") | [
Marek Šuppa](http://shu.io)
[💻](https://github.com/snipe/snipe-it/commits?author=mrshu "Code") | [
Juan J. Martinez](https://github.com/mizar1616)
[🌍](#translation-mizar1616 "Translation") | [
R Ryan Dial](https://github.com/rrdial)
[🌍](#translation-rrdial "Translation") | [
Andrej Manduch](https://github.com/burlito)
[📖](https://github.com/snipe/snipe-it/commits?author=burlito "Documentation") |
+| [
Jay Richards](http://www.cordeos.com)
[💻](https://github.com/snipe/snipe-it/commits?author=technogenus "Code") | [
Alexander Innes](https://necurity.co.uk)
[💻](https://github.com/snipe/snipe-it/commits?author=leostat "Code") | [
Danny Garcia](https://buzzedword.codes)
[💻](https://github.com/snipe/snipe-it/commits?author=buzzedword "Code") | [
archpoint](https://github.com/archpoint)
[💻](https://github.com/snipe/snipe-it/commits?author=archpoint "Code") | [
Jake McGraw](http://www.jakemcgraw.com)
[💻](https://github.com/snipe/snipe-it/commits?author=jakemcgraw "Code") | [
FleischKarussel](https://github.com/FleischKarussel)
[📖](https://github.com/snipe/snipe-it/commits?author=FleischKarussel "Documentation") | [
Dylan Yi](https://github.com/feeva)
[💻](https://github.com/snipe/snipe-it/commits?author=feeva "Code") |
+| [
Gil Rutkowski](http://FlashingCursor.com)
[💻](https://github.com/snipe/snipe-it/commits?author=flashingcursor "Code") | [
Desmond Morris](http://www.desmondmorris.com)
[💻](https://github.com/snipe/snipe-it/commits?author=desmondmorris "Code") | [
Nick Peelman](http://peelman.us)
[💻](https://github.com/snipe/snipe-it/commits?author=peelman "Code") | [
Abraham Vegh](https://abrahamvegh.com)
[💻](https://github.com/snipe/snipe-it/commits?author=abrahamvegh "Code") | [
Mohamed Rashid](https://github.com/rashivkp)
[📖](https://github.com/snipe/snipe-it/commits?author=rashivkp "Documentation") | [
Kasey](http://hinchk.github.io)
[💻](https://github.com/snipe/snipe-it/commits?author=HinchK "Code") | [
Brett](https://github.com/BrettFagerlund)
[⚠️](https://github.com/snipe/snipe-it/commits?author=BrettFagerlund "Tests") |
+| [
Jason Spriggs](http://jasonspriggs.com)
[💻](https://github.com/snipe/snipe-it/commits?author=jasonspriggs "Code") | [
Nate Felton](http://n8felton.wordpress.com)
[💻](https://github.com/snipe/snipe-it/commits?author=n8felton "Code") | [
Manasses Ferreira](http://homepages.dcc.ufmg.br/~manassesferreira)
[💻](https://github.com/snipe/snipe-it/commits?author=manassesferreira "Code") | [
Steve](https://github.com/steveelwood)
[⚠️](https://github.com/snipe/snipe-it/commits?author=steveelwood "Tests") | [
matc](http://twitter.com/matc)
[⚠️](https://github.com/snipe/snipe-it/commits?author=matc "Tests") | [
Cole R. Davis](http://www.davisracingteam.com)
[⚠️](https://github.com/snipe/snipe-it/commits?author=VanillaNinjaD "Tests") | [
gibsonjoshua55](https://github.com/gibsonjoshua55)
[💻](https://github.com/snipe/snipe-it/commits?author=gibsonjoshua55 "Code") |
+| [
Robin Temme](https://github.com/zwerch)
[💻](https://github.com/snipe/snipe-it/commits?author=zwerch "Code") | [
Iman](https://github.com/imanghafoori1)
[💻](https://github.com/snipe/snipe-it/commits?author=imanghafoori1 "Code") | [
Richard Hofman](https://github.com/richardhofman6)
[💻](https://github.com/snipe/snipe-it/commits?author=richardhofman6 "Code") | [
gizzmojr](https://github.com/gizzmojr)
[💻](https://github.com/snipe/snipe-it/commits?author=gizzmojr "Code") | [
Jenny Li](https://github.com/imjennyli)
[📖](https://github.com/snipe/snipe-it/commits?author=imjennyli "Documentation") | [
Geoff Young](https://github.com/GeoffYoung)
[💻](https://github.com/snipe/snipe-it/commits?author=GeoffYoung "Code") | [
Elliot Blackburn](http://www.elliotblackburn.com)
[📖](https://github.com/snipe/snipe-it/commits?author=BlueHatbRit "Documentation") |
+| [
Tõnis Ormisson](http://andmemasin.eu)
[💻](https://github.com/snipe/snipe-it/commits?author=TonisOrmisson "Code") | [
Nicolai Essig](http://www.nicolai-essig.de)
[💻](https://github.com/snipe/snipe-it/commits?author=thakilla "Code") | [
Danielle](https://github.com/techincolor)
[📖](https://github.com/snipe/snipe-it/commits?author=techincolor "Documentation") | [
Lawrence](https://github.com/TheVakman)
[⚠️](https://github.com/snipe/snipe-it/commits?author=TheVakman "Tests") [🐛](https://github.com/snipe/snipe-it/issues?q=author%3ATheVakman "Bug reports") | [
uknzaeinozpas](https://github.com/uknzaeinozpas)
[⚠️](https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas "Tests") [💻](https://github.com/snipe/snipe-it/commits?author=uknzaeinozpas "Code") | [
Ryan](https://github.com/Gelob)
[📖](https://github.com/snipe/snipe-it/commits?author=Gelob "Documentation") | [
vcordes79](https://github.com/vcordes79)
[💻](https://github.com/snipe/snipe-it/commits?author=vcordes79 "Code") |
+| [
fordster78](https://github.com/fordster78)
[💻](https://github.com/snipe/snipe-it/commits?author=fordster78 "Code") | [
CronKz](https://github.com/CronKz)
[💻](https://github.com/snipe/snipe-it/commits?author=CronKz "Code") [🌍](#translation-CronKz "Translation") | [
Tim Bishop](https://github.com/tdb)
[💻](https://github.com/snipe/snipe-it/commits?author=tdb "Code") | [
Sean McIlvenna](https://www.seanmcilvenna.com)
[💻](https://github.com/snipe/snipe-it/commits?author=seanmcilvenna "Code") | [
cepacs](https://github.com/cepacs)
[🐛](https://github.com/snipe/snipe-it/issues?q=author%3Acepacs "Bug reports") [📖](https://github.com/snipe/snipe-it/commits?author=cepacs "Documentation") | [
lea-mink](https://github.com/lea-mink)
[💻](https://github.com/snipe/snipe-it/commits?author=lea-mink "Code") | [
Hannah Tinkler](https://github.com/hannahtinkler)
[💻](https://github.com/snipe/snipe-it/commits?author=hannahtinkler "Code") |
+| [
Doeke Zanstra](https://github.com/doekman)
[💻](https://github.com/snipe/snipe-it/commits?author=doekman "Code") | [
Djamon Staal](https://www.sdhd.nl/)
[💻](https://github.com/snipe/snipe-it/commits?author=SjamonDaal "Code") | [
Earl Ramirez](https://github.com/EarlRamirez)
[💻](https://github.com/snipe/snipe-it/commits?author=EarlRamirez "Code") | [
Richard Ray Thomas](https://github.com/RichardRay)
[💻](https://github.com/snipe/snipe-it/commits?author=RichardRay "Code") | [
Ryan Kuba](https://www.taisun.io/)
[💻](https://github.com/snipe/snipe-it/commits?author=thelamer "Code") | [
Brian Monroe](https://github.com/ParadoxGuitarist)
[💻](https://github.com/snipe/snipe-it/commits?author=ParadoxGuitarist "Code") | [
plexorama](https://github.com/plexorama)
[💻](https://github.com/snipe/snipe-it/commits?author=plexorama "Code") |
+| [
Till Deeke](https://tilldeeke.de)
[💻](https://github.com/snipe/snipe-it/commits?author=tilldeeke "Code") | [
5quirrel](https://github.com/5quirrel)
[💻](https://github.com/snipe/snipe-it/commits?author=5quirrel "Code") | [
Jason](https://github.com/jasonlshelton)
[💻](https://github.com/snipe/snipe-it/commits?author=jasonlshelton "Code") | [
Antti](https://github.com/chemfy)
[💻](https://github.com/snipe/snipe-it/commits?author=chemfy "Code") | [
DeusMaximus](https://github.com/DeusMaximus)
[💻](https://github.com/snipe/snipe-it/commits?author=DeusMaximus "Code") | [
a-royal](https://github.com/A-ROYAL)
[🌍](#translation-A-ROYAL "Translation") | [
Alberto Aldrigo](https://github.com/albertoaldrigo)
[🌍](#translation-albertoaldrigo "Translation") |
+| [
Alex Stanev](http://alex.stanev.org/blog)
[🌍](#translation-RealEnder "Translation") | [
Andreas Rehm](http://devel.itsolution2.de)
[🌍](#translation-sirrus "Translation") | [
Andreas Erhard](https://github.com/xelan)
[🌍](#translation-xelan "Translation") | [
Andrés Vanegas Jiménez](https://github.com/angeldeejay)
[🌍](#translation-angeldeejay "Translation") | [
Antonio Schiavon](https://github.com/aschiavon91)
[🌍](#translation-aschiavon91 "Translation") | [
benunter](https://github.com/benunter)
[🌍](#translation-benunter "Translation") | [
Borys Żmuda](http://catweb24.pl)
[🌍](#translation-rudashi "Translation") |
+| [
chibacityblues](https://github.com/chibacityblues)
[🌍](#translation-chibacityblues "Translation") | [
Chien Wei Lin](https://github.com/cwlin0416)
[🌍](#translation-cwlin0416 "Translation") | [
Christian Schuster](https://github.com/Againstreality)
[🌍](#translation-Againstreality "Translation") | [
Christian Stefanus](http://chriss.webhostid.com)
[🌍](#translation-kopi-item "Translation") | [
wxcafé](http://wxcafe.net)
[🌍](#translation-wxcafe "Translation") | [
dpyroc](https://github.com/dpyroc)
[🌍](#translation-dpyroc "Translation") | [
Daniel Friedlmaier](http://www.friedlmaier.net)
[🌍](#translation-da-friedl "Translation") |
+| [
Daniel Heene](https://github.com/danielheene)
[🌍](#translation-danielheene "Translation") | [
danielcb](https://github.com/danielcb)
[🌍](#translation-danielcb "Translation") | [
Dominik Senti](https://github.com/dominiksenti)
[🌍](#translation-dominiksenti "Translation") | [
Eric Gautheron](http://www.konectik.com)
[🌍](#translation-EpixFr "Translation") | [
Erlend Pilø](https://erlpil.com)
[🌍](#translation-Erlpil "Translation") | [
Fabio Rapposelli](http://fabio.technology)
[🌍](#translation-frapposelli "Translation") | [
Felipe Barros](https://github.com/fgbs)
[🌍](#translation-fgbs "Translation") |
+| [
Fernando Possebon](https://github.com/possebon)
[🌍](#translation-possebon "Translation") | [
gdraque](https://github.com/gdraque)
[🌍](#translation-gdraque "Translation") | [
Georg Wallisch](https://github.com/georgwallisch)
[🌍](#translation-georgwallisch "Translation") | [
Gerardo Robles](https://github.com/jgroblesr85)
[🌍](#translation-jgroblesr85 "Translation") | [
Gluek](https://t.me/Gluek)
[🌍](#translation-mrgluek "Translation") | [
AdnanAbuShahad](https://github.com/AdnanAbuShahad)
[🌍](#translation-AdnanAbuShahad "Translation") | [
Hafidzi My](https://hafidzi.my)
[🌍](#translation-hafidzi "Translation") |
+| [
Harim Park](https://github.com/fofwisdom)
[🌍](#translation-fofwisdom "Translation") | [
Henrik Kentsson](http://www.kentsson.se)
[🌍](#translation-Kentsson "Translation") | [
Husnul Yaqien](https://github.com/husnulyaqien)
[🌍](#translation-husnulyaqien "Translation") | [
Ibrahim](http://abaalkhail.org)
[🌍](#translation-abaalkh "Translation") | [
igolman](https://github.com/igolman)
[🌍](#translation-igolman "Translation") | [
itangiang](https://github.com/itangiang)
[🌍](#translation-itangiang "Translation") | [
jarby1211](https://github.com/jarby1211)
[🌍](#translation-jarby1211 "Translation") |
+| [
Jhonn Willker](http://jwillker.com)
[🌍](#translation-JohnWillker "Translation") | [
Jose](https://github.com/joxelito94)
[🌍](#translation-joxelito94 "Translation") | [
laopangzi](https://github.com/laopangzi)
[🌍](#translation-laopangzi "Translation") | [
Lars Strojny](http://usrportage.de)
[🌍](#translation-lstrojny "Translation") | [
MarcosBL](http://twitter.com/marcosbl)
[🌍](#translation-MarcosBL "Translation") | [
marie joy cajes](https://github.com/mariejoyacajes)
[🌍](#translation-mariejoyacajes "Translation") | [
Mark S. Johansen](http://www.markjohansen.dk)
[🌍](#translation-msjohansen "Translation") |
+| [
Martin Stub](http://martinstub.dk)
[🌍](#translation-stubben "Translation") | [
Meyer Flavio](https://github.com/meyerf99)
[🌍](#translation-meyerf99 "Translation") | [
Micael Rodrigues](https://github.com/MicaelRodrigues)
[🌍](#translation-MicaelRodrigues "Translation") | [
Mikael Rasmussen](http://rubixy.com/)
[🌍](#translation-mikaelssen "Translation") | [
IxFail](https://github.com/IxFail)
[🌍](#translation-IxFail "Translation") | [
Mohammed Fota](http://www.mohammedfota.com)
[🌍](#translation-MohammedFota "Translation") | [
Moayad Alserihi](https://github.com/omego)
[🌍](#translation-omego "Translation") |
+| [
saymd](https://github.com/saymd)
[🌍](#translation-saymd "Translation") | [
Patrik Larsson](https://nordsken.se)
[🌍](#translation-pooot "Translation") | [
drcryo](https://github.com/drcryo)
[🌍](#translation-drcryo "Translation") | [
pawel1615](https://github.com/pawel1615)
[🌍](#translation-pawel1615 "Translation") | [
bodrovics](https://github.com/bodrovics)
[🌍](#translation-bodrovics "Translation") | [
priatna](https://github.com/priatna)
[🌍](#translation-priatna "Translation") | [
Fan Jiang](https://amayume.net)
[🌍](#translation-ProfFan "Translation") |
+| [
ragnarcx](https://github.com/ragnarcx)
[🌍](#translation-ragnarcx "Translation") | [
Rein van Haaren](http://www.reinvanhaaren.nl/)
[🌍](#translation-reinvanhaaren "Translation") | [
Teguh Dwicaksana](http://dheche.songolimo.net)
[🌍](#translation-dheche "Translation") | [
fraccie](https://github.com/FRaccie)
[🌍](#translation-FRaccie "Translation") | [
vinzruzell](https://github.com/vinzruzell)
[🌍](#translation-vinzruzell "Translation") | [
Kevin Austin](http://kevinaustin.com)
[🌍](#translation-vipsystem "Translation") | [
Wira Sandy](http://azuraweb.xyz)
[🌍](#translation-wira-sandy "Translation") |
+| [
Илья](https://github.com/GrayHoax)
[🌍](#translation-GrayHoax "Translation") | [
GodUseVPN](https://github.com/godusevpn)
[🌍](#translation-godusevpn "Translation") | [
周周](https://github.com/EngrZhou)
[🌍](#translation-EngrZhou "Translation") | [
Sam](https://github.com/takuy)
[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [
Azerothian](https://www.illisian.com.au)
[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | [
Wes Hulette](http://macfoo.wordpress.com/)
[💻](https://github.com/snipe/snipe-it/commits?author=jwhulette "Code") | [
patrict](https://github.com/patrict)
[💻](https://github.com/snipe/snipe-it/commits?author=patrict "Code") |
+| [
Dmitriy Minaev](https://github.com/VELIKII-DIVAN)
[💻](https://github.com/snipe/snipe-it/commits?author=VELIKII-DIVAN "Code") | [
liquidhorse](https://github.com/liquidhorse)
[💻](https://github.com/snipe/snipe-it/commits?author=liquidhorse "Code") | [
Jordi Boggiano](https://seld.be/)
[💻](https://github.com/snipe/snipe-it/commits?author=Seldaek "Code") | [
Ivan Nieto](https://github.com/inietov)
[💻](https://github.com/snipe/snipe-it/commits?author=inietov "Code") | [
Ben RUBSON](https://github.com/benrubson)
[💻](https://github.com/snipe/snipe-it/commits?author=benrubson "Code") | [
NMathar](https://github.com/NMathar)
[💻](https://github.com/snipe/snipe-it/commits?author=NMathar "Code") | [
Steffen](https://github.com/smb)
[💻](https://github.com/snipe/snipe-it/commits?author=smb "Code") |
+| [
Sxderp](https://github.com/Sxderp)
[💻](https://github.com/snipe/snipe-it/commits?author=Sxderp "Code") | [
fanta8897](https://github.com/fanta8897)
[💻](https://github.com/snipe/snipe-it/commits?author=fanta8897 "Code") | [
Andrey Bolonin](https://andreybolonin.com/phpconsulting/)
[💻](https://github.com/snipe/snipe-it/commits?author=andreybolonin "Code") | [
shinayoshi](http://www.shinayoshi.net/)
[💻](https://github.com/snipe/snipe-it/commits?author=shinayoshi "Code") | [
Hubert](https://github.com/reuser)
[💻](https://github.com/snipe/snipe-it/commits?author=reuser "Code") | [
KeenRivals](https://brashear.me)
[💻](https://github.com/snipe/snipe-it/commits?author=KeenRivals "Code") | [
omyno](https://github.com/omyno)
[💻](https://github.com/snipe/snipe-it/commits?author=omyno "Code") |
+| [
Evgeny](https://github.com/jackka)
[💻](https://github.com/snipe/snipe-it/commits?author=jackka "Code") | [
Colin Campbell](https://digitalist.se)
[💻](https://github.com/snipe/snipe-it/commits?author=colin-campbell "Code") | [
Ľubomír Kučera](https://github.com/lubo)
[💻](https://github.com/snipe/snipe-it/commits?author=lubo "Code") | [
Martin Meredith](https://www.sourceguru.net)
[💻](https://github.com/snipe/snipe-it/commits?author=Mezzle "Code") | [
Tim Farmer](https://github.com/timothyfarmer)
[💻](https://github.com/snipe/snipe-it/commits?author=timothyfarmer "Code") | [
Marián Skrip](https://github.com/mskrip)
[💻](https://github.com/snipe/snipe-it/commits?author=mskrip "Code") | [
Godfrey Martinez](https://github.com/Godmartinz)
[💻](https://github.com/snipe/snipe-it/commits?author=Godmartinz "Code") |
+| [
bigtreeEdo](https://github.com/bigtreeEdo)
[💻](https://github.com/snipe/snipe-it/commits?author=bigtreeEdo "Code") | [
Colin McNeil](https://colinmcneil.me/)
[💻](https://github.com/snipe/snipe-it/commits?author=ColinMcNeil "Code") | [
JoKneeMo](https://github.com/JoKneeMo)
[💻](https://github.com/snipe/snipe-it/commits?author=JoKneeMo "Code") | [
Joshi](http://www.redbridge.se)
[💻](https://github.com/snipe/snipe-it/commits?author=joshi-redbridge "Code") | [
Anthony Burns](https://github.com/anthonypburns)
[💻](https://github.com/snipe/snipe-it/commits?author=anthonypburns "Code") | [
johnson-yi](https://github.com/johnson-yi)
[💻](https://github.com/snipe/snipe-it/commits?author=johnson-yi "Code") | [
Sanjay Govind](https://tangentmc.net)
[💻](https://github.com/snipe/snipe-it/commits?author=sanjay900 "Code") |
+| [
Peter Upfold](https://peter.upfold.org.uk/)
[💻](https://github.com/snipe/snipe-it/commits?author=PeterUpfold "Code") | [
Jared Biel](https://github.com/jbiel)
[💻](https://github.com/snipe/snipe-it/commits?author=jbiel "Code") | [
Dampfklon](https://github.com/dampfklon)
[💻](https://github.com/snipe/snipe-it/commits?author=dampfklon "Code") | [
Charles Hamilton](https://communityclosing.com)
[💻](https://github.com/snipe/snipe-it/commits?author=chamilton-ccn "Code") | [
Giuseppe Iannello](https://github.com/giannello)
[💻](https://github.com/snipe/snipe-it/commits?author=giannello "Code") | [
Peter Dave Hello](https://www.peterdavehello.org/)
[💻](https://github.com/snipe/snipe-it/commits?author=PeterDaveHello "Code") | [
sigmoidal](https://github.com/sigmoidal)
[💻](https://github.com/snipe/snipe-it/commits?author=sigmoidal "Code") |
+| [
Vincent Lainé](https://github.com/phenixdotnet)
[💻](https://github.com/snipe/snipe-it/commits?author=phenixdotnet "Code") | [
Lucas Pleß](http://www.lucas-pless.com)
[💻](https://github.com/snipe/snipe-it/commits?author=derlucas "Code") | [
Ian Littman](http://twitter.com/iansltx)
[💻](https://github.com/snipe/snipe-it/commits?author=iansltx "Code") | [
João Paulo](https://github.com/PauloLuna)
[💻](https://github.com/snipe/snipe-it/commits?author=PauloLuna "Code") | [
ThoBur](https://github.com/ThoBur)
[💻](https://github.com/snipe/snipe-it/commits?author=ThoBur "Code") | [
Alexander Chibrikin](http://phpprofi.ru/)
[💻](https://github.com/snipe/snipe-it/commits?author=alek13 "Code") | [
Anthony Winstanley](https://github.com/winstan)
[💻](https://github.com/snipe/snipe-it/commits?author=winstan "Code") |
+| [
Folke](https://github.com/fashberg)
[💻](https://github.com/snipe/snipe-it/commits?author=fashberg "Code") | [
Bennett Blodinger](https://github.com/benwa)
[💻](https://github.com/snipe/snipe-it/commits?author=benwa "Code") | [
NMC](https://nmc.dev)
[💻](https://github.com/snipe/snipe-it/commits?author=ncareau "Code") | [
andres-baller](https://github.com/andres-baller)
[💻](https://github.com/snipe/snipe-it/commits?author=andres-baller "Code") | [
sean-borg](https://github.com/sean-borg)
[💻](https://github.com/snipe/snipe-it/commits?author=sean-borg "Code") | [
EDVLeer](https://github.com/EDVLeer)
[💻](https://github.com/snipe/snipe-it/commits?author=EDVLeer "Code") | [
Kurokat](https://github.com/Kurokat)
[💻](https://github.com/snipe/snipe-it/commits?author=Kurokat "Code") |
+| [
Kevin Köllmann](https://www.kevinkoellmann.de)
[💻](https://github.com/snipe/snipe-it/commits?author=koelle25 "Code") | [
sw-mreyes](https://github.com/sw-mreyes)
[💻](https://github.com/snipe/snipe-it/commits?author=sw-mreyes "Code") | [
Joel Pittet](https://pittet.ca)
[💻](https://github.com/snipe/snipe-it/commits?author=joelpittet "Code") | [
Eli Young](https://elyscape.com)
[💻](https://github.com/snipe/snipe-it/commits?author=elyscape "Code") | [
Raell Dottin](https://github.com/raelldottin)
[💻](https://github.com/snipe/snipe-it/commits?author=raelldottin "Code") | [
Tom Misilo](https://github.com/misilot)
[💻](https://github.com/snipe/snipe-it/commits?author=misilot "Code") | [
David Davenne](http://david.davenne.be)
[💻](https://github.com/snipe/snipe-it/commits?author=JuustoMestari "Code") |
+| [
Mark Stenglein](https://markstenglein.com)
[💻](https://github.com/snipe/snipe-it/commits?author=ocelotsloth "Code") | [
ajsy](https://github.com/ajsy)
[💻](https://github.com/snipe/snipe-it/commits?author=ajsy "Code") | [
Jan Kiesewetter](https://github.com/t3easy)
[💻](https://github.com/snipe/snipe-it/commits?author=t3easy "Code") | [
Tetrachloromethane250](https://github.com/Tetrachloromethane250)
[💻](https://github.com/snipe/snipe-it/commits?author=Tetrachloromethane250 "Code") | [
Lars Kajes](https://www.kajes.se/)
[💻](https://github.com/snipe/snipe-it/commits?author=kajes "Code") | [
Joly0](https://github.com/Joly0)
[💻](https://github.com/snipe/snipe-it/commits?author=Joly0 "Code") | [
theburger](https://github.com/limeless)
[💻](https://github.com/snipe/snipe-it/commits?author=limeless "Code") |
+| [
David Valin Alonso](https://github.com/deivishome)
[💻](https://github.com/snipe/snipe-it/commits?author=deivishome "Code") | [
andreaci](https://github.com/andreaci)
[💻](https://github.com/snipe/snipe-it/commits?author=andreaci "Code") | [
Jelle Sebreghts](http://www.jellesebreghts.be)
[💻](https://github.com/snipe/snipe-it/commits?author=Jelle-S "Code") | [
Michael Pietsch](https://github.com/Skywalker-11)
| [
Masudul Haque Shihab](https://github.com/sh1hab)
[💻](https://github.com/snipe/snipe-it/commits?author=sh1hab "Code") | [
Supapong Areeprasertkul](http://www.freedomdive.com/)
[💻](https://github.com/snipe/snipe-it/commits?author=zybersup "Code") | [
Peter Sarossy](https://github.com/psarossy)
[💻](https://github.com/snipe/snipe-it/commits?author=psarossy "Code") |
+| [
Renee Margaret McConahy](https://github.com/nepella)
[💻](https://github.com/snipe/snipe-it/commits?author=nepella "Code") | [
JohnnyPicnic](https://github.com/JohnnyPicnic)
[💻](https://github.com/snipe/snipe-it/commits?author=JohnnyPicnic "Code") | [
markbrule](https://github.com/markbrule)
[💻](https://github.com/snipe/snipe-it/commits?author=markbrule "Code") | [
Mike Campbell](https://github.com/mikecmpbll)
[💻](https://github.com/snipe/snipe-it/commits?author=mikecmpbll "Code") | [
tbrconnect](https://github.com/tbrconnect)
[💻](https://github.com/snipe/snipe-it/commits?author=tbrconnect "Code") | [
kcoyo](https://github.com/kcoyo)
[💻](https://github.com/snipe/snipe-it/commits?author=kcoyo "Code") | [
Travis Miller](https://travismiller.com/)
[💻](https://github.com/snipe/snipe-it/commits?author=travismiller "Code") |
+| [
Evan Taylor](https://github.com/Delta5)
[💻](https://github.com/snipe/snipe-it/commits?author=Delta5 "Code") | [
Petri Asikainen](https://github.com/PetriAsi)
[💻](https://github.com/snipe/snipe-it/commits?author=PetriAsi "Code") | [
derdeagle](https://github.com/derdeagle)
[💻](https://github.com/snipe/snipe-it/commits?author=derdeagle "Code") | [
Mike Frysinger](https://wh0rd.org/)
[💻](https://github.com/snipe/snipe-it/commits?author=vapier "Code") | [
ALPHA](https://github.com/AL4AL)
[💻](https://github.com/snipe/snipe-it/commits?author=AL4AL "Code") | [
FliegenKLATSCH](https://www.ifern.de)
[💻](https://github.com/snipe/snipe-it/commits?author=FliegenKLATSCH "Code") | [
Jeremy Price](https://github.com/jerm)
[💻](https://github.com/snipe/snipe-it/commits?author=jerm "Code") |
+| [
Toreg87](https://github.com/Toreg87)
[💻](https://github.com/snipe/snipe-it/commits?author=Toreg87 "Code") | [
Matthew Nickson](https://github.com/Computroniks)
[💻](https://github.com/snipe/snipe-it/commits?author=Computroniks "Code") | [
Jethro Nederhof](https://jethron.id.au)
[💻](https://github.com/snipe/snipe-it/commits?author=jethron "Code") | [
Oskar Stenberg](https://github.com/01ste02)
[💻](https://github.com/snipe/snipe-it/commits?author=01ste02 "Code") | [
Robert-Azelis](https://github.com/Robert-Azelis)
[💻](https://github.com/snipe/snipe-it/commits?author=Robert-Azelis "Code") | [
Alexander William Smith](https://github.com/alwism)
[💻](https://github.com/snipe/snipe-it/commits?author=alwism "Code") | [
LEITWERK AG](https://www.leitwerk.de/)
[💻](https://github.com/snipe/snipe-it/commits?author=leitwerk-ag "Code") |
+| [
Adam](http://www.aboutcher.co.uk)
[💻](https://github.com/snipe/snipe-it/commits?author=adamboutcher "Code") | [
Ian](https://snksrv.com)
[💻](https://github.com/snipe/snipe-it/commits?author=sneak-it "Code") | [
Shao Yu-Lung (Allen)](http://blog.bestlong.idv.tw/)
[💻](https://github.com/snipe/snipe-it/commits?author=bestlong "Code") | [
Haxatron](https://github.com/Haxatron)
[💻](https://github.com/snipe/snipe-it/commits?author=Haxatron "Code") | [
PlaneNuts](https://github.com/PlaneNuts)
[💻](https://github.com/snipe/snipe-it/commits?author=PlaneNuts "Code") | [
Bradley Coudriet](http://bjcpgd.cias.rit.edu)
[💻](https://github.com/snipe/snipe-it/commits?author=exula "Code") | [
Dalton Durst](https://daltondur.st)
[💻](https://github.com/snipe/snipe-it/commits?author=UniversalSuperBox "Code") |
+| [
Alex Janes](https://adagiohealth.org)
[💻](https://github.com/snipe/snipe-it/commits?author=adagioajanes "Code") | [
Nuraeil](https://github.com/nuraeil)
[💻](https://github.com/snipe/snipe-it/commits?author=nuraeil "Code") | [
TenOfTens](https://github.com/TenOfTens)
[💻](https://github.com/snipe/snipe-it/commits?author=TenOfTens "Code") | [
waffle](https://ditisjens.be/)
[💻](https://github.com/snipe/snipe-it/commits?author=insert-waffle "Code") | [
Yevhenii Huzii](https://github.com/QveenSi)
[💻](https://github.com/snipe/snipe-it/commits?author=QveenSi "Code") | [
Achmad Fienan Rahardianto](https://github.com/veenone)
[💻](https://github.com/snipe/snipe-it/commits?author=veenone "Code") | [
Yevhenii Huzii](https://github.com/QveenSi)
[💻](https://github.com/snipe/snipe-it/commits?author=QveenSi "Code") |
+| [
Christian Weirich](https://github.com/chrisweirich)
[💻](https://github.com/snipe/snipe-it/commits?author=chrisweirich "Code") | [
denzfarid](https://github.com/denzfarid)
| [
ntbutler-nbcs](https://github.com/ntbutler-nbcs)
[💻](https://github.com/snipe/snipe-it/commits?author=ntbutler-nbcs "Code") | [
Naveen](https://naveensrinivasan.dev)
[💻](https://github.com/snipe/snipe-it/commits?author=naveensrinivasan "Code") | [
Mike Roquemore](https://github.com/mikeroq)
[💻](https://github.com/snipe/snipe-it/commits?author=mikeroq "Code") | [
Daniel Reeder](https://github.com/reederda)
[🌍](#translation-reederda "Translation") [🌍](#translation-reederda "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=reederda "Code") | [
vickyjaura183](https://github.com/vickyjaura183)
[💻](https://github.com/snipe/snipe-it/commits?author=vickyjaura183 "Code") |
+| [
Peace](https://github.com/julian-piehl)
[💻](https://github.com/snipe/snipe-it/commits?author=julian-piehl "Code") | [
Kyle Gordon](https://github.com/kylegordon)
[💻](https://github.com/snipe/snipe-it/commits?author=kylegordon "Code") | [
Katharina Drexel](http://www.bfh.ch)
[💻](https://github.com/snipe/snipe-it/commits?author=sunflowerbofh "Code") | [
David Sferruzza](https://david.sferruzza.fr/)
[💻](https://github.com/snipe/snipe-it/commits?author=dsferruzza "Code") | [
Rick Nelson](https://github.com/rnelsonee)
[💻](https://github.com/snipe/snipe-it/commits?author=rnelsonee "Code") | [
BasO12](https://github.com/BasO12)
[💻](https://github.com/snipe/snipe-it/commits?author=BasO12 "Code") | [
Vautia](https://github.com/Vautia)
[💻](https://github.com/snipe/snipe-it/commits?author=Vautia "Code") |
+| [
Chris Hartjes](http://www.littlehart.net/atthekeyboard)
[💻](https://github.com/snipe/snipe-it/commits?author=chartjes "Code") | [
geo-chen](https://github.com/geo-chen)
[💻](https://github.com/snipe/snipe-it/commits?author=geo-chen "Code") | [
Phan Nguyen](https://github.com/nh314)
[💻](https://github.com/snipe/snipe-it/commits?author=nh314 "Code") | [
Iisakki Jaakkola](https://github.com/StarlessNights)
[💻](https://github.com/snipe/snipe-it/commits?author=StarlessNights "Code") | [
Ikko Ashimine](https://bandism.net/)
[💻](https://github.com/snipe/snipe-it/commits?author=eltociear "Code") | [
Lukas Fehling](https://github.com/lukasfehling)
[💻](https://github.com/snipe/snipe-it/commits?author=lukasfehling "Code") | [
Fernando Almeida](https://github.com/fernando-almeida)
[💻](https://github.com/snipe/snipe-it/commits?author=fernando-almeida "Code") |
+| [
akemidx](https://github.com/akemidx)
[💻](https://github.com/snipe/snipe-it/commits?author=akemidx "Code") | [
Oguz Bilgic](http://oguz.site)
[💻](https://github.com/snipe/snipe-it/commits?author=oguzbilgic "Code") | [
Scooter Crawford](https://github.com/scoo73r)
[💻](https://github.com/snipe/snipe-it/commits?author=scoo73r "Code") | [
subdriven](https://github.com/subdriven)
[💻](https://github.com/snipe/snipe-it/commits?author=subdriven "Code") | [
Andrew Savinykh](https://github.com/AndrewSav)
[💻](https://github.com/snipe/snipe-it/commits?author=AndrewSav "Code") | [
Tadayuki Onishi](https://kenchan0130.github.io)
[💻](https://github.com/snipe/snipe-it/commits?author=kenchan0130 "Code") | [
Florian](https://github.com/floschoepfer)
[💻](https://github.com/snipe/snipe-it/commits?author=floschoepfer "Code") |
+| [
Spencer Long](http://spencerlong.com)
[💻](https://github.com/snipe/snipe-it/commits?author=spencerrlongg "Code") | [
Marcus Moore](https://github.com/marcusmoore)
[💻](https://github.com/snipe/snipe-it/commits?author=marcusmoore "Code") | [
Martin Meredith](https://github.com/Mezzle)
| [
dboth](http://dboth.de)
[💻](https://github.com/snipe/snipe-it/commits?author=dboth "Code") | [
Zachary Fleck](https://github.com/zacharyfleck)
[💻](https://github.com/snipe/snipe-it/commits?author=zacharyfleck "Code") | [
VIKAAS-A](https://github.com/vikaas-cyper)
[💻](https://github.com/snipe/snipe-it/commits?author=vikaas-cyper "Code") | [
Abdul Kareem](https://github.com/ak-piracha)
[💻](https://github.com/snipe/snipe-it/commits?author=ak-piracha "Code") |
+| [
NojoudAlshehri](https://github.com/NojoudAlshehri)
[💻](https://github.com/snipe/snipe-it/commits?author=NojoudAlshehri "Code") | [
Stefan Stidl](https://github.com/stefanstidlffg)
[💻](https://github.com/snipe/snipe-it/commits?author=stefanstidlffg "Code") | [
Quentin Aymard](https://github.com/qay21)
[💻](https://github.com/snipe/snipe-it/commits?author=qay21 "Code") | [
Grant Le Roux](https://github.com/cram42)
[💻](https://github.com/snipe/snipe-it/commits?author=cram42 "Code") | [
Bogdan](http://@singrity)
[💻](https://github.com/snipe/snipe-it/commits?author=Singrity "Code") | [
mmanjos](https://github.com/mmanjos)
[💻](https://github.com/snipe/snipe-it/commits?author=mmanjos "Code") | [
Abdelaziz Faki](https://azooz2014.github.io/)
[💻](https://github.com/snipe/snipe-it/commits?author=Azooz2014 "Code") |
+| [
bilias](https://github.com/bilias)
[💻](https://github.com/snipe/snipe-it/commits?author=bilias "Code") | [
coach1988](https://github.com/coach1988)
[💻](https://github.com/snipe/snipe-it/commits?author=coach1988 "Code") | [
MrM](https://github.com/mauro-miatello)
[💻](https://github.com/snipe/snipe-it/commits?author=mauro-miatello "Code") | [
koiakoia](https://github.com/koiakoia)
[💻](https://github.com/snipe/snipe-it/commits?author=koiakoia "Code") | [
Mustafa Online](https://github.com/mustafa-online)
[💻](https://github.com/snipe/snipe-it/commits?author=mustafa-online "Code") | [
franceslui](https://github.com/franceslui)
[💻](https://github.com/snipe/snipe-it/commits?author=franceslui "Code") | [
Q4kK](https://github.com/Q4kK)
[💻](https://github.com/snipe/snipe-it/commits?author=Q4kK "Code") |
+| [
squintfox](https://github.com/squintfox)
[💻](https://github.com/snipe/snipe-it/commits?author=squintfox "Code") | [
Jeff Clay](https://github.com/jeffclay)
[💻](https://github.com/snipe/snipe-it/commits?author=jeffclay "Code") | [
Phil J R](https://github.com/PP-JN-RL)
[💻](https://github.com/snipe/snipe-it/commits?author=PP-JN-RL "Code") | [
i_virus](https://www.corelight.com/)
[💻](https://github.com/snipe/snipe-it/commits?author=chandanchowdhury "Code") | [
Paul Grime](https://github.com/gitgrimbo)
[💻](https://github.com/snipe/snipe-it/commits?author=gitgrimbo "Code") | [
Lee Porte](https://leeporte.co.uk)
[💻](https://github.com/snipe/snipe-it/commits?author=LeePorte "Code") | [
BRYAN ](https://github.com/bryanlopezinc)
[💻](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Code") [⚠️](https://github.com/snipe/snipe-it/commits?author=bryanlopezinc "Tests") |
+| [
U-H-T](https://github.com/U-H-T)
[💻](https://github.com/snipe/snipe-it/commits?author=U-H-T "Code") | [
Matt Tyree](https://github.com/Tyree)
[📖](https://github.com/snipe/snipe-it/commits?author=Tyree "Documentation") | [
Florent Bervas](http://spoontux.net)
[💻](https://github.com/snipe/snipe-it/commits?author=FlorentDotMe "Code") | [
Daniel Albertsen](https://ditscheri.com)
[💻](https://github.com/snipe/snipe-it/commits?author=dbakan "Code") | [
r-xyz](https://github.com/r-xyz)
[💻](https://github.com/snipe/snipe-it/commits?author=r-xyz "Code") |
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
diff --git a/Dockerfile b/Dockerfile
index 88de52858b..bd363ccd18 100644
--- a/Dockerfile
+++ b/Dockerfile
@@ -105,7 +105,7 @@ RUN \
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.cert" "/var/www/html/storage/ldap_client_tls.cert" \
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.key" "/var/www/html/storage/ldap_client_tls.key" \
&& chown docker "/var/lib/snipeit/keys/" \
- && chown -h docker "/var/www/html/storage/" \
+ && chown -Rh docker "/var/www/html/storage/" \
&& chmod +x /var/www/html/artisan \
&& echo "Finished setting up application in /var/www/html"
diff --git a/README.md b/README.md
index b271d88c26..6d2c45ac71 100644
--- a/README.md
+++ b/README.md
@@ -1,18 +1,18 @@

-[](https://crowdin.com/project/snipe-it) [](https://hub.docker.com/r/snipe/snipe-it/) [](https://twitter.com/snipeitapp) [](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade) [](https://github.com/snipe/snipe-it/actions/workflows/tests.yml)
+[](https://crowdin.com/project/snipe-it) [](https://hub.docker.com/r/snipe/snipe-it/) [](https://twitter.com/snipeitapp) [](https://app.codacy.com/gh/snipe/snipe-it/dashboard?utm_source=gh&utm_medium=referral&utm_content=&utm_campaign=Badge_grade) [](https://github.com/snipe/snipe-it/actions/workflows/tests.yml)
[](#contributing) [](https://discord.gg/yZFtShAcKk)
## Snipe-IT - Open Source Asset Management System
This is a FOSS project for asset management in IT Operations. Knowing who has which laptop, when it was purchased in order to depreciate it correctly, handling software licenses, etc.
-It is built on [Laravel 8](http://laravel.com).
+It is built on [Laravel 10](http://laravel.com).
Snipe-IT is actively developed and we [release quite frequently](https://github.com/snipe/snipe-it/releases). ([Check out the live demo here](https://snipeitapp.com/demo/).)
> [!TIP]
-> __This is web-based software__. This means there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
+> __This is web-based software__. This means there is no executable file (aka no .exe files), and it must be run on a web server and accessed through a web browser. It runs on any Mac OSX, any flavor of Linux, as well as Windows, and we have a [Docker image](https://snipe-it.readme.io/docs/docker) available if that's what you're into.
-----
diff --git a/app.json b/app.json
index 97a81d4d7b..0bf523f5e4 100644
--- a/app.json
+++ b/app.json
@@ -38,7 +38,7 @@
"description": "The maximum number of search results that can be returned at one time.",
"value": "500"
},
- "MAIL_DRIVER": {
+ "MAIL_MAILER": {
"description": "Mail driver - Generally SMTP on Heroku - https://snipe-it.readme.io/docs/configuration#required-outgoing-mail-settings",
"value": "smtp"
},
@@ -58,9 +58,9 @@
"description": "SMTP Server Password",
"value": "YOURPASSWORD"
},
- "MAIL_ENCRYPTION": {
- "description": "Encryption protocol for email sending.",
- "value": "null"
+ "MAIL_TLS_VERIFY_PEER": {
+ "description": "Ensure validity of TLS certificate on remote mail server",
+ "value": true
},
"MAIL_FROM_ADDR": {
"description": "Email from address",
diff --git a/app/Console/Commands/GeneratePersonalAccessToken.php b/app/Console/Commands/GeneratePersonalAccessToken.php
index 098d9678ad..c5f531213c 100644
--- a/app/Console/Commands/GeneratePersonalAccessToken.php
+++ b/app/Console/Commands/GeneratePersonalAccessToken.php
@@ -7,7 +7,7 @@ use Illuminate\Console\Command;
use App\Models\User;
use Laravel\Passport\TokenRepository;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
-use DB;
+use Illuminate\Support\Facades\DB;
class GeneratePersonalAccessToken extends Command
{
diff --git a/app/Console/Commands/LdapSync.php b/app/Console/Commands/LdapSync.php
index 05f60ee4e1..845db27ef9 100755
--- a/app/Console/Commands/LdapSync.php
+++ b/app/Console/Commands/LdapSync.php
@@ -9,7 +9,7 @@ use App\Models\Setting;
use App\Models\Ldap;
use App\Models\User;
use App\Models\Location;
-use Log;
+use Illuminate\Support\Facades\Log;
class LdapSync extends Command
{
@@ -251,6 +251,7 @@ class LdapSync extends Command
// 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';
}
@@ -298,7 +299,7 @@ class LdapSync extends Command
try {
$ldap_manager = Ldap::findLdapUsers($item['manager'], -1, $this->option('filter'));
} catch (\Exception $e) {
- \Log::warning("Manager lookup caused an exception: " . $e->getMessage() . ". Falling back to direct username lookup");
+ Log::warning("Manager lookup caused an exception: " . $e->getMessage() . ". Falling back to direct username lookup");
// Hail-mary for Okta manager 'shortnames' - will only work if
// Okta configuration is using full email-address-style usernames
$ldap_manager = [
@@ -390,7 +391,7 @@ class LdapSync extends Command
$user->location_id = $location->id;
}
}
-
+ $location = null;
$user->ldap_import = 1;
$errors = '';
diff --git a/app/Console/Commands/LdapTroubleshooter.php b/app/Console/Commands/LdapTroubleshooter.php
index 8c28318866..5bb3cdd366 100644
--- a/app/Console/Commands/LdapTroubleshooter.php
+++ b/app/Console/Commands/LdapTroubleshooter.php
@@ -5,7 +5,7 @@ namespace App\Console\Commands;
use Illuminate\Console\Command;
use App\Models\Setting;
use Exception;
-use Crypt;
+use Illuminate\Support\Facades\Crypt;
/**
* Check if a given ip is in a network
@@ -160,7 +160,7 @@ class LdapTroubleshooter extends Command
$output[] = "-x";
$output[] = "-b ".escapeshellarg($settings->ldap_basedn);
$output[] = "-D ".escapeshellarg($settings->ldap_uname);
- $output[] = "-w ".escapeshellarg(\Crypt::Decrypt($settings->ldap_pword));
+ $output[] = "-w ".escapeshellarg(Crypt::Decrypt($settings->ldap_pword));
$output[] = escapeshellarg(parenthesized_filter($settings->ldap_filter));
if($settings->ldap_tls) {
$this->line("# adding STARTTLS option");
diff --git a/app/Console/Commands/MergeUsersByUsername.php b/app/Console/Commands/MergeUsersByUsername.php
index 390942708d..0c5e966ab9 100644
--- a/app/Console/Commands/MergeUsersByUsername.php
+++ b/app/Console/Commands/MergeUsersByUsername.php
@@ -2,6 +2,7 @@
namespace App\Console\Commands;
+use App\Events\UserMerged;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Console\Command;
@@ -51,7 +52,7 @@ class MergeUsersByUsername extends Command
$bad_users = User::where('username', '=', trim($parts[0]))
->whereNull('deleted_at')
- ->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations')
+ ->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations','uploads', 'acceptances')
->get();
@@ -105,10 +106,26 @@ class MergeUsersByUsername extends Command
$managedLocation->save();
}
+ foreach ($bad_user->uploads as $upload) {
+ $this->info('Updating upload log record '.$upload->id.' to user '.$user->id);
+ $upload->item_id = $user->id;
+ $upload->save();
+ }
+
+ foreach ($bad_user->acceptances as $acceptance) {
+ $this->info('Updating acceptance log record '.$acceptance->id.' to user '.$user->id);
+ $acceptance->item_id = $user->id;
+ $acceptance->save();
+ }
+
// Mark the user as deleted
$this->info('Marking the user as deleted');
$bad_user->deleted_at = Carbon::now()->timestamp;
$bad_user->save();
+
+ event(new UserMerged($bad_user, $user, null));
+
+
}
}
}
diff --git a/app/Console/Commands/MoveUploadsToNewDisk.php b/app/Console/Commands/MoveUploadsToNewDisk.php
index 798ab99874..a27b06feed 100644
--- a/app/Console/Commands/MoveUploadsToNewDisk.php
+++ b/app/Console/Commands/MoveUploadsToNewDisk.php
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
use Illuminate\Console\Command;
use Illuminate\Support\Facades\Storage;
+use Illuminate\Support\Facades\Log;
class MoveUploadsToNewDisk extends Command
{
@@ -74,7 +75,7 @@ class MoveUploadsToNewDisk extends Command
$new_url = Storage::disk('public')->url('uploads/'.$public_type.'/'.$filename, $filename);
$this->info($type_count.'. PUBLIC: '.$filename.' was copied to '.$new_url);
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
$this->error($e);
}
}
@@ -116,7 +117,7 @@ class MoveUploadsToNewDisk extends Command
$new_url = Storage::url($private_type . '/' . $filename, $filename);
$this->info($type_count . '. PRIVATE: ' . $filename . ' was copied to ' . $new_url);
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
$this->error($e);
}
}
@@ -140,7 +141,7 @@ class MoveUploadsToNewDisk extends Command
unlink($filename);
$public_delete_count++;
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
$this->error($e);
}
}
@@ -153,7 +154,7 @@ class MoveUploadsToNewDisk extends Command
unlink($filename);
$private_delete_count++;
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
$this->error($e);
}
}
diff --git a/app/Console/Commands/ObjectImportCommand.php b/app/Console/Commands/ObjectImportCommand.php
index c89018400a..8370e7c050 100644
--- a/app/Console/Commands/ObjectImportCommand.php
+++ b/app/Console/Commands/ObjectImportCommand.php
@@ -5,6 +5,7 @@ namespace App\Console\Commands;
use Illuminate\Console\Command;
use Symfony\Component\Console\Input\InputArgument;
use Symfony\Component\Console\Input\InputOption;
+use Illuminate\Support\Facades\Log;
ini_set('max_execution_time', env('IMPORT_TIME_LIMIT', 600)); //600 seconds = 10 minutes
ini_set('memory_limit', env('IMPORT_MEMORY_LIMIT', '500M'));
@@ -59,7 +60,7 @@ class ObjectImportCommand extends Command
// This $logFile/useFiles() bit is currently broken, so commenting it out for now
// $logFile = $this->option('logfile');
- // \Log::useFiles($logFile);
+ // Log::useFiles($logFile);
$this->comment('======= Importing Items from '.$filename.' =========');
$importer->import();
@@ -112,10 +113,10 @@ class ObjectImportCommand extends Command
public function log($string, $level = 'info')
{
if ($level === 'warning') {
- \Log::warning($string);
+ Log::warning($string);
$this->comment($string);
} else {
- \Log::Info($string);
+ Log::Info($string);
if ($this->option('verbose')) {
$this->comment($string);
}
diff --git a/app/Console/Commands/PaveIt.php b/app/Console/Commands/PaveIt.php
index 9ccb5bf7f3..09c846ea68 100644
--- a/app/Console/Commands/PaveIt.php
+++ b/app/Console/Commands/PaveIt.php
@@ -5,7 +5,7 @@ namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\CustomField;
use Schema;
-use DB;
+use Illuminate\Support\Facades\DB;
use Illuminate\Console\Command;
class PaveIt extends Command
diff --git a/app/Console/Commands/RecryptFromMcrypt.php b/app/Console/Commands/RecryptFromMcrypt.php
index 805774a517..33c8ae65c9 100644
--- a/app/Console/Commands/RecryptFromMcrypt.php
+++ b/app/Console/Commands/RecryptFromMcrypt.php
@@ -103,7 +103,7 @@ class RecryptFromMcrypt extends Command
$this->comment('INFO: No LDAP password found. Skipping... ');
} else {
$decrypted_ldap_pword = $mcrypter->decrypt($settings->ldap_pword);
- $settings->ldap_pword = \Crypt::encrypt($decrypted_ldap_pword);
+ $settings->ldap_pword = Crypt::encrypt($decrypted_ldap_pword);
$settings->save();
}
/** @var CustomField[] $custom_fields */
@@ -132,7 +132,7 @@ class RecryptFromMcrypt extends Command
// Try to decrypt the payload using the legacy app key
try {
$decrypted_field = $mcrypter->decrypt($asset->{$columnName});
- $asset->{$columnName} = \Crypt::encrypt($decrypted_field);
+ $asset->{$columnName} = Crypt::encrypt($decrypted_field);
$this->comment($decrypted_field);
} catch (\Exception $e) {
$errors[] = ' - ERROR: Could not decrypt field ['.$encrypted_field->name.']: '.$e->getMessage();
diff --git a/app/Console/Commands/RegenerateAssetTags.php b/app/Console/Commands/RegenerateAssetTags.php
index bd5cf37a42..a49d3d0774 100644
--- a/app/Console/Commands/RegenerateAssetTags.php
+++ b/app/Console/Commands/RegenerateAssetTags.php
@@ -4,7 +4,7 @@ namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\Setting;
-use Artisan;
+use Illuminate\Support\Facades\Artisan;
use Illuminate\Console\Command;
class RegenerateAssetTags extends Command
diff --git a/app/Console/Commands/RestoreDeletedUsers.php b/app/Console/Commands/RestoreDeletedUsers.php
index 4bf26a544d..9d5582a618 100644
--- a/app/Console/Commands/RestoreDeletedUsers.php
+++ b/app/Console/Commands/RestoreDeletedUsers.php
@@ -6,8 +6,8 @@ use App\Models\Actionlog;
use App\Models\Asset;
use App\Models\License;
use App\Models\User;
-use Artisan;
-use DB;
+use Illuminate\Support\Facades\Artisan;
+use Illuminate\Support\Facades\DB;
use Illuminate\Console\Command;
class RestoreDeletedUsers extends Command
diff --git a/app/Console/Commands/RestoreFromBackup.php b/app/Console/Commands/RestoreFromBackup.php
index 2133b22be1..1cc9b280e1 100644
--- a/app/Console/Commands/RestoreFromBackup.php
+++ b/app/Console/Commands/RestoreFromBackup.php
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
use Illuminate\Console\Command;
use ZipArchive;
+use Illuminate\Support\Facades\Log;
class SQLStreamer {
private $input;
@@ -125,7 +126,7 @@ class SQLStreamer {
while (($buffer = fgets($this->input, SQLStreamer::$buffer_size)) !== false) {
$bytes_read += strlen($buffer);
if ($this->reading_beginning_of_line) {
- // \Log::debug("Buffer is: '$buffer'");
+ // Log::debug("Buffer is: '$buffer'");
$cleaned_buffer = $this->parse_sql($buffer);
if ($this->output) {
$bytes_written = fwrite($this->output, $cleaned_buffer);
@@ -191,7 +192,7 @@ class RestoreFromBackup extends Command
{
$dir = getcwd();
if( $dir != base_path() ) { // usually only the case when running via webserver, not via command-line
- \Log::debug("Current working directory is: $dir, changing directory to: ".base_path());
+ Log::debug("Current working directory is: $dir, changing directory to: ".base_path());
chdir(base_path()); // TODO - is this *safe* to change on a running script?!
}
//
@@ -297,7 +298,7 @@ class RestoreFromBackup extends Command
continue;
}
if (@pathinfo($raw_path, PATHINFO_EXTENSION) == 'sql') {
- \Log::debug("Found a sql file!");
+ Log::debug("Found a sql file!");
$sqlfiles[] = $raw_path;
$sqlfile_indices[] = $i;
continue;
@@ -413,7 +414,7 @@ class RestoreFromBackup extends Command
$bytes_read = 0;
while (($buffer = fgets($sql_contents, SQLStreamer::$buffer_size)) !== false) {
$bytes_read += strlen($buffer);
- // \Log::debug("Buffer is: '$buffer'");
+ // Log::debug("Buffer is: '$buffer'");
$bytes_written = fwrite($pipes[0], $buffer);
if ($bytes_written === false) {
@@ -425,13 +426,13 @@ class RestoreFromBackup extends Command
$bytes_read = $sql_importer->line_aware_piping();
}
} catch (\Exception $e) {
- \Log::error("Error during restore!!!! ".$e->getMessage());
+ Log::error("Error during restore!!!! ".$e->getMessage());
// FIXME - put these back and/or put them in the right places?!
$err_out = fgets($pipes[1]);
$err_err = fgets($pipes[2]);
- \Log::error("Error OUTPUT: ".$err_out);
+ Log::error("Error OUTPUT: ".$err_out);
$this->info($err_out);
- \Log::error("Error ERROR : ".$err_err);
+ Log::error("Error ERROR : ".$err_err);
$this->error($err_err);
throw $e;
}
diff --git a/app/Console/Commands/RotateAppKey.php b/app/Console/Commands/RotateAppKey.php
index f57a9462ee..e4529962b2 100644
--- a/app/Console/Commands/RotateAppKey.php
+++ b/app/Console/Commands/RotateAppKey.php
@@ -5,7 +5,7 @@ namespace App\Console\Commands;
use App\Models\Asset;
use App\Models\CustomField;
use App\Models\Setting;
-use Artisan;
+use Illuminate\Support\Facades\Artisan;
use Illuminate\Console\Command;
use Illuminate\Contracts\Encryption\DecryptException;
use Illuminate\Encryption\Encrypter;
diff --git a/app/Console/Commands/SendAcceptanceReminder.php b/app/Console/Commands/SendAcceptanceReminder.php
new file mode 100644
index 0000000000..dd9e59f611
--- /dev/null
+++ b/app/Console/Commands/SendAcceptanceReminder.php
@@ -0,0 +1,105 @@
+where('checkoutable_type', 'App\Models\Asset')
+ ->whereHas('checkoutable', function($query) {
+ $query->where('archived', 0);
+ })
+ ->with(['assignedTo', 'checkoutable.assignedTo', 'checkoutable.model', 'checkoutable.adminuser'])
+ ->get();
+
+ $count = 0;
+ $unacceptedAssetGroups = $pending
+ ->filter(function($acceptance) {
+ return $acceptance->checkoutable_type == 'App\Models\Asset';
+ })
+ ->map(function($acceptance) {
+ return ['assetItem' => $acceptance->checkoutable, 'acceptance' => $acceptance];
+ })
+ ->groupBy(function($item) {
+ return $item['acceptance']->assignedTo ? $item['acceptance']->assignedTo->id : '';
+ });
+
+ $no_mail_address = [];
+
+ foreach($unacceptedAssetGroups as $unacceptedAssetGroup) {
+ $item_count = $unacceptedAssetGroup->count();
+ foreach ($unacceptedAssetGroup as $unacceptedAsset) {
+// if ($unacceptedAsset['acceptance']->assignedTo->email == ''){
+// $no_mail_address[] = $unacceptedAsset['checkoutable']->assignedTo->present()->fullName;
+// }
+ if ($unacceptedAsset['acceptance']->assignedTo) {
+
+ if (!$unacceptedAsset['acceptance']->assignedTo->locale) {
+ Notification::locale(Setting::getSettings()->locale)->send(
+ $unacceptedAsset['acceptance']->assignedTo,
+ new UnacceptedAssetReminderNotification($unacceptedAsset['assetItem'], $count)
+ );
+ } else {
+ Notification::send(
+ $unacceptedAsset['acceptance']->assignedTo,
+ new UnacceptedAssetReminderNotification($unacceptedAsset, $item_count)
+ );
+ }
+ $count++;
+ }
+ }
+ }
+
+ if (!empty($no_mail_address)) {
+ foreach($no_mail_address as $user) {
+ return $user.' has no email.';
+ }
+
+
+ }
+
+
+
+ $this->info($count.' users notified.');
+ }
+}
diff --git a/app/Console/Commands/SendCurrentInventoryToUsers.php b/app/Console/Commands/SendCurrentInventoryToUsers.php
index 74acc9cc0f..c5180203e6 100644
--- a/app/Console/Commands/SendCurrentInventoryToUsers.php
+++ b/app/Console/Commands/SendCurrentInventoryToUsers.php
@@ -43,7 +43,7 @@ class SendCurrentInventoryToUsers extends Command
$count = 0;
foreach ($users as $user) {
- if (($user->assets->count() > 0) || ($user->accessories->count() > 0) || ($user->licenses->count() > 0)) {
+ if (($user->assets->count() > 0) || ($user->accessories->count() > 0) || ($user->licenses->count() > 0) || ($user->consumables->count() > 0)) {
$count++;
$user->notify((new CurrentInventory($user)));
}
diff --git a/app/Console/Commands/SendExpectedCheckinAlerts.php b/app/Console/Commands/SendExpectedCheckinAlerts.php
index 34e9609ce5..e042e8b088 100644
--- a/app/Console/Commands/SendExpectedCheckinAlerts.php
+++ b/app/Console/Commands/SendExpectedCheckinAlerts.php
@@ -9,7 +9,6 @@ use App\Notifications\ExpectedCheckinAdminNotification;
use App\Notifications\ExpectedCheckinNotification;
use Carbon\Carbon;
use Illuminate\Console\Command;
-use Illuminate\Support\Facades\Log;
class SendExpectedCheckinAlerts extends Command
{
@@ -43,25 +42,31 @@ class SendExpectedCheckinAlerts extends Command
public function handle()
{
$settings = Setting::getSettings();
- $whenNotify = Carbon::now();
- $assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
+ $interval = $settings->audit_warning_days ?? 0;
+ $today = Carbon::now();
+ $interval_date = $today->copy()->addDays($interval);
+
+ $assets = Asset::whereNull('deleted_at')->DueOrOverdueForCheckin($settings)->orderBy('assets.expected_checkin', 'desc')->get();
+
+ $this->info($assets->count().' assets must be checked in on or before '.$interval_date.' is deadline');
- $this->info($whenNotify.' is deadline');
- $this->info($assets->count().' assets');
foreach ($assets as $asset) {
- if ($asset->assigned && $asset->checkedOutToUser()) {
- Log::info('Sending ExpectedCheckinNotification to ' . $asset->assigned->email);
- $asset->assigned->notify((new ExpectedCheckinNotification($asset)));
+ if ($asset->assignedTo && (isset($asset->assignedTo->email)) && ($asset->assignedTo->email!='') && $asset->checkedOutToUser()) {
+ $this->info('Sending User ExpectedCheckinNotification to: '.$asset->assignedTo->email);
+ $asset->assignedTo->notify((new ExpectedCheckinNotification($asset)));
}
}
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
// Send a rollup to the admin, if settings dictate
- $recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
+ $recipients = collect(explode(',', $settings->alert_email))->map(function ($item) {
return new AlertRecipient($item);
});
+
+ $this->info('Sending Admin ExpectedCheckinNotification to: '.$settings->alert_email);
\Notification::send($recipients, new ExpectedCheckinAdminNotification($assets));
+
}
}
}
diff --git a/app/Console/Commands/SendUpcomingAuditReport.php b/app/Console/Commands/SendUpcomingAuditReport.php
index e9cba106c6..7c81a37d3a 100644
--- a/app/Console/Commands/SendUpcomingAuditReport.php
+++ b/app/Console/Commands/SendUpcomingAuditReport.php
@@ -3,13 +3,11 @@
namespace App\Console\Commands;
use App\Models\Asset;
-use App\Models\License;
-use App\Models\Recipients;
+use App\Models\Recipients\AlertRecipient;
use App\Models\Setting;
-use App\Notifications\ExpiringAssetsNotification;
use App\Notifications\SendUpcomingAuditNotification;
use Carbon\Carbon;
-use DB;
+use Illuminate\Support\Facades\DB;
use Illuminate\Console\Command;
class SendUpcomingAuditReport extends Command
@@ -46,39 +44,24 @@ class SendUpcomingAuditReport extends Command
public function handle()
{
$settings = Setting::getSettings();
+ $interval = $settings->audit_warning_days ?? 0;
+ $today = Carbon::now();
+ $interval_date = $today->copy()->addDays($interval);
- if (($settings->alert_email != '') && ($settings->audit_warning_days) && ($settings->alerts_enabled == 1)) {
+ $assets = Asset::whereNull('deleted_at')->DueOrOverdueForAudit($settings)->orderBy('assets.next_audit_date', 'desc')->get();
+ $this->info($assets->count().' assets must be audited in on or before '.$interval_date.' is deadline');
+
+ if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
// Send a rollup to the admin, if settings dictate
- $recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
- return new \App\Models\Recipients\AlertRecipient($item);
+ $recipients = collect(explode(',', $settings->alert_email))->map(function ($item) {
+ return new AlertRecipient($item);
});
- // Assets due for auditing
+ $this->info('Sending Admin SendUpcomingAuditNotification to: '.$settings->alert_email);
+ \Notification::send($recipients, new SendUpcomingAuditNotification($assets, $settings->audit_warning_days));
- $assets = Asset::whereNotNull('next_audit_date')
- ->DueOrOverdueForAudit($settings)
- ->orderBy('last_audit_date', 'asc')->get();
-
- if ($assets->count() > 0) {
- $this->info(trans_choice('mail.upcoming-audits', $assets->count(),
- ['count' => $assets->count(), 'threshold' => $settings->audit_warning_days]));
- \Notification::send($recipients, new SendUpcomingAuditNotification($assets, $settings->audit_warning_days));
- $this->info('Audit report sent to '.$settings->alert_email);
- } else {
- $this->info('No assets to be audited. No report sent.');
- }
- } elseif ($settings->alert_email == '') {
- $this->error('Could not send email. No alert email configured in settings');
- } elseif (! $settings->audit_warning_days) {
- $this->error('No audit warning days set in Admin Notifications. No mail will be sent.');
- } elseif ($settings->alerts_enabled != 1) {
- $this->info('Alerts are disabled in the settings. No mail will be sent');
- } else {
- $this->error('Something went wrong. :( ');
- $this->error('Admin Notifications Email Setting: '.$settings->alert_email);
- $this->error('Admin Audit Warning Setting: '.$settings->audit_warning_days);
- $this->error('Admin Alerts Emnabled: '.$settings->alerts_enabled);
}
+
}
}
diff --git a/app/Console/Commands/SyncAssetCounters.php b/app/Console/Commands/SyncAssetCounters.php
index b3bc15776e..2e2bb18f3b 100644
--- a/app/Console/Commands/SyncAssetCounters.php
+++ b/app/Console/Commands/SyncAssetCounters.php
@@ -4,6 +4,7 @@ namespace App\Console\Commands;
use App\Models\Asset;
use Illuminate\Console\Command;
+use Illuminate\Support\Facades\Log;
class SyncAssetCounters extends Command
{
@@ -58,7 +59,7 @@ class SyncAssetCounters extends Command
$asset->save();
$bar->advance();
- \Log::debug('Asset: '.$asset->id.' has '.$asset->checkin_counter.' checkins, '.$asset->checkout_counter.' checkouts, and '.$asset->requests_counter.' requests');
+ Log::debug('Asset: '.$asset->id.' has '.$asset->checkin_counter.' checkins, '.$asset->checkout_counter.' checkouts, and '.$asset->requests_counter.' requests');
}
diff --git a/app/Events/UserMerged.php b/app/Events/UserMerged.php
index b045fdef03..3a7f4d6a2c 100644
--- a/app/Events/UserMerged.php
+++ b/app/Events/UserMerged.php
@@ -15,7 +15,7 @@ class UserMerged
*
* @return void
*/
- public function __construct(User $from_user, User $to_user, User $admin)
+ public function __construct(User $from_user, User $to_user, ?User $admin)
{
$this->merged_from = $from_user;
$this->merged_to = $to_user;
diff --git a/app/Exceptions/Handler.php b/app/Exceptions/Handler.php
index e76d8e5dae..2b8eaa3627 100644
--- a/app/Exceptions/Handler.php
+++ b/app/Exceptions/Handler.php
@@ -7,7 +7,7 @@ use App\Helpers\Helper;
use Illuminate\Validation\ValidationException;
use Illuminate\Auth\AuthenticationException;
use ArieTimmerman\Laravel\SCIMServer\Exceptions\SCIMException;
-use Log;
+use Illuminate\Support\Facades\Log;
use Throwable;
use JsonException;
use Carbon\Exceptions\InvalidFormatException;
@@ -44,8 +44,8 @@ class Handler extends ExceptionHandler
public function report(Throwable $exception)
{
if ($this->shouldReport($exception)) {
- if (class_exists(\Log::class)) {
- \Log::error($exception);
+ if (class_exists(Log::class)) {
+ Log::error($exception);
}
return parent::report($exception);
}
diff --git a/app/Helpers/Helper.php b/app/Helpers/Helper.php
index e3f2b036e0..c6de362dcb 100644
--- a/app/Helpers/Helper.php
+++ b/app/Helpers/Helper.php
@@ -12,10 +12,12 @@ use App\Models\Depreciation;
use App\Models\Setting;
use App\Models\Statuslabel;
use App\Models\License;
-use Crypt;
+use Illuminate\Support\Facades\Crypt;
use Illuminate\Contracts\Encryption\DecryptException;
-use Image;
use Carbon\Carbon;
+use Illuminate\Support\Facades\Log;
+use Intervention\Image\ImageManagerStatic as Image;
+use Illuminate\Support\Facades\Session;
class Helper
{
@@ -62,6 +64,7 @@ class Helper
'nl' => 'nl-NL', // Dutch
'no' => 'no-NO', // Norwegian
'pl' => 'pl-PL', // Polish
+ 'pt' => 'pt-PT', // Portuguese
'ro' => 'ro-RO', // Romanian
'ru' => 'ru-RU', // Russian
'sk' => 'sk-SK', // Slovak
@@ -412,7 +415,7 @@ class Helper
if ($index >= $total_colors) {
- \Log::info('Status label count is '.$index.' and exceeds the allowed count of 266.');
+ Log::info('Status label count is '.$index.' and exceeds the allowed count of 266.');
//patch fix for array key overflow (color count starts at 1, array starts at 0)
$index = $index - $total_colors - 1;
@@ -875,12 +878,15 @@ class Helper
$permission_name = $permission[$x]['permission'];
if ($permission[$x]['display'] === true) {
- if ($selected_arr) {
+
+ if (is_array($selected_arr)) {
+
if (array_key_exists($permission_name, $selected_arr)) {
$permissions_arr[$permission_name] = $selected_arr[$permission_name];
} else {
$permissions_arr[$permission_name] = '0';
}
+
} else {
$permissions_arr[$permission_name] = '0';
}
@@ -1012,7 +1018,7 @@ class Helper
try {
- $tmp_date = new \Carbon($date);
+ $tmp_date = new Carbon($date);
if ($type == 'datetime') {
$dt['datetime'] = $tmp_date->format('Y-m-d H:i:s');
@@ -1029,7 +1035,7 @@ class Helper
return $dt['formatted'];
} catch (\Exception $e) {
- \Log::warning($e);
+ Log::warning($e);
return $date.' (Invalid '.$type.' value.)';
}
@@ -1342,7 +1348,7 @@ class Helper
public static function isDemoMode() {
if (config('app.lock_passwords') === true) {
return true;
- \Log::debug('app locked!');
+ Log::debug('app locked!');
}
return false;
@@ -1435,7 +1441,6 @@ class Helper
foreach (self::$language_map as $legacy => $new) {
if ($language_code == $legacy) {
- \Log::debug('Current language is '.$legacy.', using '.$new.' instead');
return $new;
}
}
@@ -1446,6 +1451,7 @@ 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
}
@@ -1453,10 +1459,53 @@ 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, $asset_id = null)
+ {
+
+ $redirect_option = Session::get('redirect_option');
+ $checkout_to_type = Session::get('checkout_to_type');
+
+ //return to index
+ if ($redirect_option == '0') {
+ switch ($table) {
+ case "Assets":
+ return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkout.success'));
+ }
+ }
+ //return to thing being assigned
+ if ($redirect_option == '1') {
+ switch ($table) {
+ case "Assets":
+ return redirect()->route('hardware.show', $id ? $id : $asset_id)->with('success', trans('admin/hardware/message.checkout.success'));
+ }
+ }
+ //return to thing being assigned to
+ if ($redirect_option == '2') {
+ switch ($checkout_to_type) {
+ case 'user':
+ return redirect()->route('users.show', $request->assigned_user)->with('success', trans('admin/hardware/message.checkout.success'));
+ case 'location':
+ return redirect()->route('locations.show', $request->assigned_location)->with('success', trans('admin/hardware/message.checkout.success'));
+ case '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'));
+ }
}
diff --git a/app/Helpers/StorageHelper.php b/app/Helpers/StorageHelper.php
index 94dfe62c76..2cdab1d66c 100644
--- a/app/Helpers/StorageHelper.php
+++ b/app/Helpers/StorageHelper.php
@@ -3,10 +3,13 @@
namespace App\Helpers;
use Illuminate\Support\Facades\Storage;
-
+use Illuminate\Http\Response;
+use Illuminate\Http\RedirectResponse;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
+use Symfony\Component\HttpFoundation\StreamedResponse;
class StorageHelper
{
- public static function downloader($filename, $disk = 'default')
+ public static function downloader($filename, $disk = 'default') : BinaryFileResponse | RedirectResponse | StreamedResponse
{
if ($disk == 'default') {
$disk = config('filesystems.default');
diff --git a/app/Http/Controllers/Accessories/AccessoriesController.php b/app/Http/Controllers/Accessories/AccessoriesController.php
index 6ef6fb9933..bb2e74899b 100755
--- a/app/Http/Controllers/Accessories/AccessoriesController.php
+++ b/app/Http/Controllers/Accessories/AccessoriesController.php
@@ -7,10 +7,11 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Accessory;
use App\Models\Company;
-use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
-use Redirect;
+use \Illuminate\Contracts\View\View;
+use \Illuminate\Http\RedirectResponse;
+use Illuminate\Support\Facades\Log;
/** This controller handles all actions related to Accessories for
* the Snipe-IT Asset Management application.
@@ -26,13 +27,10 @@ class AccessoriesController extends Controller
* @author [A. Gianotto] []
* @see AccessoriesController::getDatatable() method that generates the JSON response
* @since [v1.0]
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function index()
+ public function index() : View
{
$this->authorize('index', Accessory::class);
-
return view('accessories/index');
}
@@ -40,10 +38,8 @@ class AccessoriesController extends Controller
* Returns a view with a form to create a new Accessory.
*
* @author [A. Gianotto] []
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create()
+ public function create() : View
{
$this->authorize('create', Accessory::class);
$category_type = 'accessory';
@@ -57,10 +53,8 @@ class AccessoriesController extends Controller
*
* @author [A. Gianotto] []
* @param ImageUploadRequest $request
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : RedirectResponse
{
$this->authorize(Accessory::class);
@@ -79,7 +73,7 @@ class AccessoriesController extends Controller
$accessory->purchase_date = request('purchase_date');
$accessory->purchase_cost = request('purchase_cost');
$accessory->qty = request('qty');
- $accessory->user_id = Auth::user()->id;
+ $accessory->user_id = auth()->id();
$accessory->supplier_id = request('supplier_id');
$accessory->notes = request('notes');
@@ -99,15 +93,12 @@ class AccessoriesController extends Controller
*
* @author [A. Gianotto] []
* @param int $accessoryId
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit($accessoryId = null)
+ public function edit($accessoryId = null) : View | RedirectResponse
{
if ($item = Accessory::find($accessoryId)) {
$this->authorize($item);
-
return view('accessories/edit', compact('item'))->with('category_type', 'accessory');
}
@@ -121,9 +112,8 @@ class AccessoriesController extends Controller
* @author [J. Vinsmoke]
* @param int $accessoryId
* @since [v6.0]
- * @return View
*/
- public function getClone($accessoryId = null)
+ public function getClone($accessoryId = null) : View | RedirectResponse
{
$this->authorize('create', Accessory::class);
@@ -150,10 +140,8 @@ class AccessoriesController extends Controller
* @author [A. Gianotto] []
* @param ImageUploadRequest $request
* @param int $accessoryId
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function update(ImageUploadRequest $request, $accessoryId = null)
+ public function update(ImageUploadRequest $request, $accessoryId = null) : RedirectResponse
{
if ($accessory = Accessory::withCount('users as users_count')->find($accessoryId)) {
@@ -204,10 +192,8 @@ class AccessoriesController extends Controller
*
* @author [A. Gianotto] []
* @param int $accessoryId
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($accessoryId)
+ public function destroy($accessoryId) : RedirectResponse
{
if (is_null($accessory = Accessory::find($accessoryId))) {
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
@@ -224,7 +210,7 @@ class AccessoriesController extends Controller
try {
Storage::disk('public')->delete('accessories'.'/'.$accessory->image);
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
}
}
@@ -242,10 +228,8 @@ class AccessoriesController extends Controller
* @param int $accessoryID
* @see AccessoriesController::getDataView() method that generates the JSON response
* @since [v1.0]
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function show($accessoryID = null)
+ public function show($accessoryID = null) : View | RedirectResponse
{
$accessory = Accessory::withCount('users as users_count')->find($accessoryID);
$this->authorize('view', $accessory);
diff --git a/app/Http/Controllers/Accessories/AccessoriesFilesController.php b/app/Http/Controllers/Accessories/AccessoriesFilesController.php
index f0de6354f7..b63c202d30 100644
--- a/app/Http/Controllers/Accessories/AccessoriesFilesController.php
+++ b/app/Http/Controllers/Accessories/AccessoriesFilesController.php
@@ -7,9 +7,13 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\Accessory;
-use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
-use Symfony\Accessory\HttpFoundation\JsonResponse;
+use Illuminate\Support\Facades\Log;
+use \Illuminate\Contracts\View\View;
+use \Illuminate\Http\RedirectResponse;
+use Illuminate\Support\Facades\Response;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
+use Symfony\Component\HttpFoundation\StreamedResponse;
class AccessoriesFilesController extends Controller
{
@@ -18,20 +22,17 @@ class AccessoriesFilesController extends Controller
*
* @param UploadFileRequest $request
* @param int $accessoryId
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
- *@author [A. Gianotto] []
+ * @author [A. Gianotto] []
* @since [v1.0]
* @todo Switch to using the AssetFileRequest form request validator.
*/
- public function store(UploadFileRequest $request, $accessoryId = null)
+ public function store(UploadFileRequest $request, $accessoryId = null) : RedirectResponse
{
if (config('app.lock_passwords')) {
return redirect()->route('accessories.show', ['accessory'=>$accessoryId])->with('error', trans('general.feature_disabled'));
}
-
$accessory = Accessory::find($accessoryId);
if (isset($accessory->id)) {
@@ -68,10 +69,8 @@ class AccessoriesFilesController extends Controller
* @since [v1.0]
* @param int $accessoryId
* @param int $fileId
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($accessoryId = null, $fileId = null)
+ public function destroy($accessoryId = null, $fileId = null) : RedirectResponse
{
$accessory = Accessory::find($accessoryId);
@@ -85,7 +84,7 @@ class AccessoriesFilesController extends Controller
try {
Storage::delete('accessories/'.$log->filename);
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
}
}
@@ -106,13 +105,11 @@ class AccessoriesFilesController extends Controller
* @since [v1.4]
* @param int $accessoryId
* @param int $fileId
- * @return \Symfony\Accessory\HttpFoundation\Response
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function show($accessoryId = null, $fileId = null, $download = true)
+ public function show($accessoryId = null, $fileId = null, $download = true) : View | RedirectResponse | Response | BinaryFileResponse | StreamedResponse
{
- \Log::debug('Private filesystem is: '.config('filesystems.default'));
+ Log::debug('Private filesystem is: '.config('filesystems.default'));
$accessory = Accessory::find($accessoryId);
@@ -129,8 +126,8 @@ class AccessoriesFilesController extends Controller
$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));
+ 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');
diff --git a/app/Http/Controllers/Accessories/AccessoryCheckinController.php b/app/Http/Controllers/Accessories/AccessoryCheckinController.php
index 06d910c481..eff635d24a 100644
--- a/app/Http/Controllers/Accessories/AccessoryCheckinController.php
+++ b/app/Http/Controllers/Accessories/AccessoryCheckinController.php
@@ -7,8 +7,9 @@ use App\Http\Controllers\Controller;
use App\Models\Accessory;
use App\Models\User;
use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
+use \Illuminate\Contracts\View\View;
+use \Illuminate\Http\RedirectResponse;
class AccessoryCheckinController extends Controller
{
@@ -19,15 +20,10 @@ class AccessoryCheckinController extends Controller
* @param Request $request
* @param int $accessoryUserId
* @param string $backto
- * @return View
- * @internal param int $accessoryId
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create($accessoryUserId = null, $backto = null)
+ public function create($accessoryUserId = null, $backto = null) : View | RedirectResponse
{
- // Check if the accessory exists
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
- // Redirect to the accessory management page with error
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
}
@@ -44,15 +40,10 @@ class AccessoryCheckinController extends Controller
* @author [A. Gianotto] []
* @param null $accessoryUserId
* @param string $backto
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
- * @internal param int $accessoryId
*/
- public function store(Request $request, $accessoryUserId = null, $backto = null)
+ public function store(Request $request, $accessoryUserId = null, $backto = null) : RedirectResponse
{
- // Check if the accessory exists
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
- // Redirect to the accessory management page with error
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
}
@@ -70,7 +61,7 @@ class AccessoryCheckinController extends Controller
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
$return_to = e($accessory_user->assigned_to);
- event(new CheckoutableCheckedIn($accessory, User::find($return_to), Auth::user(), $request->input('note'), $checkin_at));
+ event(new CheckoutableCheckedIn($accessory, User::find($return_to), auth()->user(), $request->input('note'), $checkin_at));
return redirect()->route('accessories.show', $accessory->id)->with('success', trans('admin/accessories/message.checkin.success'));
}
diff --git a/app/Http/Controllers/Accessories/AccessoryCheckoutController.php b/app/Http/Controllers/Accessories/AccessoryCheckoutController.php
index 1cafe319d1..19c8c6c7c5 100644
--- a/app/Http/Controllers/Accessories/AccessoryCheckoutController.php
+++ b/app/Http/Controllers/Accessories/AccessoryCheckoutController.php
@@ -4,13 +4,14 @@ namespace App\Http\Controllers\Accessories;
use App\Events\CheckoutableCheckedOut;
use App\Http\Controllers\Controller;
+use App\Http\Requests\AccessoryCheckoutRequest;
use App\Models\Accessory;
use App\Models\User;
use Carbon\Carbon;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\DB;
-use Illuminate\Support\Facades\Input;
+use \Illuminate\Contracts\View\View;
+use \Illuminate\Http\RedirectResponse;
class AccessoryCheckoutController extends Controller
{
@@ -19,10 +20,8 @@ class AccessoryCheckoutController extends Controller
*
* @author [A. Gianotto] []
* @param int $id
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create($id)
+ public function create($id) : View | RedirectResponse
{
if ($accessory = Accessory::withCount('users as users_count')->find($id)) {
@@ -58,46 +57,29 @@ class AccessoryCheckoutController extends Controller
*
* @author [A. Gianotto] []
* @param Request $request
- * @param int $accessoryId
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
+ * @param int $accessory
*/
- public function store(Request $request, $accessoryId)
+ public function store(AccessoryCheckoutRequest $request, Accessory $accessory) : 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);
+ $accessory->assigned_to = $request->input('assigned_to');
+ $user = User::find($request->input('assigned_to'));
+ $accessory->checkout_qty = $request->input('checkout_qty', 1);
- 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'));
+ for ($i = 0; $i < $accessory->checkout_qty; $i++) {
+ $accessory->users()->attach($accessory->id, [
+ 'accessory_id' => $accessory->id,
+ 'created_at' => Carbon::now(),
+ 'user_id' => Auth::id(),
+ 'assigned_to' => $request->input('assigned_to'),
+ 'note' => $request->input('note'),
+ ]);
}
-
- // 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'));
- }
-
-
- // 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')));
+ event(new CheckoutableCheckedOut($accessory, $user, auth()->user(), $request->input('note')));
// Redirect to the new accessory page
- return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.checkout.success'));
+ return redirect()->route('accessories.index')
+ ->with('success', trans('admin/accessories/message.checkout.success'));
}
}
diff --git a/app/Http/Controllers/Account/AcceptanceController.php b/app/Http/Controllers/Account/AcceptanceController.php
index 030e069bd2..2c9d29fc16 100644
--- a/app/Http/Controllers/Account/AcceptanceController.php
+++ b/app/Http/Controllers/Account/AcceptanceController.php
@@ -23,25 +23,23 @@ use App\Notifications\AcceptanceAssetAcceptedNotification;
use App\Notifications\AcceptanceAssetDeclinedNotification;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Str;
use App\Http\Controllers\SettingsController;
use Barryvdh\DomPDF\Facade\Pdf;
use Carbon\Carbon;
-use phpDocumentor\Reflection\Types\Compound;
+use \Illuminate\Contracts\View\View;
+use \Illuminate\Http\RedirectResponse;
+use Illuminate\Support\Facades\Log;
class AcceptanceController extends Controller
{
/**
* Show a listing of pending checkout acceptances for the current user
- *
- * @return View
*/
- public function index()
+ public function index() : View
{
- $acceptances = CheckoutAcceptance::forUser(Auth::user())->pending()->get();
-
+ $acceptances = CheckoutAcceptance::forUser(auth()->user())->pending()->get();
return view('account/accept.index', compact('acceptances'));
}
@@ -49,9 +47,8 @@ class AcceptanceController extends Controller
* Shows a form to either accept or decline the checkout acceptance
*
* @param int $id
- * @return mixed
*/
- public function create($id)
+ public function create($id) : View | RedirectResponse
{
$acceptance = CheckoutAcceptance::find($id);
@@ -64,7 +61,7 @@ class AcceptanceController extends Controller
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted'));
}
- if (! $acceptance->isCheckedOutTo(Auth::user())) {
+ if (! $acceptance->isCheckedOutTo(auth()->user())) {
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
@@ -80,9 +77,8 @@ class AcceptanceController extends Controller
*
* @param Request $request
* @param int $id
- * @return Redirect
*/
- public function store(Request $request, $id)
+ public function store(Request $request, $id) : RedirectResponse
{
$acceptance = CheckoutAcceptance::find($id);
@@ -94,7 +90,7 @@ class AcceptanceController extends Controller
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted'));
}
- if (! $acceptance->isCheckedOutTo(Auth::user())) {
+ if (! $acceptance->isCheckedOutTo(auth()->user())) {
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
}
@@ -223,6 +219,7 @@ class AcceptanceController extends Controller
'item_model' => $display_model,
'item_serial' => $item->serial,
'eula' => $item->getEula(),
+ 'note' => $request->input('note'),
'check_out_date' => Carbon::parse($acceptance->created_at)->format('Y-m-d'),
'accepted_date' => Carbon::parse($acceptance->accepted_at)->format('Y-m-d'),
'assigned_to' => $assigned_to,
@@ -233,12 +230,12 @@ class AcceptanceController extends Controller
];
if ($pdf_view_route!='') {
- \Log::debug($pdf_filename.' is the filename, and the route was specified.');
+ Log::debug($pdf_filename.' is the filename, and the route was specified.');
$pdf = Pdf::loadView($pdf_view_route, $data);
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
}
- $acceptance->accept($sig_filename, $item->getEula(), $pdf_filename);
+ $acceptance->accept($sig_filename, $item->getEula(), $pdf_filename, $request->input('note'));
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
event(new CheckoutAccepted($acceptance));
@@ -306,10 +303,12 @@ class AcceptanceController extends Controller
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
break;
}
+
$data = [
'item_tag' => $item->asset_tag,
'item_model' => $display_model,
'item_serial' => $item->serial,
+ '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,
'assigned_to' => $assigned_to,
@@ -318,12 +317,12 @@ class AcceptanceController extends Controller
];
if ($pdf_view_route!='') {
- \Log::debug($pdf_filename.' is the filename, and the route was specified.');
+ Log::debug($pdf_filename.' is the filename, and the route was specified.');
$pdf = Pdf::loadView($pdf_view_route, $data);
Storage::put('private_uploads/eula-pdfs/' .$pdf_filename, $pdf->output());
}
- $acceptance->decline($sig_filename);
+ $acceptance->decline($sig_filename, $request->input('note'));
$acceptance->notify(new AcceptanceAssetDeclinedNotification($data));
event(new CheckoutDeclined($acceptance));
$return_msg = trans('admin/users/message.declined');
diff --git a/app/Http/Controllers/ActionlogController.php b/app/Http/Controllers/ActionlogController.php
index c0c8a997d7..f143c4b73b 100644
--- a/app/Http/Controllers/ActionlogController.php
+++ b/app/Http/Controllers/ActionlogController.php
@@ -3,34 +3,44 @@
namespace App\Http\Controllers;
use App\Helpers\Helper;
-use App\Models\Actionlog;
-use Response;
-
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\Storage;
+use \Illuminate\Http\Response;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
class ActionlogController extends Controller
{
- public function displaySig($filename)
+ public function displaySig($filename) : RedirectResponse | Response | bool
{
// PHP doesn't let you handle file not found errors well with
// file_get_contents, so we set the error reporting for just this class
error_reporting(0);
- $this->authorize('view', \App\Models\Asset::class);
- $file = config('app.private_uploads').'/signatures/'.$filename;
- $filetype = Helper::checkUploadIsImage($file);
+ $disk = config('filesystems.default');
+ switch (config("filesystems.disks.$disk.driver")) {
- $contents = file_get_contents($file, false, stream_context_create(['http' => ['ignore_errors' => true]]));
- if ($contents === false) {
- \Log::warn('File '.$file.' not found');
- return false;
- } else {
- return Response::make($contents)->header('Content-Type', $filetype);
+ case 's3':
+ $file = 'private_uploads/signatures/'.$filename;
+ return redirect()->away(Storage::disk($disk)->temporaryUrl($file, now()->addMinutes(5)));
+ default:
+ $this->authorize('view', \App\Models\Asset::class);
+ $file = config('app.private_uploads').'/signatures/'.$filename;
+ $filetype = Helper::checkUploadIsImage($file);
+
+ $contents = file_get_contents($file, false, stream_context_create(['http' => ['ignore_errors' => true]]));
+ if ($contents === false) {
+ Log::warning('File '.$file.' not found');
+ return false;
+ } else {
+ return response()->make($contents)->header('Content-Type', $filetype);
+ }
}
-
}
- public function getStoredEula($filename){
+
+ public function getStoredEula($filename) : Response | BinaryFileResponse
+ {
$this->authorize('view', \App\Models\Asset::class);
$file = config('app.private_uploads').'/eula-pdfs/'.$filename;
-
- return Response::download($file);
+ return response()->download($file);
}
}
diff --git a/app/Http/Controllers/Api/AccessoriesController.php b/app/Http/Controllers/Api/AccessoriesController.php
index 7dcee93204..1ffdcaf193 100644
--- a/app/Http/Controllers/Api/AccessoriesController.php
+++ b/app/Http/Controllers/Api/AccessoriesController.php
@@ -5,17 +5,20 @@ namespace App\Http\Controllers\Api;
use App\Events\CheckoutableCheckedOut;
use App\Helpers\Helper;
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;
use App\Models\Company;
use App\Models\User;
-use Auth;
+use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
-use DB;
+use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
+
class AccessoriesController extends Controller
{
/**
@@ -120,12 +123,12 @@ class AccessoriesController extends Controller
/**
* Store a newly created resource in storage.
*
+ * @param \App\Http\Requests\ImageUploadRequest $request
+ * @return \Illuminate\Http\JsonResponse
* @author [A. Gianotto] []
* @since [v4.0]
- * @param \App\Http\Requests\ImageUploadRequest $request
- * @return \Illuminate\Http\Response
*/
- public function store(ImageUploadRequest $request)
+ public function store(StoreAccessoryRequest $request)
{
$this->authorize('create', Accessory::class);
$accessory = new Accessory;
@@ -143,10 +146,10 @@ class AccessoriesController extends Controller
/**
* Display the specified resource.
*
+ * @param int $id
+ * @return array
* @author [A. Gianotto] []
* @since [v4.0]
- * @param int $id
- * @return \Illuminate\Http\Response
*/
public function show($id)
{
@@ -160,10 +163,10 @@ class AccessoriesController extends Controller
/**
* Display the specified resource.
*
+ * @param int $id
+ * @return array
* @author [A. Gianotto] []
* @since [v4.0]
- * @param int $id
- * @return \Illuminate\Http\Response
*/
public function accessory_detail($id)
{
@@ -272,43 +275,31 @@ 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.
*
- * @author [A. Gianotto] []
* @param int $accessoryId
- * @return Redirect
+ * @return \Illuminate\Http\JsonResponse
+ * @author [A. Gianotto] []
*/
- public function checkout(Request $request, $accessoryId)
+ public function checkout(AccessoryCheckoutRequest $request, Accessory $accessory)
{
- // 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')));
- }
-
$this->authorize('checkout', $accessory);
+ $accessory->assigned_to = $request->input('assigned_to');
+ $user = User::find($request->input('assigned_to'));
+ $accessory->checkout_qty = $request->input('checkout_qty', 1);
-
- 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');
-
+ for ($i = 0; $i < $accessory->checkout_qty; $i++) {
$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'),
+ 'assigned_to' => $request->input('assigned_to'),
+ 'note' => $request->input('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'));
+ // Set this value to be able to pass the qty through to the event
+ event(new CheckoutableCheckedOut($accessory, $user, auth()->user(), $request->input('note')));
+
+ return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/accessories/message.checkout.success')));
}
@@ -320,7 +311,7 @@ class AccessoriesController extends Controller
* @param Request $request
* @param int $accessoryUserId
* @param string $backto
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
* @internal param int $accessoryId
*/
public function checkin(Request $request, $accessoryUserId = null)
diff --git a/app/Http/Controllers/Api/AssetFilesController.php b/app/Http/Controllers/Api/AssetFilesController.php
new file mode 100644
index 0000000000..4369d287d5
--- /dev/null
+++ b/app/Http/Controllers/Api/AssetFilesController.php
@@ -0,0 +1,200 @@
+
+ *
+ * @version v1.0
+ * @author [T. Scarsbrook] []
+ */
+class AssetFilesController extends Controller
+{
+ /**
+ * Accepts a POST to upload a file to the server.
+ *
+ * @param \App\Http\Requests\UploadFileRequest $request
+ * @param int $assetId
+ * @since [v6.0]
+ * @author [T. Scarsbrook] []
+ */
+ public function store(UploadFileRequest $request, $assetId = null) : JsonResponse
+ {
+ // Start by checking if the asset being acted upon exists
+ if (! $asset = Asset::find($assetId)) {
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
+ }
+
+ // Make sure we are allowed to update this asset
+ $this->authorize('update', $asset);
+
+ if ($request->hasFile('file')) {
+ // If the file storage directory doesn't exist; create it
+ if (! Storage::exists('private_uploads/assets')) {
+ Storage::makeDirectory('private_uploads/assets', 775);
+ }
+
+ // Loop over the attached files and add them to the asset
+ foreach ($request->file('file') as $file) {
+ $file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
+
+ $asset->logUpload($file_name, e($request->get('notes')));
+ }
+
+ // All done - report success
+ return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/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/hardware/message.upload.nofiles')), 500);
+ }
+
+ /**
+ * List the files for an asset.
+ *
+ * @param int $assetId
+ * @since [v6.0]
+ * @author [T. Scarsbrook] []
+ */
+ public function list($assetId = null) : JsonResponse
+ {
+ // Start by checking if the asset being acted upon exists
+ if (! $asset = Asset::find($assetId)) {
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
+ }
+
+ // the asset is valid
+ if (isset($asset->id)) {
+ $this->authorize('view', $asset);
+
+ // Check that there are some uploads on this asset that can be listed
+ if ($asset->uploads->count() > 0) {
+ $files = array();
+ foreach ($asset->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/hardware/message.upload.success')));
+ }
+
+ // There are no files.
+ return response()->json(Helper::formatStandardApiResponse('success', array(), trans('admin/hardware/message.upload.success')));
+ }
+
+ // Send back an error message
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.error')), 500);
+ }
+
+ /**
+ * Check for permissions and display the file.
+ *
+ * @param int $assetId
+ * @param int $fileId
+ * @return \Illuminate\Http\JsonResponse
+ * @throws \Illuminate\Auth\Access\AuthorizationException
+ * @since [v6.0]
+ * @author [T. Scarsbrook] []
+ */
+ public function show($assetId = null, $fileId = null) : JsonResponse | StreamedResponse | Storage | StorageHelper | BinaryFileResponse
+ {
+ // Start by checking if the asset being acted upon exists
+ if (! $asset = Asset::find($assetId)) {
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
+ }
+
+ // the asset is valid
+ if (isset($asset->id)) {
+ $this->authorize('view', $asset);
+
+ // Check that the file being requested exists for the asset
+ if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.no_match', ['id' => $fileId])), 404);
+ }
+
+ // Form the full filename with path
+ $file = 'private_uploads/assets/'.$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/hardware/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/hardware/message.download.error', ['id' => $fileId])), 500);
+ }
+
+ /**
+ * Delete the associated file
+ *
+ * @param int $assetId
+ * @param int $fileId
+ * @since [v6.0]
+ * @author [T. Scarsbrook] []
+ */
+ public function destroy($assetId = null, $fileId = null) : JsonResponse
+ {
+ // Start by checking if the asset being acted upon exists
+ if (! $asset = Asset::find($assetId)) {
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
+ }
+
+ $rel_path = 'private_uploads/assets';
+
+ // the asset is valid
+ if (isset($asset->id)) {
+ $this->authorize('update', $asset);
+
+ // 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/hardware/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/hardware/message.deletefile.error')), 500);
+ }
+
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.deletefile.error')), 500);
+ }
+}
diff --git a/app/Http/Controllers/Api/AssetMaintenancesController.php b/app/Http/Controllers/Api/AssetMaintenancesController.php
index 4b47c323c2..ac247a8873 100644
--- a/app/Http/Controllers/Api/AssetMaintenancesController.php
+++ b/app/Http/Controllers/Api/AssetMaintenancesController.php
@@ -8,10 +8,9 @@ use App\Http\Transformers\AssetMaintenancesTransformer;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\Company;
-use Auth;
-use Carbon\Carbon;
+use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Input;
+use Illuminate\Http\JsonResponse;
/**
* This controller handles all actions related to Asset Maintenance for
@@ -22,7 +21,6 @@ use Illuminate\Support\Facades\Input;
class AssetMaintenancesController extends Controller
{
-
/**
* Generates the JSON response for asset maintenances listing view.
*
@@ -30,9 +28,8 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato
* @version v1.0
* @since [v1.8]
- * @return string JSON
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Asset::class);
@@ -120,9 +117,8 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato
* @version v1.0
* @since [v1.8]
- * @return string JSON
*/
- public function store(Request $request)
+ public function store(Request $request) : JsonResponse
{
$this->authorize('update', Asset::class);
// create a new model instance
@@ -148,9 +144,8 @@ class AssetMaintenancesController extends Controller
* @param int $request
* @version v1.0
* @since [v4.0]
- * @return string JSON
*/
- public function update(Request $request, $id)
+ public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', Asset::class);
@@ -186,9 +181,8 @@ class AssetMaintenancesController extends Controller
* @param int $assetMaintenanceId
* @version v1.0
* @since [v4.0]
- * @return string JSON
*/
- public function destroy($assetMaintenanceId)
+ public function destroy($assetMaintenanceId) : JsonResponse
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
@@ -212,9 +206,8 @@ class AssetMaintenancesController extends Controller
* @param int $assetMaintenanceId
* @version v1.0
* @since [v4.0]
- * @return string JSON
*/
- public function show($assetMaintenanceId)
+ public function show($assetMaintenanceId) : JsonResponse
{
$this->authorize('view', Asset::class);
$assetMaintenance = AssetMaintenance::findOrFail($assetMaintenanceId);
diff --git a/app/Http/Controllers/Api/AssetModelsController.php b/app/Http/Controllers/Api/AssetModelsController.php
index e77c648b34..835f4d22e0 100644
--- a/app/Http/Controllers/Api/AssetModelsController.php
+++ b/app/Http/Controllers/Api/AssetModelsController.php
@@ -4,14 +4,16 @@ namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
+use App\Http\Requests\StoreAssetModelRequest;
use App\Http\Transformers\AssetModelsTransformer;
use App\Http\Transformers\AssetsTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Asset;
use App\Models\AssetModel;
use Illuminate\Http\Request;
-use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Http\JsonResponse;
/**
* This class controls all actions related to asset models for
@@ -27,9 +29,8 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', AssetModel::class);
$allowed_columns =
@@ -115,10 +116,9 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @param \App\Http\Requests\ImageUploadRequest $request
- * @return \Illuminate\Http\Response
+ * @param \App\Http\Requests\StoreAssetModelRequest $request
*/
- public function store(ImageUploadRequest $request)
+ public function store(StoreAssetModelRequest $request) : JsonResponse
{
$this->authorize('create', AssetModel::class);
$assetmodel = new AssetModel;
@@ -139,9 +139,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : array
{
$this->authorize('view', AssetModel::class);
$assetmodel = AssetModel::withCount('assets as assets_count')->findOrFail($id);
@@ -155,9 +154,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function assets($id)
+ public function assets($id) : array
{
$this->authorize('view', AssetModel::class);
$assets = Asset::where('model_id', '=', $id)->get();
@@ -175,7 +173,7 @@ class AssetModelsController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
- public function update(ImageUploadRequest $request, $id)
+ public function update(StoreAssetModelRequest $request, $id) : JsonResponse
{
$this->authorize('update', AssetModel::class);
$assetmodel = AssetModel::findOrFail($id);
@@ -208,9 +206,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', AssetModel::class);
$assetmodel = AssetModel::findOrFail($id);
@@ -224,7 +221,7 @@ class AssetModelsController extends Controller
try {
Storage::disk('public')->delete('assetmodels/'.$assetmodel->image);
} catch (\Exception $e) {
- \Log::info($e);
+ Log::info($e);
}
}
@@ -240,7 +237,7 @@ class AssetModelsController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
diff --git a/app/Http/Controllers/Api/AssetsController.php b/app/Http/Controllers/Api/AssetsController.php
index 92f1038cbd..f0ac97b7f9 100644
--- a/app/Http/Controllers/Api/AssetsController.php
+++ b/app/Http/Controllers/Api/AssetsController.php
@@ -25,19 +25,13 @@ use App\Models\License;
use App\Models\Location;
use App\Models\Setting;
use App\Models\User;
-use \Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
-use DB;
+use Illuminate\Support\Facades\DB;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Log;
-use Input;
-use Paginator;
-use Slack;
-use Str;
-use TCPDF;
-use Validator;
-use Route;
+use Illuminate\Support\Facades\Route;
/**
@@ -57,9 +51,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v4.0]
- * @return \Illuminate\Http\JsonResponse
*/
- public function index(Request $request, $audit = null)
+ public function index(Request $request, $action = null, $upcoming_status = null) : JsonResponse | array
{
$filter_non_deprecable_assets = false;
@@ -155,17 +148,44 @@ class AssetsController extends Controller
$assets->TextSearch($request->input('search'));
}
- // This is used by the audit reporting routes
- if (Gate::allows('audit', Asset::class)) {
- switch ($audit) {
- case 'due':
- $assets->DueOrOverdueForAudit($settings);
- break;
- case 'overdue':
- $assets->overdueForAudit($settings);
- break;
+
+ /**
+ * Handle due and overdue audits and checkin dates
+ */
+ switch ($action) {
+ case 'audits':
+
+ switch ($upcoming_status) {
+ case 'due':
+ $assets->DueForAudit($settings);
+ break;
+ case 'overdue':
+ $assets->OverdueForAudit();
+ break;
+ case 'due-or-overdue':
+ $assets->DueOrOverdueForAudit($settings);
+ break;
+ }
+ break;
+
+ case 'checkins':
+ switch ($upcoming_status) {
+ case 'due':
+ $assets->DueForCheckin($settings);
+ break;
+ case 'overdue':
+ $assets->OverdueForCheckin();
+ break;
+ case 'due-or-overdue':
+ $assets->DueOrOverdueForCheckin($settings);
+ break;
+ }
+ break;
}
- }
+
+ /**
+ * End handling due and overdue audits and checkin dates
+ */
// This is used by the sidenav, mostly
@@ -389,9 +409,8 @@ class AssetsController extends Controller
* @param string $tag
* @since [v4.2.1]
* @author [A. Gianotto] []
- * @return \Illuminate\Http\JsonResponse
*/
- public function showByTag(Request $request, $tag)
+ public function showByTag(Request $request, $tag) : JsonResponse | array
{
$this->authorize('index', Asset::class);
$assets = Asset::where('asset_tag', $tag)->with('assetstatus')->with('assignedTo');
@@ -429,7 +448,7 @@ class AssetsController extends Controller
* @since [v4.2.1]
* @return \Illuminate\Http\JsonResponse
*/
- public function showBySerial(Request $request, $serial)
+ public function showBySerial(Request $request, $serial) : JsonResponse | array
{
$this->authorize('index', Asset::class);
$assets = Asset::where('serial', $serial)->with('assetstatus')->with('assignedTo');
@@ -456,19 +475,20 @@ class AssetsController extends Controller
* @since [v4.0]
* @return \Illuminate\Http\JsonResponse
*/
- public function show(Request $request, $id)
+ public function show(Request $request, $id) : JsonResponse | array
{
- if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()
- ->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')->findOrFail($id)) {
+ if ($asset = Asset::with('assetstatus')
+ ->with('assignedTo')->withTrashed()
+ ->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')->find($id)) {
$this->authorize('view', $asset);
return (new AssetsTransformer)->transformAsset($asset, $request->input('components') );
}
-
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
}
- public function licenses(Request $request, $id)
+ public function licenses(Request $request, $id) : array
{
$this->authorize('view', Asset::class);
$this->authorize('view', License::class);
@@ -485,9 +505,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
- * @return \Illuminate\Http\JsonResponse
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
$assets = Asset::select([
@@ -612,7 +631,7 @@ class AssetsController extends Controller
$target = Location::find(request('assigned_location'));
}
if (isset($target)) {
- $asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e($request->get('name')));
+ $asset->checkOut($target, auth()->user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e($request->get('name')));
}
if ($asset->image) {
@@ -634,9 +653,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param \App\Http\Requests\ImageUploadRequest $request
* @since [v4.0]
- * @return \Illuminate\Http\JsonResponse
*/
- public function update(ImageUploadRequest $request, $id)
+ public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Asset::class);
@@ -665,25 +683,26 @@ class AssetsController extends Controller
$model = AssetModel::find($asset->model_id);
// Update custom fields
+ $problems_updating_encrypted_custom_fields = false;
if (($model) && (isset($model->fieldset))) {
foreach ($model->fieldset->fields as $field) {
$field_val = $request->input($field->db_column, null);
if ($request->has($field->db_column)) {
- if ($field->field_encrypted == '1') {
- if (Gate::allows('admin')) {
- $asset->{$field->db_column} = Crypt::encrypt($field_val);
- }
- }
if ($field->element == 'checkbox') {
if(is_array($field_val)) {
$field_val = implode(',', $field_val);
- $asset->{$field->db_column} = $field_val;
}
}
- else {
- $asset->{$field->db_column} = $field_val;
+ if ($field->field_encrypted == '1') {
+ if (Gate::allows('admin')) {
+ $field_val = Crypt::encrypt($field_val);
+ } else {
+ $problems_updating_encrypted_custom_fields = true;
+ continue;
+ }
}
+ $asset->{$field->db_column} = $field_val;
}
}
}
@@ -702,15 +721,18 @@ class AssetsController extends Controller
}
if (isset($target)) {
- $asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset update', e($request->get('name')), $location);
+ $asset->checkOut($target, auth()->user(), date('Y-m-d H:i:s'), '', 'Checked out on asset update', e($request->get('name')), $location);
}
if ($asset->image) {
$asset->image = $asset->getImageUrl();
}
- return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.update.success')));
- return response()->json(Helper::formatStandardApiResponse('success', (new AssetsTransformer)->transformAsset($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);
@@ -726,9 +748,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v4.0]
- * @return \Illuminate\Http\JsonResponse
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', Asset::class);
@@ -755,9 +776,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v5.1.18]
- * @return \Illuminate\Http\JsonResponse
*/
- public function restore(Request $request, $assetId = null)
+ public function restore(Request $request, $assetId = null) : JsonResponse
{
if ($asset = Asset::withTrashed()->find($assetId)) {
@@ -785,9 +805,8 @@ class AssetsController extends Controller
* @author [N. Butler]
* @param string $tag
* @since [v6.0.5]
- * @return \Illuminate\Http\JsonResponse
*/
- public function checkoutByTag(AssetCheckoutRequest $request, $tag)
+ public function checkoutByTag(AssetCheckoutRequest $request, $tag) : JsonResponse
{
if ($asset = Asset::where('asset_tag', $tag)->first()) {
return $this->checkout($request, $asset->id);
@@ -801,9 +820,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v4.0]
- * @return \Illuminate\Http\JsonResponse
*/
- public function checkout(AssetCheckoutRequest $request, $asset_id)
+ public function checkout(AssetCheckoutRequest $request, $asset_id) : JsonResponse
{
$this->authorize('checkout', Asset::class);
$asset = Asset::findOrFail($asset_id);
@@ -820,7 +838,6 @@ class AssetsController extends Controller
'asset_tag' => $asset->asset_tag,
];
-
// This item is checked out to a location
if (request('checkout_to_type') == 'location') {
$target = Location::find(request('assigned_location'));
@@ -847,13 +864,10 @@ class AssetsController extends Controller
$asset->status_id = $request->get('status_id');
}
-
if (! isset($target)) {
return response()->json(Helper::formatStandardApiResponse('error', $error_payload, 'Checkout target for asset '.e($asset->asset_tag).' is invalid - '.$error_payload['target_type'].' does not exist.'));
}
-
-
$checkout_at = request('checkout_at', date('Y-m-d H:i:s'));
$expected_checkin = request('expected_checkin', null);
$note = request('note', null);
@@ -869,9 +883,7 @@ class AssetsController extends Controller
// $asset->location_id = $target->rtd_location_id;
// }
-
-
- if ($asset->checkOut($target, Auth::user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) {
+ if ($asset->checkOut($target, auth()->user(), $checkout_at, $expected_checkin, $note, $asset_name, $asset->location_id)) {
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkout.success')));
}
@@ -885,9 +897,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v4.0]
- * @return \Illuminate\Http\JsonResponse
*/
- public function checkin(Request $request, $asset_id)
+ public function checkin(Request $request, $asset_id) : JsonResponse
{
$asset = Asset::with('model')->findOrFail($asset_id);
$this->authorize('checkin', $asset);
@@ -952,7 +963,7 @@ class AssetsController extends Controller
});
if ($asset->save()) {
- event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note'), $checkin_at, $originalValues));
+ event(new CheckoutableCheckedIn($asset, $target, auth()->user(), $request->input('note'), $checkin_at, $originalValues));
return response()->json(Helper::formatStandardApiResponse('success', [
'asset_tag'=> e($asset->asset_tag),
@@ -969,9 +980,8 @@ class AssetsController extends Controller
*
* @author [A. Janes] []
* @since [v6.0]
- * @return \Illuminate\Http\JsonResponse
*/
- public function checkinByTag(Request $request, $tag = null)
+ public function checkinByTag(Request $request, $tag = null) : JsonResponse
{
$this->authorize('checkin', Asset::class);
if(null == $tag && null !== ($request->input('asset_tag'))) {
@@ -995,31 +1005,44 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $id
* @since [v4.0]
- * @return \Illuminate\Http\JsonResponse
*/
- public function audit(Request $request)
+ public function audit(Request $request) : JsonResponse
{
$this->authorize('audit', Asset::class);
- $rules = [
- 'asset_tag' => 'required',
- 'location_id' => 'exists:locations,id|nullable|numeric',
- 'next_audit_date' => 'date|nullable',
- ];
-
- $validator = Validator::make($request->all(), $rules);
- if ($validator->fails()) {
- return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
- }
$settings = Setting::getSettings();
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
+ // No tag passed - return an error
+ if (!$request->filled('asset_tag')) {
+ return response()->json(Helper::formatStandardApiResponse('error', [
+ 'asset_tag'=> '',
+ 'error'=> trans('admin/hardware/message.no_tag'),
+ ], trans('admin/hardware/message.no_tag')), 200);
+ }
+
+
$asset = Asset::where('asset_tag', '=', $request->input('asset_tag'))->first();
if ($asset) {
- // We don't want to log this as a normal update, so let's bypass that
+
+ /**
+ * Even though we do a save() further down, we don't want to log this as a "normal" asset update,
+ * which would trigger the Asset Observer and would log an asset *update* log entry (because the
+ * de-normed fields like next_audit_date on the asset itself will change on save()) *in addition* to
+ * the audit log entry we're creating through this controller.
+ *
+ * To prevent this double-logging (one for update and one for audit), we skip the observer and bypass
+ * that de-normed update log entry by using unsetEventDispatcher(), BUT invoking unsetEventDispatcher()
+ * will bypass normal model-level validation that's usually handled at the observer )
+ *
+ * We handle validation on the save() by checking if the asset is valid via the ->isValid() method,
+ * which manually invokes Watson Validating to make sure the asset's model is valid.
+ *
+ * @see \App\Observers\AssetObserver::updating()
+ */
$asset->unsetEventDispatcher();
$asset->next_audit_date = $dt;
@@ -1035,8 +1058,12 @@ class AssetsController extends Controller
$asset->last_audit_date = date('Y-m-d H:i:s');
- if ($asset->save()) {
- $log = $asset->logAudit(request('note'), request('location_id'));
+ /**
+ * Invoke Watson Validating to check the asset itself and check to make sure it saved correctly.
+ * We have to invoke this manually because of the unsetEventDispatcher() above.)
+ */
+ if ($asset->isValid() && $asset->save()) {
+ $asset->logAudit(request('note'), request('location_id'));
return response()->json(Helper::formatStandardApiResponse('success', [
'asset_tag'=> e($asset->asset_tag),
@@ -1044,9 +1071,23 @@ class AssetsController extends Controller
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date),
], trans('admin/hardware/message.audit.success')));
}
+
+ // Asset failed validation or was not able to be saved
+ return response()->json(Helper::formatStandardApiResponse('error', [
+ 'asset_tag'=> e($asset->asset_tag),
+ 'error'=> $asset->getErrors()->first(),
+ ], trans('admin/hardware/message.audit.error', ['error' => $asset->getErrors()->first()])), 200);
+
}
- return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag'=> e($request->input('asset_tag'))], 'Asset with tag '.e($request->input('asset_tag')).' not found'));
+
+ // No matching asset for the asset tag that was passed.
+ return response()->json(Helper::formatStandardApiResponse('error', [
+ 'asset_tag'=> e($request->input('asset_tag')),
+ 'error'=> trans('admin/hardware/message.audit.error'),
+ ], trans('admin/hardware/message.audit.error', ['error' => trans('admin/hardware/message.does_not_exist')])), 200);
+
+
}
@@ -1056,9 +1097,8 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return \Illuminate\Http\JsonResponse
*/
- public function requestable(Request $request)
+ public function requestable(Request $request) : JsonResponse | array
{
$this->authorize('viewRequestable', Asset::class);
diff --git a/app/Http/Controllers/Api/CategoriesController.php b/app/Http/Controllers/Api/CategoriesController.php
index 2aa4b3741c..6e9866f90b 100644
--- a/app/Http/Controllers/Api/CategoriesController.php
+++ b/app/Http/Controllers/Api/CategoriesController.php
@@ -8,9 +8,9 @@ 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\Support\Facades\Validator;
class CategoriesController extends Controller
{
@@ -21,7 +21,7 @@ class CategoriesController extends Controller
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : array
{
$this->authorize('view', Category::class);
$allowed_columns = [
@@ -115,7 +115,7 @@ class CategoriesController extends Controller
* @param \App\Http\Requests\ImageUploadRequest $request
* @return \Illuminate\Http\Response
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Category::class);
$category = new Category;
@@ -136,9 +136,8 @@ class CategoriesController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : array
{
$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);
@@ -156,7 +155,7 @@ class CategoriesController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
- public function update(ImageUploadRequest $request, $id)
+ public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Category::class);
$category = Category::findOrFail($id);
@@ -164,7 +163,7 @@ class CategoriesController extends Controller
// Don't allow the user to change the category_type once it's been created
if (($request->filled('category_type')) && ($category->category_type != $request->input('category_type'))) {
return response()->json(
- Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.update.cannot_change_category_type'))
+ Helper::formatStandardApiResponse('error', null, ['category_type' => trans('admin/categories/message.update.cannot_change_category_type')], 422)
);
}
$category->fill($request->all());
@@ -185,7 +184,7 @@ class CategoriesController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', 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);
@@ -208,7 +207,7 @@ class CategoriesController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request, $category_type = 'asset')
+ public function selectlist(Request $request, $category_type = 'asset') : array
{
$this->authorize('view.selectlists');
$categories = Category::select([
diff --git a/app/Http/Controllers/Api/CompaniesController.php b/app/Http/Controllers/Api/CompaniesController.php
index 9c667973a3..0d78df9acc 100644
--- a/app/Http/Controllers/Api/CompaniesController.php
+++ b/app/Http/Controllers/Api/CompaniesController.php
@@ -10,6 +10,7 @@ use App\Models\Company;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
+use Illuminate\Http\JsonResponse;
class CompaniesController extends Controller
{
@@ -18,9 +19,8 @@ class CompaniesController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Company::class);
@@ -79,9 +79,8 @@ class CompaniesController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
- * @return \Illuminate\Http\Response
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Company::class);
$company = new Company;
@@ -102,9 +101,8 @@ class CompaniesController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : array
{
$this->authorize('view', Company::class);
$company = Company::findOrFail($id);
@@ -120,9 +118,8 @@ class CompaniesController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(ImageUploadRequest $request, $id)
+ public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Company::class);
$company = Company::findOrFail($id);
@@ -144,9 +141,8 @@ class CompaniesController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', Company::class);
$company = Company::findOrFail($id);
@@ -169,7 +165,7 @@ class CompaniesController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
$companies = Company::select([
diff --git a/app/Http/Controllers/Api/ComponentsController.php b/app/Http/Controllers/Api/ComponentsController.php
index 9202b10b71..69bd828487 100644
--- a/app/Http/Controllers/Api/ComponentsController.php
+++ b/app/Http/Controllers/Api/ComponentsController.php
@@ -5,15 +5,17 @@ namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\ComponentsTransformer;
-use App\Models\Company;
use App\Models\Component;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use App\Events\CheckoutableCheckedIn;
-use App\Events\ComponentCheckedIn;
use App\Models\Asset;
use Illuminate\Support\Facades\Validator;
use Illuminate\Database\Query\Builder;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Http\JsonResponse;
+use Illuminate\Support\Facades\DB;
+use Carbon\Carbon;
class ComponentsController extends Controller
{
@@ -23,9 +25,8 @@ class ComponentsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
*
- * @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Component::class);
@@ -115,9 +116,8 @@ class ComponentsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
- * @return \Illuminate\Http\Response
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Component::class);
$component = new Component;
@@ -136,9 +136,8 @@ class ComponentsController extends Controller
*
* @author [A. Gianotto] []
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : array
{
$this->authorize('view', Component::class);
$component = Component::findOrFail($id);
@@ -155,9 +154,8 @@ class ComponentsController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(ImageUploadRequest $request, $id)
+ public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Component::class);
$component = Component::findOrFail($id);
@@ -178,9 +176,8 @@ class ComponentsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', Component::class);
$component = Component::findOrFail($id);
@@ -197,9 +194,8 @@ class ComponentsController extends Controller
* @since [v4.0]
* @param Request $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function getAssets(Request $request, $id)
+ public function getAssets(Request $request, $id) : array
{
$this->authorize('view', \App\Models\Asset::class);
@@ -240,10 +236,8 @@ class ComponentsController extends Controller
* @since [v5.1.8]
* @param Request $request
* @param int $componentId
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function checkout(Request $request, $componentId)
+ public function checkout(Request $request, $componentId) : JsonResponse
{
// Check if the component exists
if (!$component = Component::find($componentId)) {
@@ -274,9 +268,9 @@ class ComponentsController extends Controller
$component->assets()->attach($component->id, [
'component_id' => $component->id,
- 'created_at' => \Carbon::now(),
+ 'created_at' => Carbon::now(),
'assigned_qty' => $request->get('assigned_qty', 1),
- 'user_id' => \Auth::id(),
+ 'user_id' => auth()->id(),
'asset_id' => $request->get('assigned_to'),
'note' => $request->get('note'),
]);
@@ -296,12 +290,10 @@ class ComponentsController extends Controller
* @since [v5.1.8]
* @param Request $request
* @param $component_asset_id
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function checkin(Request $request, $component_asset_id)
+ public function checkin(Request $request, $component_asset_id) : JsonResponse
{
- if ($component_assets = \DB::table('components_assets')->find($component_asset_id)) {
+ if ($component_assets = DB::table('components_assets')->find($component_asset_id)) {
if (is_null($component = Component::find($component_assets->component_id))) {
@@ -314,7 +306,7 @@ class ComponentsController extends Controller
if ($max_to_checkin > 1) {
- $validator = \Validator::make($request->all(), [
+ $validator = Validator::make($request->all(), [
"checkin_qty" => "required|numeric|between:1,$max_to_checkin"
]);
@@ -331,21 +323,21 @@ class ComponentsController extends Controller
// actually checked out.
$component_assets->assigned_qty = $qty_remaining_in_checkout;
- \Log::debug($component_asset_id.' - '.$qty_remaining_in_checkout.' remaining in record '.$component_assets->id);
+ Log::debug($component_asset_id.' - '.$qty_remaining_in_checkout.' remaining in record '.$component_assets->id);
- \DB::table('components_assets')->where('id',
+ DB::table('components_assets')->where('id',
$component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]);
// If the checked-in qty is exactly the same as the assigned_qty,
// we can simply delete the associated components_assets record
if ($qty_remaining_in_checkout == 0) {
- \DB::table('components_assets')->where('id', '=', $component_asset_id)->delete();
+ DB::table('components_assets')->where('id', '=', $component_asset_id)->delete();
}
$asset = Asset::find($component_assets->asset_id);
- event(new CheckoutableCheckedIn($component, $asset, \Auth::user(), $request->input('note'), \Carbon::now()));
+ event(new CheckoutableCheckedIn($component, $asset, auth()->user(), $request->input('note'), Carbon::now()));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/components/message.checkin.success')));
diff --git a/app/Http/Controllers/Api/ConsumablesController.php b/app/Http/Controllers/Api/ConsumablesController.php
index d6e3350ddc..1665b7f4f0 100644
--- a/app/Http/Controllers/Api/ConsumablesController.php
+++ b/app/Http/Controllers/Api/ConsumablesController.php
@@ -5,6 +5,7 @@ namespace App\Http\Controllers\Api;
use App\Events\CheckoutableCheckedOut;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
+use App\Http\Requests\StoreConsumableRequest;
use App\Http\Transformers\ConsumablesTransformer;
use App\Http\Transformers\SelectlistTransformer;
use App\Models\Company;
@@ -12,7 +13,8 @@ use App\Models\Consumable;
use App\Models\User;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
-use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Http\JsonResponse;
class ConsumablesController extends Controller
{
@@ -21,34 +23,13 @@ class ConsumablesController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- *
- * @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : array
{
$this->authorize('index', Consumable::class);
- // This array is what determines which fields should be allowed to be sorted on ON the table itself, no relations
- // Relations will be handled in query scopes a little further down.
- $allowed_columns =
- [
- 'id',
- 'name',
- 'order_number',
- 'min_amt',
- 'purchase_date',
- 'purchase_cost',
- 'company',
- 'category',
- 'model_number',
- 'item_no',
- 'qty',
- 'image',
- 'notes',
- ];
-
- $consumables = Consumable::select('consumables.*')
- ->with('company', 'location', 'category', 'users', 'manufacturer');
+ $consumables = Consumable::with('company', 'location', 'category', 'supplier', 'manufacturer')
+ ->withCount('users as consumables_users_count');
if ($request->filled('search')) {
$consumables = $consumables->TextSearch(e($request->input('search')));
@@ -90,15 +71,9 @@ class ConsumablesController extends Controller
// Make sure the offset and limit are actually integers and do not exceed system limits
$offset = ($request->input('offset') > $consumables->count()) ? $consumables->count() : app('api_offset_value');
$limit = app('api_limit_value');
-
- $allowed_columns = ['id', 'name', 'order_number', 'min_amt', 'purchase_date', 'purchase_cost', 'company', 'category', 'model_number', 'item_no', 'manufacturer', 'location', 'qty', 'image'];
$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) {
+ switch ($request->input('sort')) {
case 'category':
$consumables = $consumables->OrderCategory($order);
break;
@@ -112,10 +87,30 @@ class ConsumablesController extends Controller
$consumables = $consumables->OrderCompany($order);
break;
case 'supplier':
- $components = $consumables->OrderSupplier($order);
+ $consumables = $consumables->OrderSupplier($order);
break;
default:
- $consumables = $consumables->orderBy($column_sort, $order);
+ // 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',
+ 'order_number',
+ 'min_amt',
+ 'purchase_date',
+ 'purchase_cost',
+ 'company',
+ 'category',
+ 'model_number',
+ 'item_no',
+ 'manufacturer',
+ 'location',
+ 'qty',
+ 'image'
+ ];
+
+ $sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
+ $consumables = $consumables->orderBy($sort, $order);
break;
}
@@ -131,9 +126,8 @@ class ConsumablesController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
- * @return \Illuminate\Http\Response
*/
- public function store(ImageUploadRequest $request)
+ public function store(StoreConsumableRequest $request) : JsonResponse
{
$this->authorize('create', Consumable::class);
$consumable = new Consumable;
@@ -152,9 +146,8 @@ class ConsumablesController extends Controller
*
* @author [A. Gianotto] []
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : array
{
$this->authorize('view', Consumable::class);
$consumable = Consumable::with('users')->findOrFail($id);
@@ -169,9 +162,8 @@ class ConsumablesController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(ImageUploadRequest $request, $id)
+ public function update(StoreConsumableRequest $request, $id) : JsonResponse
{
$this->authorize('update', Consumable::class);
$consumable = Consumable::findOrFail($id);
@@ -191,9 +183,8 @@ class ConsumablesController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', Consumable::class);
$consumable = Consumable::findOrFail($id);
@@ -210,9 +201,8 @@ class ConsumablesController extends Controller
* @see \App\Http\Controllers\Consumables\ConsumablesController::getView() method that returns the form.
* @since [v1.0]
* @param int $consumableId
- * @return array
*/
- public function getDataView($consumableId)
+ public function getDataView($consumableId) : array
{
$consumable = Consumable::with(['consumableAssignments'=> function ($query) {
$query->orderBy($query->getModel()->getTable().'.created_at', 'DESC');
@@ -251,9 +241,8 @@ class ConsumablesController extends Controller
* @author [A. Gutierrez] []
* @param int $id
* @since [v4.9.5]
- * @return JsonResponse
*/
- public function checkout(Request $request, $id)
+ public function checkout(Request $request, $id) : JsonResponse
{
// Check if the consumable exists
if (!$consumable = Consumable::with('users')->find($id)) {
@@ -277,7 +266,6 @@ class ConsumablesController extends Controller
if (!$user = User::find($request->input('assigned_to'))) {
// Return error message
return response()->json(Helper::formatStandardApiResponse('error', null, 'No user found'));
- \Log::debug('No valid user');
}
// Update the consumable data
@@ -292,7 +280,7 @@ class ConsumablesController extends Controller
]
);
- event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note')));
+ event(new CheckoutableCheckedOut($consumable, $user, auth()->user(), $request->input('note')));
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/consumables/message.checkout.success')));
@@ -303,7 +291,7 @@ class ConsumablesController extends Controller
*
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
$consumables = Consumable::select([
'consumables.id',
diff --git a/app/Http/Controllers/Api/CustomFieldsController.php b/app/Http/Controllers/Api/CustomFieldsController.php
index 688e1146f3..207a92e274 100644
--- a/app/Http/Controllers/Api/CustomFieldsController.php
+++ b/app/Http/Controllers/Api/CustomFieldsController.php
@@ -8,7 +8,8 @@ use App\Http\Transformers\CustomFieldsTransformer;
use App\Models\CustomField;
use App\Models\CustomFieldset;
use Illuminate\Http\Request;
-use Validator;
+use Illuminate\Support\Facades\Validator;
+use Illuminate\Http\JsonResponse;
class CustomFieldsController extends Controller
{
@@ -20,7 +21,7 @@ class CustomFieldsController extends Controller
* @since [v3.0]
* @return array
*/
- public function index()
+ public function index() : array
{
$this->authorize('index', CustomField::class);
$fields = CustomField::get();
@@ -33,9 +34,8 @@ class CustomFieldsController extends Controller
* @author [V. Cordes] []
* @param int $id
* @since [v4.1.10]
- * @return View
*/
- public function show($id)
+ public function show($id) : JsonResponse | array
{
$this->authorize('view', CustomField::class);
if ($field = CustomField::find($id)) {
@@ -52,9 +52,8 @@ class CustomFieldsController extends Controller
* @since [v4.1.10]
* @param \Illuminate\Http\Request $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(Request $request, $id)
+ public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', CustomField::class);
$field = CustomField::findOrFail($id);
@@ -86,9 +85,8 @@ class CustomFieldsController extends Controller
* @author [V. Cordes] []
* @since [v4.1.10]
* @param \Illuminate\Http\Request $request
- * @return \Illuminate\Http\Response
*/
- public function store(Request $request)
+ public function store(Request $request) : JsonResponse
{
$this->authorize('create', CustomField::class);
$field = new CustomField;
@@ -136,7 +134,7 @@ class CustomFieldsController extends Controller
return $fieldset->fields()->sync($fields);
}
- public function associate(Request $request, $field_id)
+ public function associate(Request $request, $field_id) : JsonResponse
{
$this->authorize('update', CustomFieldset::class);
@@ -155,10 +153,9 @@ class CustomFieldsController extends Controller
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.update.success')));
}
- public function disassociate(Request $request, $field_id)
+ public function disassociate(Request $request, $field_id) : JsonResponse
{
$this->authorize('update', CustomFieldset::class);
-
$field = CustomField::findOrFail($field_id);
$fieldset_id = $request->input('fieldset_id');
@@ -179,9 +176,8 @@ class CustomFieldsController extends Controller
*
* @author [Brady Wetherington] []
* @since [v1.8]
- * @return Redirect
*/
- public function destroy($field_id)
+ public function destroy($field_id) : JsonResponse
{
$field = CustomField::findOrFail($field_id);
diff --git a/app/Http/Controllers/Api/CustomFieldsetsController.php b/app/Http/Controllers/Api/CustomFieldsetsController.php
index df0fc940cf..5dbd507917 100644
--- a/app/Http/Controllers/Api/CustomFieldsetsController.php
+++ b/app/Http/Controllers/Api/CustomFieldsetsController.php
@@ -9,8 +9,7 @@ use App\Http\Transformers\CustomFieldsTransformer;
use App\Models\CustomFieldset;
use App\Models\CustomField;
use Illuminate\Http\Request;
-use Redirect;
-use View;
+use Illuminate\Http\JsonResponse;
/**
* This controller handles all actions related to Custom Asset Fieldsets for
@@ -30,9 +29,8 @@ class CustomFieldsetsController extends Controller
* @author [Josh Gibson]
* @param int $id
* @since [v1.8]
- * @return View
*/
- public function index()
+ public function index() : array
{
$this->authorize('index', CustomField::class);
$fieldsets = CustomFieldset::withCount('fields as fields_count', 'models as models_count')->get();
@@ -46,9 +44,8 @@ class CustomFieldsetsController extends Controller
* @author [Josh Gibson]
* @param int $id
* @since [v1.8]
- * @return View
*/
- public function show($id)
+ public function show($id) : JsonResponse | array
{
$this->authorize('view', CustomField::class);
if ($fieldset = CustomFieldset::find($id)) {
@@ -65,9 +62,8 @@ class CustomFieldsetsController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(Request $request, $id)
+ public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', CustomField::class);
$fieldset = CustomFieldset::findOrFail($id);
@@ -86,9 +82,8 @@ class CustomFieldsetsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \Illuminate\Http\Request $request
- * @return \Illuminate\Http\Response
*/
- public function store(Request $request)
+ public function store(Request $request) : JsonResponse
{
$this->authorize('create', CustomField::class);
$fieldset = new CustomFieldset;
@@ -118,9 +113,8 @@ class CustomFieldsetsController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return Redirect
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', CustomField::class);
$fieldset = CustomFieldset::findOrFail($id);
@@ -147,7 +141,7 @@ class CustomFieldsetsController extends Controller
* @param $fieldsetId
* @return string JSON
*/
- public function fields($id)
+ public function fields($id) : array
{
$this->authorize('view', CustomField::class);
$set = CustomFieldset::findOrFail($id);
@@ -164,14 +158,11 @@ class CustomFieldsetsController extends Controller
* @param $fieldsetId
* @return string JSON
*/
- public function fieldsWithDefaultValues($fieldsetId, $modelId)
+ public function fieldsWithDefaultValues($fieldsetId, $modelId) : array
{
$this->authorize('view', CustomField::class);
-
$set = CustomFieldset::findOrFail($fieldsetId);
-
$fields = $set->fields;
-
return (new CustomFieldsTransformer)->transformCustomFieldsWithDefaultValues($fields, $modelId, $fields->count());
}
}
diff --git a/app/Http/Controllers/Api/DepartmentsController.php b/app/Http/Controllers/Api/DepartmentsController.php
index f211089b93..eabc79ec2b 100644
--- a/app/Http/Controllers/Api/DepartmentsController.php
+++ b/app/Http/Controllers/Api/DepartmentsController.php
@@ -6,12 +6,11 @@ use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Transformers\DepartmentsTransformer;
use App\Http\Transformers\SelectlistTransformer;
-use App\Models\Company;
use App\Models\Department;
-use Auth;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
+use Illuminate\Http\JsonResponse;
class DepartmentsController extends Controller
{
@@ -20,9 +19,8 @@ class DepartmentsController extends Controller
*
* @author [Godfrey Martinez] []
* @since [v4.0]
- * @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Department::class);
$allowed_columns = ['id', 'name', 'image', 'users_count'];
@@ -91,16 +89,15 @@ class DepartmentsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
- * @return \Illuminate\Http\Response
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Department::class);
$department = new Department;
$department->fill($request->all());
$department = $request->handleImages($department);
- $department->user_id = Auth::user()->id;
+ $department->user_id = auth()->id();
$department->manager_id = ($request->filled('manager_id') ? $request->input('manager_id') : null);
if ($department->save()) {
@@ -116,13 +113,11 @@ class DepartmentsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : array
{
$this->authorize('view', Department::class);
$department = Department::findOrFail($id);
-
return (new DepartmentsTransformer)->transformDepartment($department);
}
@@ -133,9 +128,8 @@ class DepartmentsController extends Controller
* @since [v5.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(ImageUploadRequest $request, $id)
+ public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Department::class);
$department = Department::findOrFail($id);
@@ -156,9 +150,8 @@ class DepartmentsController extends Controller
* @author [A. Gianotto] []
* @param int $locationId
* @since [v4.0]
- * @return \Illuminate\Http\RedirectResponse
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$department = Department::findOrFail($id);
@@ -180,7 +173,7 @@ class DepartmentsController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
diff --git a/app/Http/Controllers/Api/DepreciationsController.php b/app/Http/Controllers/Api/DepreciationsController.php
index 502a0741b7..93088bb04a 100644
--- a/app/Http/Controllers/Api/DepreciationsController.php
+++ b/app/Http/Controllers/Api/DepreciationsController.php
@@ -7,6 +7,7 @@ use App\Http\Controllers\Controller;
use App\Http\Transformers\DepreciationsTransformer;
use App\Models\Depreciation;
use Illuminate\Http\Request;
+use Illuminate\Http\JsonResponse;
class DepreciationsController extends Controller
{
@@ -15,9 +16,8 @@ class DepreciationsController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Depreciation::class);
$allowed_columns = ['id','name','months','depreciation_min','created_at'];
@@ -48,9 +48,8 @@ class DepreciationsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \Illuminate\Http\Request $request
- * @return \Illuminate\Http\Response
*/
- public function store(Request $request)
+ public function store(Request $request) : JsonResponse
{
$this->authorize('create', Depreciation::class);
$depreciation = new Depreciation;
@@ -69,9 +68,8 @@ class DepreciationsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : JsonResponse | array
{
$this->authorize('view', Depreciation::class);
$depreciation = Depreciation::findOrFail($id);
@@ -86,9 +84,8 @@ class DepreciationsController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(Request $request, $id)
+ public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', Depreciation::class);
$depreciation = Depreciation::findOrFail($id);
@@ -107,9 +104,8 @@ class DepreciationsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', Depreciation::class);
$depreciation = Depreciation::withCount('models as models_count')->findOrFail($id);
diff --git a/app/Http/Controllers/Api/GroupsController.php b/app/Http/Controllers/Api/GroupsController.php
index 5a441e41ce..878650c718 100644
--- a/app/Http/Controllers/Api/GroupsController.php
+++ b/app/Http/Controllers/Api/GroupsController.php
@@ -7,7 +7,7 @@ use App\Http\Controllers\Controller;
use App\Http\Transformers\GroupsTransformer;
use App\Models\Group;
use Illuminate\Http\Request;
-use Auth;
+use Illuminate\Http\JsonResponse;
class GroupsController extends Controller
@@ -17,9 +17,8 @@ class GroupsController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('superadmin');
@@ -56,19 +55,21 @@ class GroupsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \Illuminate\Http\Request $request
- * @return \Illuminate\Http\Response
*/
- public function store(Request $request)
+ public function store(Request $request) : JsonResponse
{
$this->authorize('superadmin');
$group = new Group;
+ // Get all the available permissions
+ $permissions = config('permissions');
+ $groupPermissions = Helper::selectedPermissionsArray($permissions, $permissions);
$group->name = $request->input('name');
- $group->created_by = Auth::user()->id;
- $group->permissions = json_encode($request->input('permissions')); // Todo - some JSON validation stuff here
+ $group->created_by = auth()->id();
+ $group->permissions = json_encode($request->input('permissions', $groupPermissions));
if ($group->save()) {
- return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.create.success')));
+ return response()->json(Helper::formatStandardApiResponse('success', (new GroupsTransformer)->transformGroup($group), trans('admin/groups/message.success.create')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $group->getErrors()));
@@ -80,13 +81,11 @@ class GroupsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : array
{
$this->authorize('superadmin');
$group = Group::findOrFail($id);
-
return (new GroupsTransformer)->transformGroup($group);
}
@@ -97,9 +96,8 @@ class GroupsController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(Request $request, $id)
+ public function update(Request $request, $id) : JsonResponse
{
$this->authorize('superadmin');
$group = Group::findOrFail($id);
@@ -108,7 +106,7 @@ class GroupsController extends Controller
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
if ($group->save()) {
- return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.update.success')));
+ return response()->json(Helper::formatStandardApiResponse('success', (new GroupsTransformer)->transformGroup($group), trans('admin/groups/message.success.update')));
}
return response()->json(Helper::formatStandardApiResponse('error', null, $group->getErrors()));
@@ -120,9 +118,8 @@ class GroupsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('superadmin');
$group = Group::findOrFail($id);
diff --git a/app/Http/Controllers/Api/ImportController.php b/app/Http/Controllers/Api/ImportController.php
index 2d7e2f7d78..13f4301217 100644
--- a/app/Http/Controllers/Api/ImportController.php
+++ b/app/Http/Controllers/Api/ImportController.php
@@ -9,22 +9,23 @@ use App\Http\Transformers\ImportsTransformer;
use App\Models\Asset;
use App\Models\Company;
use App\Models\Import;
-use Artisan;
+use Illuminate\Support\Facades\Artisan;
use Illuminate\Database\Eloquent\JsonEncodingException;
use Illuminate\Support\Facades\Request;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Storage;
use League\Csv\Reader;
use Symfony\Component\HttpFoundation\File\Exception\FileException;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Http\JsonResponse;
class ImportController extends Controller
{
/**
* Display a listing of the resource.
*
- * @return \Illuminate\Http\Response
*/
- public function index()
+ public function index() : JsonResponse | array
{
$this->authorize('import');
$imports = Import::latest()->get();
@@ -36,9 +37,8 @@ class ImportController extends Controller
* Process and store a CSV upload file.
*
* @param \Illuminate\Http\Request $request
- * @return \Illuminate\Http\JsonResponse
*/
- public function store()
+ public function store() : JsonResponse
{
$this->authorize('import');
if (! config('app.lock_passwords')) {
@@ -151,18 +151,17 @@ class ImportController extends Controller
* Processes the specified Import.
*
* @param int $import_id
- * @return \Illuminate\Http\Response
*/
- public function process(ItemImportRequest $request, $import_id)
+ public function process(ItemImportRequest $request, $import_id) : JsonResponse
{
$this->authorize('import');
// Run a backup immediately before processing
if ($request->get('run-backup')) {
- \Log::debug('Backup manually requested via importer');
+ Log::debug('Backup manually requested via importer');
Artisan::call('snipeit:backup', ['--filename' => 'pre-import-backup-'.date('Y-m-d-H:i:s')]);
} else {
- \Log::debug('NO BACKUP requested via importer');
+ Log::debug('NO BACKUP requested via importer');
}
$import = Import::find($import_id);
@@ -211,9 +210,8 @@ class ImportController extends Controller
* Remove the specified resource from storage.
*
* @param int $import_id
- * @return \Illuminate\Http\Response
*/
- public function destroy($import_id)
+ public function destroy($import_id) : JsonResponse
{
$this->authorize('create', Asset::class);
@@ -230,6 +228,8 @@ class ImportController extends Controller
return response()->json(Helper::formatStandardApiResponse('warning', null, trans('admin/hardware/message.import.file_not_deleted_warning')));
}
+
}
+ return response()->json(Helper::formatStandardApiResponse('warning', null, trans('admin/hardware/message.import.file_not_deleted_warning')));
}
}
diff --git a/app/Http/Controllers/Api/LabelsController.php b/app/Http/Controllers/Api/LabelsController.php
index 6576ec0373..0b54235422 100644
--- a/app/Http/Controllers/Api/LabelsController.php
+++ b/app/Http/Controllers/Api/LabelsController.php
@@ -8,7 +8,7 @@ use App\Http\Transformers\LabelsTransformer;
use App\Models\Labels\Label;
use Illuminate\Http\Request;
use Illuminate\Support\ItemNotFoundException;
-use Auth;
+use Illuminate\Http\JsonResponse;
class LabelsController extends Controller
{
@@ -16,9 +16,8 @@ class LabelsController extends Controller
* Returns JSON listing of all labels.
*
* @author Grant Le Roux
- * @return JsonResponse
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Label::class);
@@ -50,9 +49,8 @@ class LabelsController extends Controller
*
* @author Grant Le Roux
* @param string $labelName
- * @return JsonResponse
*/
- public function show(string $labelName)
+ public function show(string $labelName) : JsonResponse | array
{
$labelName = str_replace('/', '\\', $labelName);
try {
diff --git a/app/Http/Controllers/Api/LicenseSeatsController.php b/app/Http/Controllers/Api/LicenseSeatsController.php
index 5e79c49b23..a9630aa296 100644
--- a/app/Http/Controllers/Api/LicenseSeatsController.php
+++ b/app/Http/Controllers/Api/LicenseSeatsController.php
@@ -9,7 +9,7 @@ use App\Models\Asset;
use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\User;
-use Auth;
+use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
class LicenseSeatsController extends Controller
@@ -19,11 +19,10 @@ class LicenseSeatsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $licenseId
- * @return \Illuminate\Http\Response
*/
- public function index(Request $request, $licenseId)
+ public function index(Request $request, $licenseId) : JsonResponse | array
{
- //
+
if ($license = License::find($licenseId)) {
$this->authorize('view', $license);
@@ -64,11 +63,10 @@ class LicenseSeatsController extends Controller
*
* @param int $licenseId
* @param int $seatId
- * @return \Illuminate\Http\Response
*/
- public function show($licenseId, $seatId)
+ public function show($licenseId, $seatId) : JsonResponse | array
{
- //
+
$this->authorize('view', License::class);
// sanity checks:
// 1. does the license seat exist?
@@ -89,19 +87,18 @@ class LicenseSeatsController extends Controller
* @param \Illuminate\Http\Request $request
* @param int $licenseId
* @param int $seatId
- * @return \Illuminate\Http\Response
*/
- public function update(Request $request, $licenseId, $seatId)
+ public function update(Request $request, $licenseId, $seatId) : JsonResponse | array
{
$this->authorize('checkout', License::class);
- // sanity checks:
- // 1. does the license seat exist?
+
if (! $licenseSeat = LicenseSeat::find($seatId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Seat not found'));
}
- // 2. does the seat belong to the specified license?
- if (! $license = $licenseSeat->license()->first() || $license->id != intval($licenseId)) {
+
+ $license = $licenseSeat->license()->first();
+ if (!$license || $license->id != intval($licenseId)) {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Seat does not belong to the specified license'));
}
@@ -110,7 +107,7 @@ class LicenseSeatsController extends Controller
// attempt to update the license seat
$licenseSeat->fill($request->all());
- $licenseSeat->user_id = Auth::user()->id;
+ $licenseSeat->user_id = auth()->id();
// check if this update is a checkin operation
// 1. are relevant fields touched at all?
diff --git a/app/Http/Controllers/Api/LicensesController.php b/app/Http/Controllers/Api/LicensesController.php
index c35b669d70..579d80eeb5 100644
--- a/app/Http/Controllers/Api/LicensesController.php
+++ b/app/Http/Controllers/Api/LicensesController.php
@@ -4,14 +4,12 @@ namespace App\Http\Controllers\Api;
use App\Helpers\Helper;
use App\Http\Controllers\Controller;
-use App\Http\Transformers\LicenseSeatsTransformer;
use App\Http\Transformers\LicensesTransformer;
use App\Http\Transformers\SelectlistTransformer;
-use App\Models\Company;
use App\Models\License;
-use App\Models\LicenseSeat;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\DB;
+use Illuminate\Http\JsonResponse;
class LicensesController extends Controller
{
@@ -21,9 +19,8 @@ class LicensesController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
*
- * @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', License::class);
@@ -156,11 +153,9 @@ class LicensesController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \Illuminate\Http\Request $request
- * @return \Illuminate\Http\Response
*/
- public function store(Request $request)
+ public function store(Request $request) : JsonResponse
{
- //
$this->authorize('create', License::class);
$license = new License;
$license->fill($request->all());
@@ -177,9 +172,8 @@ class LicensesController extends Controller
*
* @author [A. Gianotto] []
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : JsonResponse | array
{
$this->authorize('view', License::class);
$license = License::withCount('freeSeats')->findOrFail($id);
@@ -195,9 +189,8 @@ class LicensesController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(Request $request, $id)
+ public function update(Request $request, $id) : JsonResponse | array
{
//
$this->authorize('update', License::class);
@@ -218,9 +211,8 @@ class LicensesController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
//
$license = License::findOrFail($id);
@@ -248,7 +240,7 @@ class LicensesController extends Controller
*
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
$licenses = License::select([
'licenses.id',
diff --git a/app/Http/Controllers/Api/LocationsController.php b/app/Http/Controllers/Api/LocationsController.php
index b46c13e13e..2ceeb8374e 100644
--- a/app/Http/Controllers/Api/LocationsController.php
+++ b/app/Http/Controllers/Api/LocationsController.php
@@ -11,6 +11,7 @@ use App\Models\Location;
use Illuminate\Http\Request;
use Illuminate\Pagination\LengthAwarePaginator;
use Illuminate\Support\Collection;
+use Illuminate\Http\JsonResponse;
class LocationsController extends Controller
{
@@ -21,7 +22,7 @@ class LocationsController extends Controller
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', Location::class);
$allowed_columns = [
@@ -138,9 +139,8 @@ class LocationsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
- * @return \Illuminate\Http\Response
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Location::class);
$location = new Location;
@@ -160,9 +160,8 @@ class LocationsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : JsonResponse | array
{
$this->authorize('view', Location::class);
$location = Location::with('parent', 'manager', 'children')
@@ -199,9 +198,8 @@ class LocationsController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
- * @return \Illuminate\Http\JsonResponse
*/
- public function update(ImageUploadRequest $request, $id)
+ public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Location::class);
$location = Location::findOrFail($id);
@@ -230,9 +228,8 @@ class LocationsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', Location::class);
$location = Location::withCount('assignedAssets as assigned_assets_count')
@@ -244,7 +241,7 @@ class LocationsController extends Controller
if (! $location->isDeletable()) {
return response()
- ->json(Helper::formatStandardApiResponse('error', null, trans('admin/companies/message.assoc_users')));
+ ->json(Helper::formatStandardApiResponse('error', null, trans('admin/locations/message.assoc_users')));
}
$this->authorize('delete', $location);
$location->delete();
@@ -280,7 +277,7 @@ class LocationsController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
// If a user is in the process of editing their profile, as determined by the referrer,
// then we check that they have permission to edit their own location.
@@ -325,7 +322,6 @@ class LocationsController extends Controller
$paginated_results = new LengthAwarePaginator($locations_formatted->forPage($page, 500), $locations_formatted->count(), 500, $page, []);
- //return [];
return (new SelectlistTransformer)->transformSelectlist($paginated_results);
}
}
diff --git a/app/Http/Controllers/Api/ManufacturersController.php b/app/Http/Controllers/Api/ManufacturersController.php
index 6b5a130229..eb89693e5c 100644
--- a/app/Http/Controllers/Api/ManufacturersController.php
+++ b/app/Http/Controllers/Api/ManufacturersController.php
@@ -10,8 +10,8 @@ use App\Models\Actionlog;
use App\Models\Manufacturer;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
-use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
+use Illuminate\Http\JsonResponse;
class ManufacturersController extends Controller
{
@@ -22,7 +22,7 @@ class ManufacturersController extends Controller
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ 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'];
@@ -83,9 +83,8 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
- * @return \Illuminate\Http\Response
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Manufacturer::class);
$manufacturer = new Manufacturer;
@@ -105,9 +104,8 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : JsonResponse | array
{
$this->authorize('view', Manufacturer::class);
$manufacturer = Manufacturer::withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('consumables as consumables_count')->withCount('accessories as accessories_count')->findOrFail($id);
@@ -122,9 +120,8 @@ class ManufacturersController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(ImageUploadRequest $request, $id)
+ public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Manufacturer::class);
$manufacturer = Manufacturer::findOrFail($id);
@@ -144,9 +141,8 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', Manufacturer::class);
$manufacturer = Manufacturer::findOrFail($id);
@@ -167,10 +163,9 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] []
* @since [v6.3.4]
* @param int $id
- * @return \Illuminate\Http\JsonResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function restore($id)
+ public function restore($id) : JsonResponse
{
$this->authorize('delete', Manufacturer::class);
@@ -186,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->user_id = Auth::user()->id;
+ $logaction->user_id = auth()->id();
$logaction->logaction('restore');
return response()->json(Helper::formatStandardApiResponse('success', trans('admin/manufacturers/message.restore.success')), 200);
@@ -206,7 +201,7 @@ class ManufacturersController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
diff --git a/app/Http/Controllers/Api/PredefinedKitsController.php b/app/Http/Controllers/Api/PredefinedKitsController.php
index b398dbfae2..2bc118db38 100644
--- a/app/Http/Controllers/Api/PredefinedKitsController.php
+++ b/app/Http/Controllers/Api/PredefinedKitsController.php
@@ -7,6 +7,8 @@ use App\Http\Controllers\Controller;
use App\Http\Transformers\PredefinedKitsTransformer;
use App\Models\PredefinedKit;
use Illuminate\Http\Request;
+use Illuminate\Http\JsonResponse;
+use App\Http\Transformers\SelectlistTransformer;
/**
* @author [D. Minaev.] []
@@ -18,7 +20,7 @@ class PredefinedKitsController extends Controller
*
* @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('view', PredefinedKit::class);
$allowed_columns = ['id', 'name'];
@@ -47,9 +49,8 @@ class PredefinedKitsController extends Controller
* Store a newly created resource in storage.
*
* @param \Illuminate\Http\Request $request
- * @return \Illuminate\Http\Response
*/
- public function store(Request $request)
+ public function store(Request $request) : JsonResponse
{
$this->authorize('create', PredefinedKit::class);
$kit = new PredefinedKit;
@@ -66,9 +67,8 @@ class PredefinedKitsController extends Controller
* Display the specified resource.
*
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : array
{
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($id);
@@ -81,9 +81,8 @@ class PredefinedKitsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $id kit id
- * @return \Illuminate\Http\Response
*/
- public function update(Request $request, $id)
+ public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($id);
@@ -100,9 +99,8 @@ class PredefinedKitsController extends Controller
* Remove the specified resource from storage.
*
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($id);
@@ -123,7 +121,7 @@ class PredefinedKitsController extends Controller
*
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
$kits = PredefinedKit::select([
'id',
@@ -145,7 +143,7 @@ class PredefinedKitsController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
- public function indexLicenses($kit_id)
+ public function indexLicenses($kit_id) : array
{
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -160,7 +158,7 @@ class PredefinedKitsController extends Controller
* @param int $id
* @return \Illuminate\Http\Response
*/
- public function storeLicense(Request $request, $kit_id)
+ public function storeLicense(Request $request, $kit_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
@@ -186,9 +184,8 @@ class PredefinedKitsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function updateLicense(Request $request, $kit_id, $license_id)
+ public function updateLicense(Request $request, $kit_id, $license_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -205,9 +202,8 @@ class PredefinedKitsController extends Controller
* Remove the specified resource from storage.
*
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function detachLicense($kit_id, $license_id)
+ public function detachLicense($kit_id, $license_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -221,9 +217,8 @@ class PredefinedKitsController extends Controller
* Display the specified resource.
*
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function indexModels($kit_id)
+ public function indexModels($kit_id) : array
{
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -236,9 +231,8 @@ class PredefinedKitsController extends Controller
* Store the specified resource.
*
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function storeModel(Request $request, $kit_id)
+ public function storeModel(Request $request, $kit_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
@@ -264,9 +258,8 @@ class PredefinedKitsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function updateModel(Request $request, $kit_id, $model_id)
+ public function updateModel(Request $request, $kit_id, $model_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -283,9 +276,8 @@ class PredefinedKitsController extends Controller
* Remove the specified resource from storage.
*
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function detachModel($kit_id, $model_id)
+ public function detachModel($kit_id, $model_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -299,9 +291,8 @@ class PredefinedKitsController extends Controller
* Display the specified resource.
*
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function indexConsumables($kit_id)
+ public function indexConsumables($kit_id) : array
{
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -314,9 +305,8 @@ class PredefinedKitsController extends Controller
* Store the specified resource.
*
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function storeConsumable(Request $request, $kit_id)
+ public function storeConsumable(Request $request, $kit_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
@@ -342,9 +332,8 @@ class PredefinedKitsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function updateConsumable(Request $request, $kit_id, $consumable_id)
+ public function updateConsumable(Request $request, $kit_id, $consumable_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -361,9 +350,8 @@ class PredefinedKitsController extends Controller
* Remove the specified resource from storage.
*
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function detachConsumable($kit_id, $consumable_id)
+ public function detachConsumable($kit_id, $consumable_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -377,9 +365,8 @@ class PredefinedKitsController extends Controller
* Display the specified resource.
*
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function indexAccessories($kit_id)
+ public function indexAccessories($kit_id) : array
{
$this->authorize('view', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -392,9 +379,8 @@ class PredefinedKitsController extends Controller
* Store the specified resource.
*
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function storeAccessory(Request $request, $kit_id)
+ public function storeAccessory(Request $request, $kit_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
@@ -420,9 +406,8 @@ class PredefinedKitsController extends Controller
*
* @param \Illuminate\Http\Request $request
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function updateAccessory(Request $request, $kit_id, $accessory_id)
+ public function updateAccessory(Request $request, $kit_id, $accessory_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
@@ -439,9 +424,8 @@ class PredefinedKitsController extends Controller
* Remove the specified resource from storage.
*
* @param int $kit_id
- * @return \Illuminate\Http\Response
*/
- public function detachAccessory($kit_id, $accessory_id)
+ public function detachAccessory($kit_id, $accessory_id) : JsonResponse
{
$this->authorize('update', PredefinedKit::class);
$kit = PredefinedKit::findOrFail($kit_id);
diff --git a/app/Http/Controllers/Api/ProfileController.php b/app/Http/Controllers/Api/ProfileController.php
index ef56ed5370..f7f91e094e 100644
--- a/app/Http/Controllers/Api/ProfileController.php
+++ b/app/Http/Controllers/Api/ProfileController.php
@@ -6,13 +6,13 @@ use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Models\CheckoutRequest;
use Illuminate\Http\Response;
-use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
use Laravel\Passport\TokenRepository;
use Illuminate\Contracts\Validation\Factory as ValidationFactory;
use Illuminate\Support\Facades\Gate;
use App\Models\CustomField;
-use DB;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Http\JsonResponse;
class ProfileController extends Controller
{
@@ -42,12 +42,10 @@ class ProfileController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.3.0]
- *
- * @return array
*/
- public function requestedAssets()
+ public function requestedAssets() : array
{
- $checkoutRequests = CheckoutRequest::where('user_id', '=', Auth::user()->id)->get();
+ $checkoutRequests = CheckoutRequest::where('user_id', '=', auth()->id())->get();
$results = array();
$show_field = array();
@@ -95,10 +93,9 @@ class ProfileController extends Controller
*
* @author [A. Gianotto] []
* @since [v6.0.5]
- *
- * @return \Illuminate\Http\Response
*/
- public function createApiToken(Request $request) {
+ public function createApiToken(Request $request) : JsonResponse
+ {
if (!Gate::allows('self.api')) {
abort(403);
@@ -106,14 +103,14 @@ class ProfileController extends Controller
$accessTokenName = $request->input('name', 'Auth Token');
- if ($accessToken = Auth::user()->createToken($accessTokenName)->accessToken) {
+ if ($accessToken = auth()->user()->createToken($accessTokenName)->accessToken) {
// Get the ID so we can return that with the payload
- $token = DB::table('oauth_access_tokens')->where('user_id', '=', Auth::user()->id)->where('name','=',$accessTokenName)->orderBy('created_at', 'desc')->first();
+ $token = DB::table('oauth_access_tokens')->where('user_id', '=', auth()->id())->where('name','=',$accessTokenName)->orderBy('created_at', 'desc')->first();
$accessTokenData['id'] = $token->id;
$accessTokenData['token'] = $accessToken;
$accessTokenData['name'] = $accessTokenName;
- return response()->json(Helper::formatStandardApiResponse('success', $accessTokenData, 'Personal access token '.$accessTokenName.' created successfully'));
+ return response()->json(Helper::formatStandardApiResponse('success', $accessTokenData, trans('account/general.personal_api_keys_success', ['key' => $accessTokenName])));
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'Token could not be created.'));
@@ -125,17 +122,16 @@ class ProfileController extends Controller
*
* @author [A. Gianotto] []
* @since [v6.0.5]
- *
- * @return \Illuminate\Http\Response
*/
- public function deleteApiToken($tokenId) {
+ public function deleteApiToken($tokenId) : Response
+ {
if (!Gate::allows('self.api')) {
abort(403);
}
$token = $this->tokenRepository->findForUser(
- $tokenId, Auth::user()->getAuthIdentifier()
+ $tokenId, auth()->user()->getAuthIdentifier()
);
if (is_null($token)) {
@@ -154,16 +150,15 @@ class ProfileController extends Controller
*
* @author [A. Gianotto] []
* @since [v6.0.5]
- *
- * @return \Illuminate\Http\Response
*/
- public function showApiTokens(Request $request) {
+ public function showApiTokens() : JsonResponse
+ {
if (!Gate::allows('self.api')) {
abort(403);
}
- $tokens = $this->tokenRepository->forUser(Auth::user()->getAuthIdentifier());
+ $tokens = $this->tokenRepository->forUser(auth()->user()->getAuthIdentifier());
$token_values = $tokens->load('client')->filter(function ($token) {
return $token->client->personal_access_client && ! $token->revoked;
})->values();
diff --git a/app/Http/Controllers/Api/ReportsController.php b/app/Http/Controllers/Api/ReportsController.php
index fbeb78fc8f..b0f64189d5 100644
--- a/app/Http/Controllers/Api/ReportsController.php
+++ b/app/Http/Controllers/Api/ReportsController.php
@@ -6,6 +6,7 @@ use App\Http\Controllers\Controller;
use App\Http\Transformers\ActionlogsTransformer;
use App\Models\Actionlog;
use Illuminate\Http\Request;
+use Illuminate\Http\JsonResponse;
class ReportsController extends Controller
{
@@ -14,9 +15,8 @@ class ReportsController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return View
*/
- public function index(Request $request)
+ public function index(Request $request) : JsonResponse | array
{
$this->authorize('reports.view');
@@ -78,13 +78,14 @@ class ReportsController extends Controller
];
+ $total = $actionlogs->count();
// Make sure the offset and limit are actually integers and do not exceed system limits
- $offset = ($request->input('offset') > $actionlogs->count()) ? $actionlogs->count() : app('api_offset_value');
+ $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';
- $total = $actionlogs->count();
+
$actionlogs = $actionlogs->orderBy($sort, $order)->skip($offset)->take($limit)->get();
diff --git a/app/Http/Controllers/Api/SettingsController.php b/app/Http/Controllers/Api/SettingsController.php
index a481d67944..7eb28a4815 100644
--- a/app/Http/Controllers/Api/SettingsController.php
+++ b/app/Http/Controllers/Api/SettingsController.php
@@ -9,42 +9,38 @@ use Illuminate\Http\Request;
use App\Http\Controllers\Controller;
use App\Models\Ldap;
use App\Models\Setting;
-use Mail;
-use App\Notifications\SlackTest;
use App\Notifications\MailTest;
-use GuzzleHttp\Client;
use Illuminate\Http\JsonResponse;
-use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Storage;
-use Illuminate\Support\Facades\Validator;
-use App\Http\Requests\SlackSettingsRequest;
+use Illuminate\Support\Facades\Validator;
use App\Http\Transformers\LoginAttemptsTransformer;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
class SettingsController extends Controller
{
- public function ldaptest()
+ public function ldaptest() : JsonResponse
{
$settings = Setting::getSettings();
if ($settings->ldap_enabled!='1') {
- \Log::debug('LDAP is not enabled cannot test.');
+ Log::debug('LDAP is not enabled cannot test.');
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
}
- \Log::debug('Preparing to test LDAP connection');
+ Log::debug('Preparing to test LDAP connection');
$message = []; //where we collect together test messages
try {
$connection = Ldap::connectToLdap();
try {
$message['bind'] = ['message' => 'Successfully bound to LDAP server.'];
- \Log::debug('attempting to bind to LDAP for LDAP test');
+ Log::debug('attempting to bind to LDAP for LDAP test');
Ldap::bindAdminToLdap($connection);
$message['login'] = [
'message' => 'Successfully connected to LDAP server.',
@@ -75,24 +71,24 @@ class SettingsController extends Controller
return response()->json($message, 200);
} catch (\Exception $e) {
- \Log::debug('Bind failed');
- \Log::debug("Exception was: ".$e->getMessage());
+ Log::debug('Bind failed');
+ Log::debug("Exception was: ".$e->getMessage());
return response()->json(['message' => $e->getMessage()], 400);
//return response()->json(['message' => $e->getMessage()], 500);
}
} catch (\Exception $e) {
- \Log::debug('Connection failed but we cannot debug it any further on our end.');
+ Log::debug('Connection failed but we cannot debug it any further on our end.');
return response()->json(['message' => $e->getMessage()], 500);
}
}
- public function ldaptestlogin(Request $request)
+ public function ldaptestlogin(Request $request) : JsonResponse
{
if (Setting::getSettings()->ldap_enabled != '1') {
- \Log::debug('LDAP is not enabled. Cannot test.');
+ Log::debug('LDAP is not enabled. Cannot test.');
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
}
@@ -104,39 +100,39 @@ class SettingsController extends Controller
$validator = Validator::make($request->all(), $rules);
if ($validator->fails()) {
- \Log::debug('LDAP Validation test failed.');
+ Log::debug('LDAP Validation test failed.');
$validation_errors = implode(' ',$validator->errors()->all());
return response()->json(['message' => $validator->errors()->all()], 400);
}
- \Log::debug('Preparing to test LDAP login');
+ Log::debug('Preparing to test LDAP login');
try {
$connection = Ldap::connectToLdap();
try {
Ldap::bindAdminToLdap($connection);
- \Log::debug('Attempting to bind to LDAP for LDAP test');
+ Log::debug('Attempting to bind to LDAP for LDAP test');
try {
$ldap_user = Ldap::findAndBindUserLdap($request->input('ldaptest_user'), $request->input('ldaptest_password'));
if ($ldap_user) {
- \Log::debug('It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.');
+ Log::debug('It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.');
return response()->json(['message' => 'It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.'], 200);
}
return response()->json(['message' => 'Login Failed. '. $request->input('ldaptest_user').' did not successfully bind to LDAP.'], 400);
} catch (\Exception $e) {
- \Log::debug('LDAP login failed');
+ Log::debug('LDAP login failed');
return response()->json(['message' => $e->getMessage()], 400);
}
} catch (\Exception $e) {
- \Log::debug('Bind failed');
+ Log::debug('Bind failed');
return response()->json(['message' => $e->getMessage()], 400);
//return response()->json(['message' => $e->getMessage()], 500);
}
} catch (\Exception $e) {
- \Log::debug('Connection failed');
+ Log::debug('Connection failed');
return response()->json(['message' => $e->getMessage()], 500);
}
@@ -148,9 +144,8 @@ class SettingsController extends Controller
*
* @author [A. Gianotto] []
* @since [v3.0]
- * @return JsonResponse
*/
- public function ajaxTestEmail()
+ public function ajaxTestEmail() : JsonResponse
{
if (!config('app.lock_passwords')) {
try {
@@ -170,9 +165,8 @@ class SettingsController extends Controller
*
* @author [A. Gianotto] []
* @since [v5.0.0]
- * @return JsonResponse
*/
- public function purgeBarcodes()
+ public function purgeBarcodes() : JsonResponse
{
$file_count = 0;
$files = Storage::disk('public')->files('barcodes');
@@ -181,19 +175,19 @@ class SettingsController extends Controller
$file_parts = explode('.', $file);
$extension = end($file_parts);
- \Log::debug($extension);
+ Log::debug($extension);
// Only generated barcodes would have a .png file extension
if ($extension == 'png') {
- \Log::debug('Deleting: '.$file);
+ Log::debug('Deleting: '.$file);
try {
Storage::disk('public')->delete($file);
- \Log::debug('Deleting: '.$file);
+ Log::debug('Deleting: '.$file);
$file_count++;
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
}
}
}
@@ -211,9 +205,8 @@ class SettingsController extends Controller
* @author [A. Gianotto] []
* @since [v5.0.0]
* @param \Illuminate\Http\Request $request
- * @return array | JsonResponse
*/
- public function showLoginAttempts(Request $request)
+ public function showLoginAttempts(Request $request) : array
{
$allowed_columns = ['id', 'username', 'remote_ip', 'user_agent', 'successful', 'created_at'];
@@ -233,9 +226,9 @@ class SettingsController extends Controller
* Lists backup files
*
* @author [A. Gianotto]
- * @return array | JsonResponse
*/
- public function listBackups() {
+ public function listBackups() : array
+ {
$settings = Setting::getSettings();
$path = 'app/backups';
$backup_files = Storage::files($path);
@@ -276,9 +269,9 @@ class SettingsController extends Controller
* exhausts memory on larger files.
*
* @author [A. Gianotto]
- * @return JsonResponse|\Symfony\Component\HttpFoundation\BinaryFileResponse
*/
- public function downloadBackup($file) {
+ public function downloadBackup($file) : JsonResponse | BinaryFileResponse
+ {
$path = storage_path('app/backups');
@@ -296,9 +289,9 @@ class SettingsController extends Controller
*
* @author [A. Gianotto]
* @since [v6.3.1]
- * @return JsonResponse|\Symfony\Component\HttpFoundation\BinaryFileResponse
*/
- public function downloadLatestBackup() {
+ public function downloadLatestBackup() : JsonResponse | BinaryFileResponse
+ {
$fileData = collect();
foreach (Storage::files('app/backups') as $file) {
diff --git a/app/Http/Controllers/Api/StatuslabelsController.php b/app/Http/Controllers/Api/StatuslabelsController.php
index 7c8e260c2f..95ac5956fa 100644
--- a/app/Http/Controllers/Api/StatuslabelsController.php
+++ b/app/Http/Controllers/Api/StatuslabelsController.php
@@ -11,7 +11,7 @@ use App\Models\Asset;
use App\Models\Statuslabel;
use Illuminate\Http\Request;
use App\Http\Transformers\PieChartTransformer;
-use Illuminate\Support\Arr;
+use Illuminate\Http\JsonResponse;
class StatuslabelsController extends Controller
{
@@ -20,9 +20,8 @@ class StatuslabelsController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request) : array
{
$this->authorize('view', Statuslabel::class);
$allowed_columns = ['id', 'name', 'created_at', 'assets_count', 'color', 'notes', 'default_label'];
@@ -72,9 +71,8 @@ class StatuslabelsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \Illuminate\Http\Request $request
- * @return \Illuminate\Http\Response
*/
- public function store(Request $request)
+ public function store(Request $request) : JsonResponse
{
$this->authorize('create', Statuslabel::class);
$request->except('deployable', 'pending', 'archived');
@@ -108,9 +106,8 @@ class StatuslabelsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : array
{
$this->authorize('view', Statuslabel::class);
$statuslabel = Statuslabel::findOrFail($id);
@@ -126,9 +123,8 @@ class StatuslabelsController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(Request $request, $id)
+ public function update(Request $request, $id) : JsonResponse
{
$this->authorize('update', Statuslabel::class);
$statuslabel = Statuslabel::findOrFail($id);
@@ -163,9 +159,8 @@ class StatuslabelsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', Statuslabel::class);
$statuslabel = Statuslabel::findOrFail($id);
@@ -188,9 +183,8 @@ class StatuslabelsController extends Controller
*
* @author [A. Gianotto] []
* @since [v3.0]
- * @return array
*/
- public function getAssetCountByStatuslabel()
+ public function getAssetCountByStatuslabel() : array
{
$this->authorize('view', Statuslabel::class);
$statuslabels = Statuslabel::withCount('assets')->get();
@@ -215,9 +209,8 @@ class StatuslabelsController extends Controller
*
* @author [A. Gianotto] []
* @since [v6.0.11]
- * @return array
*/
- public function getAssetCountByMetaStatus()
+ public function getAssetCountByMetaStatus() : array
{
$this->authorize('view', Statuslabel::class);
@@ -245,9 +238,8 @@ class StatuslabelsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function assets(Request $request, $id)
+ public function assets(Request $request, $id) : array
{
$this->authorize('view', Statuslabel::class);
$this->authorize('index', Asset::class);
@@ -281,9 +273,8 @@ class StatuslabelsController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return bool
*/
- public function checkIfDeployable($id)
+ public function checkIfDeployable($id) : string
{
$statuslabel = Statuslabel::findOrFail($id);
if ($statuslabel->getStatuslabelType() == 'deployable') {
@@ -300,7 +291,7 @@ class StatuslabelsController extends Controller
* @since [v6.1.1]
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
diff --git a/app/Http/Controllers/Api/SuppliersController.php b/app/Http/Controllers/Api/SuppliersController.php
index 3e3d637be0..f752f22241 100644
--- a/app/Http/Controllers/Api/SuppliersController.php
+++ b/app/Http/Controllers/Api/SuppliersController.php
@@ -10,6 +10,7 @@ use App\Models\Supplier;
use Illuminate\Http\Request;
use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
+use Illuminate\Http\JsonResponse;
class SuppliersController extends Controller
{
@@ -20,7 +21,7 @@ class SuppliersController extends Controller
* @since [v4.0]
* @return \Illuminate\Http\Response
*/
- public function index(Request $request)
+ public function index(Request $request): array
{
$this->authorize('view', Supplier::class);
$allowed_columns = ['
@@ -114,9 +115,8 @@ class SuppliersController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
- * @return \Illuminate\Http\Response
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : JsonResponse
{
$this->authorize('create', Supplier::class);
$supplier = new Supplier;
@@ -136,9 +136,8 @@ class SuppliersController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : array
{
$this->authorize('view', Supplier::class);
$supplier = Supplier::findOrFail($id);
@@ -154,9 +153,8 @@ class SuppliersController extends Controller
* @since [v4.0]
* @param \App\Http\Requests\ImageUploadRequest $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(ImageUploadRequest $request, $id)
+ public function update(ImageUploadRequest $request, $id) : JsonResponse
{
$this->authorize('update', Supplier::class);
$supplier = Supplier::findOrFail($id);
@@ -176,9 +174,8 @@ class SuppliersController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy($id) : JsonResponse
{
$this->authorize('delete', Supplier::class);
$supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count', 'assets as assets_count', 'licenses as licenses_count')->findOrFail($id);
@@ -209,7 +206,7 @@ class SuppliersController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
$this->authorize('view.selectlists');
diff --git a/app/Http/Controllers/Api/UsersController.php b/app/Http/Controllers/Api/UsersController.php
index 5ef45ee4d9..9200f80b1d 100644
--- a/app/Http/Controllers/Api/UsersController.php
+++ b/app/Http/Controllers/Api/UsersController.php
@@ -13,15 +13,18 @@ use App\Http\Transformers\SelectlistTransformer;
use App\Http\Transformers\UsersTransformer;
use App\Models\Actionlog;
use App\Models\Asset;
-use App\Models\Company;
+use App\Models\Accessory;
+use App\Models\Consumable;
use App\Models\License;
use App\Models\User;
use App\Notifications\CurrentInventory;
-use Auth;
+use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
-use App\Http\Requests\ImageUploadRequest;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
+use Illuminate\Support\Facades\Log;
+use App\Http\Requests\DeleteUserRequest;
+use Illuminate\Http\JsonResponse;
class UsersController extends Controller
{
@@ -31,9 +34,9 @@ class UsersController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
*
- * @return \Illuminate\Http\Response
+ * @return array
*/
- public function index(Request $request)
+ public function index(Request $request) : array
{
$this->authorize('view', User::class);
@@ -75,10 +78,14 @@ class UsersController extends Controller
'users.autoassign_licenses',
'users.website',
- ])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy',)
- ->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count');
+ ])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy', 'managesUsers', 'managedLocations')
+ ->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count');
+ if ($request->filled('search') != '') {
+ $users = $users->TextSearch($request->input('search'));
+ }
+
if ($request->filled('activated')) {
$users = $users->where('users.activated', '=', $request->input('activated'));
}
@@ -187,12 +194,23 @@ class UsersController extends Controller
$users->has('accessories', '=', $request->input('accessories_count'));
}
+ if ($request->filled('manages_users_count')) {
+ $users->has('manages_users_count', '=', $request->input('manages_users_count'));
+ }
+
+ if ($request->filled('manages_locations_count')) {
+ $users->has('manages_locations_count', '=', $request->input('manages_locations_count'));
+ }
+
if ($request->filled('autoassign_licenses')) {
$users->where('autoassign_licenses', '=', $request->input('autoassign_licenses'));
}
- if ($request->filled('search')) {
- $users = $users->TextSearch($request->input('search'));
+
+ if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
+ $users = $users->onlyTrashed();
+ } elseif (($request->filled('all')) && ($request->input('all') == 'true')) {
+ $users = $users->withTrashed();
}
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
@@ -230,10 +248,6 @@ class UsersController extends Controller
'jobtitle',
'username',
'employee_num',
- 'assets',
- 'accessories',
- 'consumables',
- 'licenses',
'groups',
'activated',
'created_at',
@@ -244,6 +258,8 @@ class UsersController extends Controller
'licenses_count',
'consumables_count',
'accessories_count',
+ 'manages_users_count',
+ 'manages_locations_count',
'phone',
'address',
'city',
@@ -262,18 +278,11 @@ class UsersController extends Controller
'website',
];
- $sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name';
+ $sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'first_name';
$users = $users->orderBy($sort, $order);
break;
}
- if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
- $users = $users->onlyTrashed();
- } elseif (($request->filled('all')) && ($request->input('all') == 'true')) {
- $users = $users->withTrashed();
- }
-
- $users = Company::scopeCompanyables($users);
// Make sure the offset and limit are actually integers and do not exceed system limits
@@ -293,7 +302,7 @@ class UsersController extends Controller
* @since [v4.0.16]
* @see \App\Http\Transformers\SelectlistTransformer
*/
- public function selectlist(Request $request)
+ public function selectlist(Request $request) : array
{
$users = User::select(
[
@@ -308,8 +317,6 @@ class UsersController extends Controller
]
)->where('show_in_list', '=', '1');
- $users = Company::scopeCompanyables($users);
-
if ($request->filled('search')) {
$users = $users->where(function ($query) use ($request) {
$query->SimpleNameSearch($request->get('search'))
@@ -351,21 +358,20 @@ class UsersController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param \Illuminate\Http\Request $request
- * @return \Illuminate\Http\Response
*/
- public function store(SaveUserRequest $request)
+ public function store(SaveUserRequest $request) : JsonResponse
{
$this->authorize('create', User::class);
$user = new User;
$user->fill($request->all());
- $user->created_by = Auth::user()->id;
+ $user->created_by = auth()->id();
if ($request->has('permissions')) {
$permissions_array = $request->input('permissions');
// Strip out the superuser permission if the API user isn't a superadmin
- if (! Auth::user()->isSuperUser()) {
+ if (! auth()->user()->isSuperUser()) {
unset($permissions_array['superuser']);
}
$user->permissions = $permissions_array;
@@ -398,14 +404,18 @@ class UsersController extends Controller
*
* @author [A. Gianotto] []
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function show($id)
+ public function show($id) : JsonResponse | array
{
$this->authorize('view', User::class);
- $user = User::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count')->findOrFail($id);
- return (new UsersTransformer)->transformUser($user);
+ if ($user = User::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count')->find($id)) {
+ $this->authorize('view', $user);
+ return (new UsersTransformer)->transformUser($user);
+ }
+
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
+
}
@@ -416,89 +426,88 @@ class UsersController extends Controller
* @since [v4.0]
* @param \Illuminate\Http\Request $request
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function update(SaveUserRequest $request, $id)
+ public function update(SaveUserRequest $request, $id) : JsonResponse
{
$this->authorize('update', User::class);
- $user = User::findOrFail($id);
-
- /**
- * 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 = User::find($id)) {
- 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.'));
- }
+ $this->authorize('update', $user);
+
+ /**
+ * 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
+ *
+ */
- $user->fill($request->all());
-
- if ($user->id == $request->input('manager_id')) {
- return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
- }
-
- if ($request->filled('password')) {
- $user->password = bcrypt($request->input('password'));
- }
-
- // We need to use has() instead of filled()
- // here because we need to overwrite permissions
- // if someone needs to null them out
- if ($request->has('permissions')) {
- $permissions_array = $request->input('permissions');
-
- // Strip out the superuser permission if the API user isn't a superadmin
- if (! Auth::user()->isSuperUser()) {
- unset($permissions_array['superuser']);
+ 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->permissions = $permissions_array;
- }
+ $user->fill($request->all());
- // 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)]);
+ if ($user->id == $request->input('manager_id')) {
+ return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
+ }
-
- app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
-
- if ($user->save()) {
+ if ($request->filled('password')) {
+ $user->password = bcrypt($request->input('password'));
+ }
- // Sync group memberships:
- // This was changed in Snipe-IT v4.6.x to 4.7, since we upgraded to Laravel 5.5
- // which changes the behavior of has vs filled.
- // The $request->has method will now return true even if the input value is an empty string or null.
- // A new $request->filled method has was added that provides the previous behavior of the has method.
+ // We need to use has() instead of filled()
+ // here because we need to overwrite permissions
+ // if someone needs to null them out
+ if ($request->has('permissions')) {
+ $permissions_array = $request->input('permissions');
- // Check if the request has groups passed and has a value
- if ($request->filled('groups')) {
- $validator = Validator::make($request->all(), [
- 'groups.*' => 'integer|exists:permission_groups,id',
- ]);
-
- if ($validator->fails()){
- return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
+ // Strip out the individual superuser permission if the API user isn't a superadmin
+ if (!auth()->user()->isSuperUser()) {
+ unset($permissions_array['superuser']);
}
- $user->groups()->sync($request->input('groups'));
- // The groups field has been passed but it is null, so we should blank it out
- } elseif ($request->has('groups')) {
- $user->groups()->sync([]);
+
+ $user->permissions = $permissions_array;
}
- return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
+ // 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())) {
+
+ $validator = Validator::make($request->only('groups'), [
+ 'groups.*' => 'integer|exists:permission_groups,id',
+ ]);
+
+ if ($validator->fails()) {
+ return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()));
+ }
+
+ // 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, $user->getErrors()));
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
+
}
/**
@@ -507,45 +516,35 @@ class UsersController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param int $id
- * @return \Illuminate\Http\Response
*/
- public function destroy($id)
+ public function destroy(DeleteUserRequest $request, $id) : JsonResponse
{
$this->authorize('delete', User::class);
- $user = User::findOrFail($id);
- $this->authorize('delete', $user);
- if (($user->assets) && ($user->assets->count() > 0)) {
- return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete_has_assets')));
- }
+ if ($user = User::withTrashed()->find($id)) {
- if (($user->licenses) && ($user->licenses->count() > 0)) {
- return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has '.$user->licenses->count().' license(s) associated with them and cannot be deleted.'));
- }
+ $this->authorize('delete', $user);
- if (($user->accessories) && ($user->accessories->count() > 0)) {
- return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has '.$user->accessories->count().' accessories associated with them.'));
- }
+ if ($user->delete()) {
- if (($user->managedLocations()) && ($user->managedLocations()->count() > 0)) {
- return response()->json(Helper::formatStandardApiResponse('error', null, 'This user still has '.$user->managedLocations()->count().' locations that they manage.'));
- }
-
- if ($user->delete()) {
-
- // Remove the user's avatar if they have one
- if (Storage::disk('public')->exists('avatars/'.$user->avatar)) {
- try {
- Storage::disk('public')->delete('avatars/'.$user->avatar);
- } catch (\Exception $e) {
- \Log::debug($e);
+ // Remove the user's avatar if they have one
+ if (Storage::disk('public')->exists('avatars/' . $user->avatar)) {
+ try {
+ Storage::disk('public')->delete('avatars/' . $user->avatar);
+ } catch (\Exception $e) {
+ Log::debug($e);
+ }
}
+
+ return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
}
- return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete')));
+
}
- return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete')));
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')));
+
}
/**
@@ -554,34 +553,41 @@ class UsersController extends Controller
* @author [A. Gianotto] []
* @since [v3.0]
* @param $userId
- * @return string JSON
*/
- public function assets(Request $request, $id)
+ public function assets(Request $request, $id) : JsonResponse | array
{
$this->authorize('view', User::class);
$this->authorize('view', Asset::class);
- $assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model');
+
+ if ($user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id)) {
+ $this->authorize('view', $user);
+
+ $assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model');
- // Filter on category ID
- if ($request->filled('category_id')) {
- $assets = $assets->InCategory($request->input('category_id'));
- }
-
-
- // Filter on model ID
- if ($request->filled('model_id')) {
-
- $model_ids = $request->input('model_id');
- if (!is_array($model_ids)) {
- $model_ids = array($model_ids);
+ // Filter on category ID
+ if ($request->filled('category_id')) {
+ $assets = $assets->InCategory($request->input('category_id'));
}
- $assets = $assets->InModelList($model_ids);
+
+
+ // Filter on model ID
+ if ($request->filled('model_id')) {
+
+ $model_ids = $request->input('model_id');
+ if (!is_array($model_ids)) {
+ $model_ids = array($model_ids);
+ }
+ $assets = $assets->InModelList($model_ids);
+ }
+
+ $assets = $assets->get();
+
+ return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
}
- $assets = $assets->get();
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
- return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
}
/**
@@ -591,19 +597,26 @@ class UsersController extends Controller
* @since [v6.0.13]
* @param Request $request
* @param $id
- * @return string JSON
*/
- public function emailAssetList(Request $request, $id)
- {
- $user = User::findOrFail($id);
+ public function emailAssetList(Request $request, $id) : JsonResponse
- if (empty($user->email)) {
- return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
+ {
+ $this->authorize('update', User::class);
+
+ if ($user = User::find($id)) {
+ $this->authorize('update', $user);
+
+ if (empty($user->email)) {
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
+ }
+
+ $user->notify((new CurrentInventory($user)));
+ return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success')));
}
- $user->notify((new CurrentInventory($user)));
+ return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
- return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success')));
+
}
/**
@@ -612,13 +625,13 @@ class UsersController extends Controller
* @author [A. Gianotto] []
* @since [v3.0]
* @param $userId
- * @return string JSON
*/
- public function consumables(Request $request, $id)
+ public function consumables(Request $request, $id) : array
{
$this->authorize('view', User::class);
$this->authorize('view', Consumable::class);
$user = User::findOrFail($id);
+ $this->authorize('view', $user);
$consumables = $user->consumables;
return (new ConsumablesTransformer)->transformConsumables($consumables, $consumables->count(), $request);
}
@@ -629,12 +642,12 @@ class UsersController extends Controller
* @author [A. Gianotto] []
* @since [v4.6.14]
* @param $userId
- * @return string JSON
*/
- public function accessories($id)
+ public function accessories($id) : array
{
$this->authorize('view', User::class);
$user = User::findOrFail($id);
+ $this->authorize('view', $user);
$this->authorize('view', Accessory::class);
$accessories = $user->accessories;
@@ -647,14 +660,14 @@ class UsersController extends Controller
* @author [N. Mathar] []
* @since [v5.0]
* @param $userId
- * @return string JSON
*/
- public function licenses($id)
+ public function licenses($id) : JsonResponse | array
{
$this->authorize('view', User::class);
$this->authorize('view', License::class);
if ($user = User::where('id', $id)->withTrashed()->first()) {
+ $this->authorize('update', $user);
$licenses = $user->licenses()->get();
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
}
@@ -669,15 +682,15 @@ class UsersController extends Controller
* @author [A. Gianotto] []
* @since [v3.0]
* @param $userId
- * @return string JSON
*/
- public function postTwoFactorReset(Request $request)
+ public function postTwoFactorReset(Request $request) : JsonResponse
{
$this->authorize('update', User::class);
if ($request->filled('id')) {
try {
$user = User::find($request->get('id'));
+ $this->authorize('update', $user);
$user->two_factor_secret = null;
$user->two_factor_enrolled = 0;
$user->saveQuietly();
@@ -689,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->user_id = Auth::user()->id;
+ $logaction->user_id = auth()->id();
$logaction->logaction('2FA reset');
return response()->json(['message' => trans('admin/settings/general.two_factor_reset_success')], 200);
@@ -708,9 +721,8 @@ class UsersController extends Controller
* @author [Juan Font] []
* @since [v4.4.2]
* @param \Illuminate\Http\Request $request
- * @return \Illuminate\Http\Response
*/
- public function getCurrentUserInfo(Request $request)
+ public function getCurrentUserInfo(Request $request) : array
{
return (new UsersTransformer)->transformUser($request->user());
}
@@ -721,12 +733,13 @@ class UsersController extends Controller
* @author [E. Taylor] []
* @param int $userId
* @since [v6.0.0]
- * @return JsonResponse
*/
- public function restore($userId = null)
+ public function restore($userId) : JsonResponse
{
+ $this->authorize('delete', User::class);
if ($user = User::withTrashed()->find($userId)) {
+
$this->authorize('delete', $user);
if ($user->deleted_at == '') {
@@ -739,14 +752,12 @@ 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->user_id = Auth::user()->id;
+ $logaction->user_id = auth()->id();
$logaction->logaction('restore');
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.restored')), 200);
}
- // Check validation to make sure we're not restoring a user with the same username as an existing user
- return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
}
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')), 200);
diff --git a/app/Http/Controllers/AssetMaintenancesController.php b/app/Http/Controllers/AssetMaintenancesController.php
index b5a50925ea..02be1e6061 100644
--- a/app/Http/Controllers/AssetMaintenancesController.php
+++ b/app/Http/Controllers/AssetMaintenancesController.php
@@ -2,17 +2,14 @@
namespace App\Http\Controllers;
-use App\Helpers\Helper;
use App\Models\Asset;
use App\Models\AssetMaintenance;
use App\Models\Company;
-use Auth;
+use Illuminate\Support\Facades\Auth;
use Carbon\Carbon;
use Illuminate\Http\Request;
-use Slack;
-use Str;
-use TCPDF;
-use View;
+use \Illuminate\Contracts\View\View;
+use \Illuminate\Http\RedirectResponse;
/**
* This controller handles all actions related to Asset Maintenance for
@@ -29,9 +26,8 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato
* @version v1.0
* @since [v1.8]
- * @return View
*/
- private static function getInsufficientPermissionsRedirect()
+ private static function getInsufficientPermissionsRedirect(): RedirectResponse
{
return redirect()->route('maintenances.index')
->with('error', trans('general.insufficient_permissions'));
@@ -46,9 +42,8 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato
* @version v1.0
* @since [v1.8]
- * @return View
*/
- public function index()
+ public function index() : View
{
$this->authorize('view', Asset::class);
return view('asset_maintenances/index');
@@ -63,7 +58,7 @@ class AssetMaintenancesController extends Controller
* @since [v1.8]
* @return mixed
*/
- public function create()
+ public function create() : View
{
$this->authorize('update', Asset::class);
$asset = null;
@@ -92,9 +87,8 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato
* @version v1.0
* @since [v1.8]
- * @return mixed
*/
- public function store(Request $request)
+ public function store(Request $request) : RedirectResponse
{
$this->authorize('update', Asset::class);
// create a new model instance
@@ -144,9 +138,8 @@ class AssetMaintenancesController extends Controller
* @param int $assetMaintenanceId
* @version v1.0
* @since [v1.8]
- * @return mixed
*/
- public function edit($assetMaintenanceId = null)
+ public function edit($assetMaintenanceId = null) : View | RedirectResponse
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
@@ -162,14 +155,9 @@ class AssetMaintenancesController extends Controller
return static::getInsufficientPermissionsRedirect();
}
-
// Prepare Improvement Type List
- $assetMaintenanceType = [
- '' => 'Select an improvement type',
- ] + AssetMaintenance::getImprovementOptions();
+ $assetMaintenanceType = ['' => 'Select an improvement type'] + AssetMaintenance::getImprovementOptions();
- // Get Supplier List
- // Render the view
return view('asset_maintenances/edit')
->with('selectedAsset', null)
->with('assetMaintenanceType', $assetMaintenanceType)
@@ -183,11 +171,10 @@ class AssetMaintenancesController extends Controller
* @author Vincent Sposato
* @param Request $request
* @param int $assetMaintenanceId
- * @return mixed
* @version v1.0
* @since [v1.8]
*/
- public function update(Request $request, $assetMaintenanceId = null)
+ public function update(Request $request, $assetMaintenanceId = null) : View | RedirectResponse
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
@@ -255,9 +242,8 @@ class AssetMaintenancesController extends Controller
* @param int $assetMaintenanceId
* @version v1.0
* @since [v1.8]
- * @return mixed
*/
- public function destroy($assetMaintenanceId)
+ public function destroy($assetMaintenanceId) : RedirectResponse
{
$this->authorize('update', Asset::class);
// Check if the asset maintenance exists
@@ -284,9 +270,8 @@ class AssetMaintenancesController extends Controller
* @param int $assetMaintenanceId
* @version v1.0
* @since [v1.8]
- * @return View
*/
- public function show($assetMaintenanceId)
+ public function show($assetMaintenanceId) : View | RedirectResponse
{
$this->authorize('view', Asset::class);
diff --git a/app/Http/Controllers/AssetModelsController.php b/app/Http/Controllers/AssetModelsController.php
index 8d387f968f..4421829f48 100755
--- a/app/Http/Controllers/AssetModelsController.php
+++ b/app/Http/Controllers/AssetModelsController.php
@@ -4,20 +4,21 @@ namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Http\Requests\ImageUploadRequest;
+use App\Http\Requests\StoreAssetModelRequest;
use App\Models\Actionlog;
-use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\CustomField;
+use App\Models\SnipeModel;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
-use Illuminate\Support\Facades\Input;
-use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Validator;
-use Redirect;
-use Request;
-use Storage;
-use Symfony\Component\HttpFoundation\JsonResponse;
+use Illuminate\Http\Request;
+use Illuminate\Support\Facades\Storage;
+use Illuminate\Support\Facades\Log;
+use \Illuminate\Contracts\View\View;
+use \Illuminate\Http\RedirectResponse;
+
/**
* This class controls all actions related to asset models for
@@ -34,10 +35,8 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.0]
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function index()
+ public function index() : View
{
$this->authorize('index', AssetModel::class);
@@ -49,10 +48,8 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.0]
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create()
+ public function create() : View
{
$this->authorize('create', AssetModel::class);
@@ -67,16 +64,12 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v1.0]
* @param ImageUploadRequest $request
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store(ImageUploadRequest $request)
+ public function store(StoreAssetModelRequest $request) : RedirectResponse
{
$this->authorize('create', AssetModel::class);
- // Create a new asset model
$model = new AssetModel;
- // Save the model data
$model->eol = $request->input('eol');
$model->depreciation_id = $request->input('depreciation_id');
$model->name = $request->input('name');
@@ -86,7 +79,7 @@ class AssetModelsController extends Controller
$model->category_id = $request->input('category_id');
$model->notes = $request->input('notes');
$model->user_id = Auth::id();
- $model->requestable = Request::has('requestable');
+ $model->requestable = $request->has('requestable');
if ($request->input('fieldset_id') != '') {
$model->fieldset_id = $request->input('fieldset_id');
@@ -94,7 +87,6 @@ class AssetModelsController extends Controller
$model = $request->handleImages($model);
- // Was it created?
if ($model->save()) {
if ($this->shouldAddDefaultValues($request->input())) {
if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){
@@ -114,18 +106,14 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v1.0]
* @param int $modelId
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit($modelId = null)
+ public function edit($modelId = null) : View | RedirectResponse
{
$this->authorize('update', AssetModel::class);
if ($item = AssetModel::find($modelId)) {
$category_type = 'asset';
- $view = View::make('models/edit', compact('item', 'category_type'));
- $view->with('depreciation_list', Helper::depreciationList());
+ return view('models/edit', compact('item', 'category_type'))->with('depreciation_list', Helper::depreciationList());
- return $view;
}
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
@@ -140,15 +128,14 @@ class AssetModelsController extends Controller
* @since [v1.0]
* @param ImageUploadRequest $request
* @param int $modelId
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function update(ImageUploadRequest $request, $modelId = null)
+ public function update(StoreAssetModelRequest $request, $modelId) : RedirectResponse
{
$this->authorize('update', AssetModel::class);
- // Check if the model exists
+
if (is_null($model = AssetModel::find($modelId))) {
- // Redirect to the models management page
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
}
@@ -174,9 +161,6 @@ class AssetModelsController extends Controller
}
}
-
-
-
if ($model->save()) {
if ($model->wasChanged('eol')) {
if ($model->eol > 0) {
@@ -201,10 +185,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v1.0]
* @param int $modelId
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($modelId)
+ public function destroy($modelId) : RedirectResponse
{
$this->authorize('delete', AssetModel::class);
// Check if the model exists
@@ -221,7 +203,7 @@ class AssetModelsController extends Controller
try {
Storage::disk('public')->delete('models/'.$model->image);
} catch (\Exception $e) {
- \Log::info($e);
+ Log::info($e);
}
}
@@ -238,10 +220,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v1.0]
* @param int $id
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function getRestore($id)
+ public function getRestore($id) : RedirectResponse
{
$this->authorize('create', AssetModel::class);
@@ -256,7 +236,7 @@ class AssetModelsController extends Controller
$logaction->item_type = User::class;
$logaction->item_id = $model->id;
$logaction->created_at = date('Y-m-d H:i:s');
- $logaction->user_id = Auth::user()->id;
+ $logaction->user_id = auth()->id();
$logaction->logaction('restore');
@@ -283,13 +263,11 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v1.0]
* @param int $modelId
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function show($modelId = null)
+ public function show($modelId = null) : View | RedirectResponse
{
$this->authorize('view', AssetModel::class);
- $model = AssetModel::withTrashed()->withCount('assets')->find($modelId);
+ $model = AssetModel::withTrashed()->find($modelId);
if (isset($model->id)) {
return view('models/view', compact('model'));
@@ -304,9 +282,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v1.0]
* @param int $modelId
- * @return View
*/
- public function getClone($modelId = null)
+ public function getClone($modelId = null) : View | RedirectResponse
{
$this->authorize('create', AssetModel::class);
// Check if the model exists
@@ -332,9 +309,8 @@ class AssetModelsController extends Controller
* @author [B. Wetherington] []
* @since [v2.0]
* @param int $modelId
- * @return View
*/
- public function getCustomFields($modelId)
+ public function getCustomFields($modelId) : View
{
return view('models.custom_fields_form')->with('model', AssetModel::find($modelId));
}
@@ -346,9 +322,8 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.7]
- * @return \Illuminate\Contracts\View\View
*/
- public function postBulkEdit(Request $request)
+ public function postBulkEdit(Request $request) : View | RedirectResponse
{
$models_raw_array = $request->input('ids');
@@ -390,9 +365,8 @@ class AssetModelsController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.7]
- * @return \Illuminate\Contracts\View\View
*/
- public function postBulkEditSave(Request $request)
+ public function postBulkEditSave(Request $request) : RedirectResponse
{
$models_raw_array = $request->input('ids');
$update_array = [];
@@ -430,9 +404,8 @@ class AssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v1.0]
* @param int $modelId
- * @return Redirect
*/
- public function postBulkDelete(Request $request)
+ public function postBulkDelete(Request $request) : RedirectResponse
{
$models_raw_array = $request->input('ids');
@@ -471,9 +444,8 @@ class AssetModelsController extends Controller
* any default values were entered into the form.
*
* @param array $input
- * @return bool
*/
- private function shouldAddDefaultValues(array $input)
+ private function shouldAddDefaultValues(array $input) : bool
{
return ! empty($input['add_default_values'])
&& ! empty($input['default_values'])
@@ -485,9 +457,8 @@ class AssetModelsController extends Controller
*
* @param AssetModel $model
* @param array $defaultValues
- * @return void
*/
- private function assignCustomFieldsDefaultValues(AssetModel $model, array $defaultValues): bool
+ private function assignCustomFieldsDefaultValues(AssetModel|SnipeModel $model, array $defaultValues): bool
{
$data = array();
foreach ($defaultValues as $customFieldId => $defaultValue) {
@@ -496,17 +467,17 @@ class AssetModelsController extends Controller
$data[$customField->db_column] = $defaultValue;
}
- $fieldsets = $model->fieldset->validation_rules();
+ $allRules = $model->fieldset->validation_rules();
$rules = array();
- foreach ($fieldsets as $fieldset => $validation){
+ foreach ($allRules as $field => $validation) {
// If the field is marked as required, eliminate the rule so it doesn't interfere with the default values
// (we are at model level, the rule still applies when creating a new asset using this model)
$index = array_search('required', $validation);
if ($index !== false){
$validation[$index] = 'nullable';
}
- $rules[$fieldset] = $validation;
+ $rules[$field] = $validation;
}
$validator = Validator::make($data, $rules);
@@ -528,9 +499,8 @@ class AssetModelsController extends Controller
/**
* Removes all default values
*
- * @return void
*/
- private function removeCustomFieldsDefaultValues(AssetModel $model)
+ private function removeCustomFieldsDefaultValues(AssetModel|SnipeModel $model): void
{
$model->defaultValues()->detach();
}
diff --git a/app/Http/Controllers/AssetModelsFilesController.php b/app/Http/Controllers/AssetModelsFilesController.php
index a5419b428d..c905282cc5 100644
--- a/app/Http/Controllers/AssetModelsFilesController.php
+++ b/app/Http/Controllers/AssetModelsFilesController.php
@@ -6,8 +6,11 @@ use App\Helpers\StorageHelper;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\AssetModel;
-use Illuminate\Support\Facades\Response;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\Response;
use Illuminate\Support\Facades\Storage;
+use \Symfony\Component\HttpFoundation\StreamedResponse;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
class AssetModelsFilesController extends Controller
{
@@ -16,12 +19,12 @@ class AssetModelsFilesController extends Controller
*
* @param UploadFileRequest $request
* @param int $modelId
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*@since [v1.0]
* @author [A. Gianotto] []
*/
- public function store(UploadFileRequest $request, $modelId = null)
+ public function store(UploadFileRequest $request, $modelId = null) : RedirectResponse
{
if (! $model = AssetModel::find($modelId)) {
return redirect()->route('models.index')->with('error', trans('admin/hardware/message.does_not_exist'));
@@ -38,7 +41,7 @@ class AssetModelsFilesController extends Controller
$file_name = $request->handleFile('private_uploads/assetmodels/','model-'.$model->id,$file);
- $model->logUpload($file_name, e($request->get('notes')));
+ $model->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->with('success', trans('general.file_upload_success'));
@@ -54,10 +57,8 @@ class AssetModelsFilesController extends Controller
* @param int $modelId
* @param int $fileId
* @since [v1.0]
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function show($modelId = null, $fileId = null)
+ public function show($modelId = null, $fileId = null) : StreamedResponse | Response | RedirectResponse | BinaryFileResponse
{
$model = AssetModel::find($modelId);
// the asset is valid
@@ -70,8 +71,6 @@ class AssetModelsFilesController extends Controller
}
$file = 'private_uploads/assetmodels/'.$log->filename;
- \Log::debug('Checking for '.$file);
-
if (! Storage::exists($file)) {
return response('File '.$file.' not found on server', 404)
@@ -103,10 +102,8 @@ class AssetModelsFilesController extends Controller
* @param int $modelId
* @param int $fileId
* @since [v1.0]
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($modelId = null, $fileId = null)
+ public function destroy($modelId = null, $fileId = null) : RedirectResponse
{
$model = AssetModel::find($modelId);
$this->authorize('update', $model);
diff --git a/app/Http/Controllers/Assets/AssetCheckinController.php b/app/Http/Controllers/Assets/AssetCheckinController.php
index 82cb98abe9..4794fa0411 100644
--- a/app/Http/Controllers/Assets/AssetCheckinController.php
+++ b/app/Http/Controllers/Assets/AssetCheckinController.php
@@ -11,9 +11,10 @@ use App\Models\Asset;
use App\Models\CheckoutAcceptance;
use App\Models\LicenseSeat;
use Illuminate\Database\Eloquent\Builder;
-use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\Redirect;
-use Illuminate\Support\Facades\View;
+use Illuminate\Support\Facades\Session;
+use Illuminate\Support\Facades\Log;
+use \Illuminate\Contracts\View\View;
+use \Illuminate\Http\RedirectResponse;
class AssetCheckinController extends Controller
{
@@ -25,11 +26,9 @@ class AssetCheckinController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @param string $backto
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
* @since [v1.0]
*/
- public function create($assetId, $backto = null)
+ public function create($assetId, $backto = null) : View | RedirectResponse
{
// Check if the asset exists
if (is_null($asset = Asset::find($assetId))) {
@@ -39,7 +38,17 @@ class AssetCheckinController extends Controller
$this->authorize('checkin', $asset);
- return view('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto);
+ // This asset is already checked in, redirect
+
+ if (is_null($asset->assignedTo)) {
+ return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
+ }
+
+ if (!$asset->model) {
+ return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
+ }
+
+ return view('hardware/checkin', compact('asset'))->with('statusLabel_list', Helper::statusLabelList())->with('backto', $backto)->with('table_name', 'Assets');
}
/**
@@ -49,11 +58,9 @@ class AssetCheckinController extends Controller
* @param AssetCheckinRequest $request
* @param int $assetId
* @param null $backto
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
* @since [v1.0]
*/
- public function store(AssetCheckinRequest $request, $assetId = null, $backto = null)
+ public function store(AssetCheckinRequest $request, $assetId = null, $backto = null) : RedirectResponse
{
// Check if the asset exists
if (is_null($asset = Asset::find($assetId))) {
@@ -64,6 +71,11 @@ class AssetCheckinController extends Controller
if (is_null($target = $asset->assignedTo)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkin.already_checked_in'));
}
+
+ if (!$asset->model) {
+ return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
+ }
+
$this->authorize('checkin', $asset);
if ($asset->assignedType() == Asset::USER) {
@@ -86,7 +98,7 @@ class AssetCheckinController extends Controller
$asset->location_id = $asset->rtd_location_id;
if ($request->filled('location_id')) {
- \Log::debug('NEW Location ID: '.$request->get('location_id'));
+ Log::debug('NEW Location ID: '.$request->get('location_id'));
$asset->location_id = $request->get('location_id');
if ($request->get('update_default_location') == 0){
@@ -116,15 +128,12 @@ class AssetCheckinController extends Controller
$acceptance->delete();
});
+ 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));
- if ((isset($user)) && ($backto == 'user')) {
- return redirect()->route('users.show', $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
- }
-
- return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkin.success'));
+ event(new CheckoutableCheckedIn($asset, $target, auth()->user(), $request->input('note'), $checkin_at, $originalValues));
+ 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());
diff --git a/app/Http/Controllers/Assets/AssetCheckoutController.php b/app/Http/Controllers/Assets/AssetCheckoutController.php
index a096f16678..355f9387bb 100644
--- a/app/Http/Controllers/Assets/AssetCheckoutController.php
+++ b/app/Http/Controllers/Assets/AssetCheckoutController.php
@@ -9,7 +9,9 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\AssetCheckoutRequest;
use App\Models\Asset;
use Illuminate\Database\Eloquent\ModelNotFoundException;
-use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Session;
+use \Illuminate\Contracts\View\View;
+use \Illuminate\Http\RedirectResponse;
class AssetCheckoutController extends Controller
{
@@ -22,9 +24,9 @@ class AssetCheckoutController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v1.0]
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
- public function create($assetId)
+ public function create($assetId) : View | RedirectResponse
{
// Check if the asset exists
if (is_null($asset = Asset::with('company')->find(e($assetId)))) {
@@ -33,11 +35,17 @@ class AssetCheckoutController extends Controller
$this->authorize('checkout', $asset);
+ if (!$asset->model) {
+ return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
+ }
+
if ($asset->availableForCheckout()) {
return view('hardware/checkout', compact('asset'))
- ->with('statusLabel_list', Helper::deployableStatusLabelList());
+ ->with('statusLabel_list', Helper::deployableStatusLabelList())
+ ->with('table_name', 'Assets');
}
+
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
}
@@ -46,11 +54,9 @@ class AssetCheckoutController extends Controller
*
* @author [A. Gianotto] []
* @param AssetCheckoutRequest $request
- * @param int $assetId
- * @return Redirect
* @since [v1.0]
*/
- public function store(AssetCheckoutRequest $request, $assetId)
+ public function store(AssetCheckoutRequest $request, $assetId) : RedirectResponse
{
try {
// Check if the asset exists
@@ -60,9 +66,14 @@ class AssetCheckoutController extends Controller
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.checkout.not_available'));
}
$this->authorize('checkout', $asset);
- $admin = Auth::user();
- $target = $this->determineCheckoutTarget($asset);
+ if (!$asset->model) {
+ return redirect()->route('hardware.show', $asset->id)->with('error', trans('admin/hardware/general.model_invalid_fix'));
+ }
+
+ $admin = auth()->user();
+
+ $target = $this->determineCheckoutTarget();
$asset = $this->updateAssetLocation($asset, $target);
@@ -97,11 +108,12 @@ class AssetCheckoutController extends Controller
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('general.error_user_company'));
}
}
-
- if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, $request->get('note'), $request->get('name'))) {
- return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkout.success'));
- }
+ 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 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());
} catch (ModelNotFoundException $e) {
diff --git a/app/Http/Controllers/Assets/AssetFilesController.php b/app/Http/Controllers/Assets/AssetFilesController.php
index 7f4258bda2..b5a04759bb 100644
--- a/app/Http/Controllers/Assets/AssetFilesController.php
+++ b/app/Http/Controllers/Assets/AssetFilesController.php
@@ -7,8 +7,12 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\Asset;
-use Illuminate\Support\Facades\Response;
+use \Illuminate\Http\Response;
use Illuminate\Support\Facades\Storage;
+use \Illuminate\Contracts\View\View;
+use \Illuminate\Http\RedirectResponse;
+use Symfony\Component\HttpFoundation\StreamedResponse;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
class AssetFilesController extends Controller
{
@@ -17,12 +21,12 @@ class AssetFilesController extends Controller
*
* @param UploadFileRequest $request
* @param int $assetId
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*@since [v1.0]
* @author [A. Gianotto] []
*/
- public function store(UploadFileRequest $request, $assetId = null)
+ public function store(UploadFileRequest $request, $assetId = null) : RedirectResponse
{
if (! $asset = Asset::find($assetId)) {
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
@@ -38,7 +42,7 @@ class AssetFilesController extends Controller
foreach ($request->file('file') as $file) {
$file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
- $asset->logUpload($file_name, e($request->get('notes')));
+ $asset->logUpload($file_name, $request->get('notes'));
}
return redirect()->back()->with('success', trans('admin/hardware/message.upload.success'));
@@ -54,10 +58,8 @@ class AssetFilesController extends Controller
* @param int $assetId
* @param int $fileId
* @since [v1.0]
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function show($assetId = null, $fileId = null)
+ public function show($assetId = null, $fileId = null) : View | RedirectResponse | Response | StreamedResponse | BinaryFileResponse
{
$asset = Asset::find($assetId);
// the asset is valid
@@ -70,7 +72,6 @@ class AssetFilesController extends Controller
}
$file = 'private_uploads/assets/'.$log->filename;
- \Log::debug('Checking for '.$file);
if ($log->action_type == 'audit') {
$file = 'private_uploads/audits/'.$log->filename;
@@ -106,10 +107,8 @@ class AssetFilesController extends Controller
* @param int $assetId
* @param int $fileId
* @since [v1.0]
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($assetId = null, $fileId = null)
+ public function destroy($assetId = null, $fileId = null) : RedirectResponse
{
$asset = Asset::find($assetId);
$this->authorize('update', $asset);
@@ -132,7 +131,6 @@ class AssetFilesController extends Controller
->with('success', trans('admin/hardware/message.deletefile.success'));
}
- // Redirect to the hardware management page
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
}
}
diff --git a/app/Http/Controllers/Assets/AssetsController.php b/app/Http/Controllers/Assets/AssetsController.php
index 6054718e6b..c929306184 100755
--- a/app/Http/Controllers/Assets/AssetsController.php
+++ b/app/Http/Controllers/Assets/AssetsController.php
@@ -6,7 +6,7 @@ use App\Helpers\Helper;
use App\Http\Controllers\Controller;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Actionlog;
-use App\Models\Manufacturer;
+use App\Http\Requests\UploadFileRequest;
use Illuminate\Support\Facades\Log;
use App\Models\Asset;
use App\Models\AssetModel;
@@ -20,14 +20,16 @@ use Illuminate\Support\Facades\Auth;
use App\View\Label;
use Carbon\Carbon;
use Illuminate\Support\Facades\DB;
-use Illuminate\Support\Facades\View;
use Illuminate\Support\Facades\Gate;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use League\Csv\Reader;
-use Illuminate\Support\Facades\Redirect;
+use Illuminate\Http\Response;
+use Illuminate\Contracts\View\View;
+use Illuminate\Http\RedirectResponse;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
/**
* This class controls all actions related to assets for
@@ -55,10 +57,8 @@ class AssetsController extends Controller
* @see AssetController::getDatatable() method that generates the JSON response
* @since [v1.0]
* @param Request $request
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function index(Request $request)
+ public function index(Request $request) : View
{
$this->authorize('index', Asset::class);
$company = Company::find($request->input('company_id'));
@@ -72,13 +72,12 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @since [v1.0]
* @param Request $request
- * @return View
* @internal param int $model_id
*/
- public function create(Request $request)
+ public function create(Request $request) : View
{
$this->authorize('create', Asset::class);
- $view = View::make('hardware/edit')
+ $view = view('hardware/edit')
->with('statuslabel_list', Helper::statusLabelList())
->with('item', new Asset)
->with('statuslabel_types', Helper::statusTypeList());
@@ -96,9 +95,8 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.0]
- * @return Redirect
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : RedirectResponse
{
$this->authorize(Asset::class);
@@ -198,7 +196,7 @@ class AssetsController extends Controller
}
if (isset($target)) {
- $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);
+ $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);
}
$success = true;
@@ -207,7 +205,6 @@ class AssetsController extends Controller
}
if ($success) {
- \Log::debug(e($asset->asset_tag));
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)]));
@@ -217,11 +214,6 @@ class AssetsController extends Controller
return redirect()->back()->withInput()->withErrors($asset->getErrors());
}
- public function getOptionCookie(Request $request){
- $value = $request->cookie('optional_info');
- echo $value;
- return $value;
- }
/**
* Returns a view that presents a form to edit an existing asset.
@@ -229,9 +221,9 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v1.0]
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
- public function edit($assetId = null)
+ public function edit($assetId = null) : View | RedirectResponse
{
if (! $item = Asset::find($assetId)) {
// Redirect to the asset management page with error
@@ -252,9 +244,9 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v1.0]
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
- public function show($assetId = null)
+ public function show($assetId = null) : View | RedirectResponse
{
$asset = Asset::withTrashed()->find($assetId);
$this->authorize('view', $asset);
@@ -292,11 +284,10 @@ class AssetsController extends Controller
* Validate and process asset edit form.
*
* @param int $assetId
- * @return \Illuminate\Http\RedirectResponse|Redirect
- *@since [v1.0]
+ * @since [v1.0]
* @author [A. Gianotto] []
*/
- public function update(ImageUploadRequest $request, $assetId = null)
+ public function update(ImageUploadRequest $request, $assetId = null) : RedirectResponse
{
// Check if the asset exists
if (! $asset = Asset::find($assetId)) {
@@ -308,7 +299,8 @@ class AssetsController extends Controller
$asset->status_id = $request->input('status_id', null);
$asset->warranty_months = $request->input('warranty_months', null);
$asset->purchase_cost = $request->input('purchase_cost', null);
- $asset->purchase_date = $request->input('purchase_date', null);
+ $asset->purchase_date = $request->input('purchase_date', null);
+ $asset->next_audit_date = $request->input('next_audit_date', null);
if ($request->filled('purchase_date') && !$request->filled('asset_eol_date') && ($asset->model->eol > 0)) {
$asset->purchase_date = $request->input('purchase_date', null);
$asset->asset_eol_date = Carbon::parse($request->input('purchase_date'))->addMonths($asset->model->eol)->format('Y-m-d');
@@ -410,9 +402,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v1.0]
- * @return Redirect
*/
- public function destroy($assetId)
+ public function destroy($assetId) : RedirectResponse
{
// Check if the asset exists
if (is_null($asset = Asset::find($assetId))) {
@@ -444,9 +435,8 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] []
* @since [v3.0]
- * @return Redirect
*/
- public function getAssetBySerial(Request $request)
+ public function getAssetBySerial(Request $request) : RedirectResponse
{
$topsearch = ($request->get('topsearch')=="true");
@@ -462,9 +452,9 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] []
* @since [v3.0]
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
- public function getAssetByTag(Request $request, $tag=null)
+ public function getAssetByTag(Request $request, $tag=null) : RedirectResponse
{
$tag = $tag ? $tag : $request->get('assetTag');
$topsearch = ($request->get('topsearch') == 'true');
@@ -484,9 +474,8 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v1.0]
- * @return Response
*/
- public function getQrCode($assetId = null)
+ public function getQrCode($assetId = null) : Response | BinaryFileResponse | string | bool
{
$settings = Setting::getSettings();
@@ -513,6 +502,7 @@ class AssetsController extends Controller
return 'That asset is invalid';
}
+ return false;
}
/**
@@ -560,7 +550,7 @@ class AssetsController extends Controller
*
* @author [L. Swartzendruber] [
* @param int $assetId
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function getLabel($assetId = null)
{
@@ -584,7 +574,7 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v1.0]
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function getClone($assetId = null)
{
@@ -613,7 +603,7 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.0]
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function getImportHistory()
{
@@ -635,7 +625,7 @@ class AssetsController extends Controller
*
* @author [A. Gianotto] []
* @since [v3.3]
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function postImportHistory(Request $request)
{
@@ -729,8 +719,8 @@ class AssetsController extends Controller
Actionlog::firstOrCreate([
'item_id' => $asset->id,
'item_type' => Asset::class,
- 'user_id' => Auth::user()->id,
- 'note' => 'Checkout imported by '.Auth::user()->present()->fullName().' from history importer',
+ '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,
'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'],
@@ -757,8 +747,8 @@ class AssetsController extends Controller
Actionlog::firstOrCreate([
'item_id' => $item[$asset_tag][$batch_counter]['asset_id'],
'item_type' => Asset::class,
- 'user_id' => Auth::user()->id,
- 'note' => 'Checkin imported by '.Auth::user()->present()->fullName().' from history importer',
+ 'user_id' => auth()->id(),
+ 'note' => 'Checkin imported by '.auth()->user()->present()->fullName().' from history importer',
'target_id' => null,
'created_at' => $checkin_date,
'action_type' => 'checkin',
@@ -795,7 +785,7 @@ class AssetsController extends Controller
* @author [A. Gianotto] []
* @param int $assetId
* @since [v1.0]
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function getRestore($assetId = null)
{
@@ -854,15 +844,15 @@ class AssetsController extends Controller
return view('hardware/audit-due');
}
- public function overdueForAudit()
+ public function dueForCheckin()
{
- $this->authorize('audit', Asset::class);
+ $this->authorize('checkin', Asset::class);
- return view('hardware/audit-overdue');
+ return view('hardware/checkin-due');
}
- public function auditStore(Request $request, $id)
+ public function auditStore(UploadFileRequest $request, $id)
{
$this->authorize('audit', Asset::class);
@@ -879,7 +869,21 @@ class AssetsController extends Controller
$asset = Asset::findOrFail($id);
- // We don't want to log this as a normal update, so let's bypass that
+ /**
+ * Even though we do a save() further down, we don't want to log this as a "normal" asset update,
+ * which would trigger the Asset Observer and would log an asset *update* log entry (because the
+ * de-normed fields like next_audit_date on the asset itself will change on save()) *in addition* to
+ * the audit log entry we're creating through this controller.
+ *
+ * To prevent this double-logging (one for update and one for audit), we skip the observer and bypass
+ * that de-normed update log entry by using unsetEventDispatcher(), BUT invoking unsetEventDispatcher()
+ * will bypass normal model-level validation that's usually handled at the observer )
+ *
+ * We handle validation on the save() by checking if the asset is valid via the ->isValid() method,
+ * which manually invokes Watson Validating to make sure the asset's model is valid.
+ *
+ * @see \App\Observers\AssetObserver::updating()
+ */
$asset->unsetEventDispatcher();
$asset->next_audit_date = $request->input('next_audit_date');
@@ -888,29 +892,27 @@ class AssetsController extends Controller
// Check to see if they checked the box to update the physical location,
// not just note it in the audit notes
if ($request->input('update_location') == '1') {
- Log::debug('update location in audit');
$asset->location_id = $request->input('location_id');
}
+
+ /**
+ * Invoke Watson Validating to check the asset itself and check to make sure it saved correctly.
+ * We have to invoke this manually because of the unsetEventDispatcher() above.)
+ */
+ if ($asset->isValid() && $asset->save()) {
- if ($asset->save()) {
- $file_name = '';
- // Upload an image, if attached
+ $file_name = null;
+ // Create the image (if one was chosen.)
if ($request->hasFile('image')) {
- $path = 'private_uploads/audits';
- if (! Storage::exists($path)) {
- Storage::makeDirectory($path, 775);
- }
- $upload = $image = $request->file('image');
- $ext = $image->getClientOriginalExtension();
- $file_name = 'audit-'.str_random(18).'.'.$ext;
- Storage::putFileAs($path, $upload, $file_name);
+ $file_name = $request->handleFile('private_uploads/audits/', 'audit-'.$asset->id, $request->file('image'));
}
-
$asset->logAudit($request->input('note'), $request->input('location_id'), $file_name);
return redirect()->route('assets.audit.due')->with('success', trans('admin/hardware/message.audit.success'));
}
+
+ return redirect()->back()->withInput()->withErrors($asset->getErrors());
}
public function getRequestedIndex($user_id = null)
diff --git a/app/Http/Controllers/Assets/BulkAssetsController.php b/app/Http/Controllers/Assets/BulkAssetsController.php
index 561e13b200..13f9c4fc92 100644
--- a/app/Http/Controllers/Assets/BulkAssetsController.php
+++ b/app/Http/Controllers/Assets/BulkAssetsController.php
@@ -2,7 +2,6 @@
namespace App\Http\Controllers\Assets;
-use App\Models\Actionlog;
use App\Helpers\Helper;
use App\Http\Controllers\CheckInOutRequest;
use App\Http\Controllers\Controller;
@@ -12,12 +11,15 @@ use App\Models\Statuslabel;
use App\Models\Setting;
use App\View\Label;
use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Crypt;
use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\Gate;
use Illuminate\Support\Facades\Log;
-use Illuminate\Support\Facades\Session;
use App\Http\Requests\AssetCheckoutRequest;
use App\Models\CustomField;
+use Illuminate\Contracts\View\View;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Database\Eloquent\ModelNotFoundException;
class BulkAssetsController extends Controller
{
@@ -34,12 +36,10 @@ class BulkAssetsController extends Controller
* action would make a lot more sense here and make things a lot more clear.
*
* @author [A. Gianotto] []
- * @return View
* @internal param int $assetId
* @since [v2.0]
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit(Request $request)
+ public function edit(Request $request) : View | RedirectResponse
{
$this->authorize('view', Asset::class);
@@ -189,11 +189,10 @@ class BulkAssetsController extends Controller
* Save bulk edits
*
* @author [A. Gianotto] []
- * @return Redirect
* @internal param array $assets
* @since [v2.0]
*/
- public function update(Request $request)
+ public function update(Request $request) : RedirectResponse
{
$this->authorize('update', Asset::class);
$has_errors = 0;
@@ -214,7 +213,7 @@ class BulkAssetsController extends Controller
}
- $assets = Asset::whereIn('id', array_keys($request->input('ids')))->get();
+ $assets = Asset::whereIn('id', $request->input('ids'))->get();
@@ -379,28 +378,30 @@ class BulkAssetsController extends Controller
foreach ($asset->model->fieldset->fields as $field) {
if ((array_key_exists($field->db_column, $this->update_array)) && ($field->field_encrypted == '1')) {
- $decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
+ if (Gate::allows('admin')) {
+ $decrypted_old = Helper::gracefulDecrypt($field, $asset->{$field->db_column});
- /*
- * Check if the decrypted existing value is different from one we just submitted
- * and if not, pull it out of the object since it shouldn't really be updating at all.
- * If we don't do this, it will try to re-encrypt it, and the same value encrypted two
- * different times will have different values, so it will *look* like it was updated
- * but it wasn't.
- */
- if ($decrypted_old != $this->update_array[$field->db_column]) {
- $asset->{$field->db_column} = \Crypt::encrypt($this->update_array[$field->db_column]);
- } else {
/*
- * Remove the encrypted custom field from the update_array, since nothing changed
+ * Check if the decrypted existing value is different from one we just submitted
+ * and if not, pull it out of the object since it shouldn't really be updating at all.
+ * If we don't do this, it will try to re-encrypt it, and the same value encrypted two
+ * different times will have different values, so it will *look* like it was updated
+ * but it wasn't.
*/
- unset($this->update_array[$field->db_column]);
- unset($asset->{$field->db_column});
- }
+ if ($decrypted_old != $this->update_array[$field->db_column]) {
+ $asset->{$field->db_column} = Crypt::encrypt($this->update_array[$field->db_column]);
+ } else {
+ /*
+ * Remove the encrypted custom field from the update_array, since nothing changed
+ */
+ unset($this->update_array[$field->db_column]);
+ unset($asset->{$field->db_column});
+ }
- /*
- * These custom fields aren't encrypted, just carry on as usual
- */
+ /*
+ * These custom fields aren't encrypted, just carry on as usual
+ */
+ }
} else {
if ((array_key_exists($field->db_column, $this->update_array)) && ($asset->{$field->db_column} != $this->update_array[$field->db_column])) {
@@ -452,9 +453,8 @@ class BulkAssetsController extends Controller
/**
* Adds parameter to update array for an item if it exists in request
* @param string $field field name
- * @return BulkAssetsController Model for Chaining
*/
- protected function conditionallyAddItem($field)
+ protected function conditionallyAddItem($field) : BulkAssetsController
{
if (request()->filled($field)) {
$this->update_array[$field] = request()->input($field);
@@ -468,12 +468,10 @@ class BulkAssetsController extends Controller
*
* @author [A. Gianotto] []
* @param Request $request
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
* @internal param array $assets
* @since [v2.0]
*/
- public function destroy(Request $request)
+ public function destroy(Request $request) : RedirectResponse
{
$this->authorize('delete', Asset::class);
@@ -502,27 +500,23 @@ class BulkAssetsController extends Controller
/**
* Show Bulk Checkout Page
- * @return View View to checkout multiple assets
*/
- public function showCheckout()
+ public function showCheckout() : View
{
$this->authorize('checkout', Asset::class);
- // Filter out assets that are not deployable.
-
return view('hardware/bulk-checkout');
}
/**
* Process Multiple Checkout Request
- * @return View
*/
- public function storeCheckout(AssetCheckoutRequest $request)
+ public function storeCheckout(AssetCheckoutRequest $request) : RedirectResponse | ModelNotFoundException
{
$this->authorize('checkout', Asset::class);
try {
- $admin = Auth::user();
+ $admin = auth()->user();
$target = $this->determineCheckoutTarget();
@@ -581,17 +575,19 @@ class BulkAssetsController extends Controller
}
}
- public function restore(Request $request) {
+ public function restore(Request $request) : RedirectResponse
+ {
$this->authorize('update', Asset::class);
- $assetIds = $request->get('ids');
- if (empty($assetIds)) {
- return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.restore.nothing_updated'));
+ $assetIds = $request->get('ids');
+
+ if (empty($assetIds)) {
+ return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.restore.nothing_updated'));
} else {
foreach ($assetIds as $key => $assetId) {
- $asset = Asset::withTrashed()->find($assetId);
- $asset->restore();
+ $asset = Asset::withTrashed()->find($assetId);
+ $asset->restore();
}
- return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.restore.success'));
+ return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.restore.success'));
}
}
}
diff --git a/app/Http/Controllers/Auth/ForgotPasswordController.php b/app/Http/Controllers/Auth/ForgotPasswordController.php
index cb661eabde..a7322e7e59 100644
--- a/app/Http/Controllers/Auth/ForgotPasswordController.php
+++ b/app/Http/Controllers/Auth/ForgotPasswordController.php
@@ -5,7 +5,7 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
use Illuminate\Http\Request;
-
+use Illuminate\Support\Facades\Log;
class ForgotPasswordController extends Controller
{
/*
@@ -79,16 +79,16 @@ class ForgotPasswordController extends Controller
)
);
} catch(\Exception $e) {
- \Log::info('Password reset attempt: User '.$request->input('username').'failed with exception: '.$e );
+ Log::info('Password reset attempt: User '.$request->input('username').'failed with exception: '.$e );
}
// Prevent timing attack to enumerate users.
usleep(500000 + random_int(0, 1500000));
if ($response === \Password::RESET_LINK_SENT) {
- \Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent');
+ Log::info('Password reset attempt: User '.$request->input('username').' WAS found, password reset sent');
} else {
- \Log::info('Password reset attempt: User matching username '.$request->input('username').' NOT FOUND or user is inactive');
+ Log::info('Password reset attempt: User matching username '.$request->input('username').' NOT FOUND or user is inactive');
}
/**
diff --git a/app/Http/Controllers/Auth/LoginController.php b/app/Http/Controllers/Auth/LoginController.php
index 896ca11ff5..9ac976b43c 100644
--- a/app/Http/Controllers/Auth/LoginController.php
+++ b/app/Http/Controllers/Auth/LoginController.php
@@ -16,7 +16,7 @@ use Illuminate\Support\Carbon;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
-use Log;
+use Illuminate\Support\Facades\Log;
use Redirect;
/**
@@ -122,12 +122,12 @@ class LoginController extends Controller
Auth::login($user);
} else {
$username = $saml->getUsername();
- \Log::debug("SAML user '$username' could not be found in database.");
+ Log::debug("SAML user '$username' could not be found in database.");
$request->session()->flash('error', trans('auth/message.signin.error'));
$saml->clearData();
}
- if ($user = Auth::user()) {
+ if ($user = auth()->user()) {
$user->last_login = \Carbon::now();
$user->saveQuietly();
}
@@ -137,7 +137,7 @@ class LoginController extends Controller
$s->save();
} catch (\Exception $e) {
- \Log::debug('There was an error authenticating the SAML user: '.$e->getMessage());
+ Log::debug('There was an error authenticating the SAML user: '.$e->getMessage());
throw $e;
}
@@ -146,7 +146,7 @@ class LoginController extends Controller
// Better logging
if (empty($samlData)) {
- \Log::debug("SAML page requested, but samlData seems empty.");
+ Log::debug("SAML page requested, but samlData seems empty.");
}
}
@@ -261,19 +261,19 @@ class LoginController extends Controller
/**
* Account sign in form processing.
*
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
public function login(Request $request)
{
//If the environment is set to ALWAYS require SAML, return access denied
if (config('app.require_saml')) {
- \Log::debug('require SAML is enabled in the .env - return a 403');
+ Log::debug('require SAML is enabled in the .env - return a 403');
return view('errors.403');
}
if (Setting::getSettings()->login_common_disabled == '1') {
- \Log::debug('login_common_disabled is set to 1 - return a 403');
+ Log::debug('login_common_disabled is set to 1 - return a 403');
return view('errors.403');
}
@@ -326,7 +326,7 @@ class LoginController extends Controller
}
}
- if ($user = Auth::user()) {
+ if ($user = auth()->user()) {
$user->last_login = \Carbon::now();
$user->activated = 1;
$user->saveQuietly();
@@ -339,7 +339,7 @@ class LoginController extends Controller
/**
* Two factor enrollment page
*
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
public function getTwoFactorEnroll()
{
@@ -350,7 +350,7 @@ class LoginController extends Controller
}
$settings = Setting::getSettings();
- $user = Auth::user();
+ $user = auth()->user();
// We wouldn't normally see this page if 2FA isn't enforced via the
// \App\Http\Middleware\CheckForTwoFactor middleware AND if a device isn't enrolled,
@@ -389,7 +389,7 @@ class LoginController extends Controller
/**
* Two factor code form page
*
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
public function getTwoFactorAuth()
{
@@ -398,7 +398,7 @@ class LoginController extends Controller
return redirect()->route('login')->with('error', trans('auth/general.login_prompt'));
}
- $user = Auth::user();
+ $user = auth()->user();
// Check whether there is a device enrolled.
// This *should* be handled via the \App\Http\Middleware\CheckForTwoFactor middleware
@@ -415,7 +415,7 @@ class LoginController extends Controller
*
* @param Request $request
*
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
public function postTwoFactorAuth(Request $request)
{
@@ -427,11 +427,7 @@ class LoginController extends Controller
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.code_required'));
}
- if (! $request->has('two_factor_secret')) { // TODO this seems almost the same as above?
- return redirect()->route('two-factor')->with('error', 'Two-factor code is required.');
- }
-
- $user = Auth::user();
+ $user = auth()->user();
$secret = $request->input('two_factor_secret');
if (Google2FA::verifyKey($user->two_factor_secret, $secret)) {
@@ -439,7 +435,7 @@ class LoginController extends Controller
$user->saveQuietly();
$request->session()->put('2fa_authed', $user->id);
- return redirect()->route('home')->with('success', 'You are logged in!');
+ return redirect()->route('home')->with('success', trans('auth/message.signin.success'));
}
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.invalid_code'));
@@ -451,7 +447,7 @@ class LoginController extends Controller
*
* @param Request $request
*
- * @return Redirect
+ * @return Illuminate\Http\RedirectResponse
*/
public function logout(Request $request)
{
@@ -537,7 +533,7 @@ class LoginController extends Controller
$minutes = round($seconds / 60);
- $message = \Lang::get('auth/message.throttle', ['minutes' => $minutes]);
+ $message = trans('auth/message.throttle', ['minutes' => $minutes]);
return redirect()->back()
->withInput($request->only($this->username(), 'remember'))
diff --git a/app/Http/Controllers/Auth/ResetPasswordController.php b/app/Http/Controllers/Auth/ResetPasswordController.php
index e7a0fb1af8..fe1b331289 100644
--- a/app/Http/Controllers/Auth/ResetPasswordController.php
+++ b/app/Http/Controllers/Auth/ResetPasswordController.php
@@ -7,7 +7,7 @@ use App\Models\Setting;
use App\Models\User;
use Illuminate\Foundation\Auth\ResetsPasswords;
use Illuminate\Http\Request;
-
+use Illuminate\Support\Facades\Log;
class ResetPasswordController extends Controller
{
@@ -66,7 +66,7 @@ class ResetPasswordController extends Controller
$credentials = $request->only('email', 'token');
if (is_null($this->broker()->getUser($credentials))) {
- \Log::debug('Password reset form FAILED - this token is not valid.');
+ Log::debug('Password reset form FAILED - this token is not valid.');
return redirect()->route('password.request')->with('error', trans('passwords.token'));
}
@@ -89,10 +89,10 @@ class ResetPasswordController extends Controller
$request->validate($this->rules(), $request->all(), $this->validationErrorMessages());
- \Log::debug('Checking if '.$request->input('username').' exists');
+ 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
if ($user = User::where('username', '=', $request->input('username'))->where('activated', '1')->whereNotNull('email')->first()) {
- \Log::debug($user->username.' exists');
+ Log::debug($user->username.' exists');
// handle the password validation rules set by the admin settings
@@ -112,17 +112,17 @@ class ResetPasswordController extends Controller
// Check if the password reset above actually worked
if ($response == \Password::PASSWORD_RESET) {
- \Log::debug('Password reset for '.$user->username.' worked');
+ Log::debug('Password reset for '.$user->username.' worked');
return redirect()->guest('login')->with('success', trans('passwords.reset'));
}
- \Log::debug('Password reset for '.$user->username.' FAILED - this user exists but the token is not valid');
+ Log::debug('Password reset for '.$user->username.' FAILED - this user exists but the token is not valid');
return redirect()->back()->withInput($request->only('email'))->with('success', trans('passwords.reset'));
}
- \Log::debug('Password reset for '.$request->input('username').' FAILED - user does not exist or does not have an email address - but make it look like it succeeded');
+ Log::debug('Password reset for '.$request->input('username').' FAILED - user does not exist or does not have an email address - but make it look like it succeeded');
return redirect()->guest('login')->with('success', trans('passwords.reset'));
}
diff --git a/app/Http/Controllers/Auth/SamlController.php b/app/Http/Controllers/Auth/SamlController.php
index b6218988ea..769f903494 100644
--- a/app/Http/Controllers/Auth/SamlController.php
+++ b/app/Http/Controllers/Auth/SamlController.php
@@ -5,7 +5,7 @@ namespace App\Http\Controllers\Auth;
use App\Http\Controllers\Controller;
use App\Services\Saml;
use Illuminate\Http\Request;
-use Log;
+use Illuminate\Support\Facades\Log;
/**
* This controller provides the endpoint for SAML communication and metadata.
@@ -51,7 +51,7 @@ class SamlController extends Controller
$metadata = $this->saml->getSPMetadata();
if (empty($metadata)) {
- \Log::debug('SAML metadata is empty - return a 403');
+ Log::debug('SAML metadata is empty - return a 403');
return response()->view('errors.403', [], 403);
}
@@ -71,7 +71,7 @@ class SamlController extends Controller
*
* @param Request $request
*
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
public function login(Request $request)
{
@@ -93,7 +93,7 @@ class SamlController extends Controller
*
* @param Request $request
*
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
public function acs(Request $request)
{
@@ -126,7 +126,7 @@ class SamlController extends Controller
*
* @param Request $request
*
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
public function sls(Request $request)
{
diff --git a/app/Http/Controllers/BulkAssetModelsController.php b/app/Http/Controllers/BulkAssetModelsController.php
index a312ba1f6e..36b21178b0 100644
--- a/app/Http/Controllers/BulkAssetModelsController.php
+++ b/app/Http/Controllers/BulkAssetModelsController.php
@@ -5,8 +5,8 @@ namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Models\AssetModel;
use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Input;
-use Illuminate\Support\Facades\Redirect;
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
class BulkAssetModelsController extends Controller
{
@@ -16,9 +16,8 @@ class BulkAssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v1.7]
* @param Request $request
- * @return \Illuminate\Contracts\View\View
*/
- public function edit(Request $request)
+ public function edit(Request $request) : View | RedirectResponse
{
$models_raw_array = $request->input('ids');
@@ -61,9 +60,8 @@ class BulkAssetModelsController extends Controller
* @author [A. Gianotto] []
* @since [v1.7]
* @param Request $request
- * @return \Illuminate\Contracts\View\View
*/
- public function update(Request $request)
+ public function update(Request $request): View | RedirectResponse
{
$this->authorize('update', AssetModel::class);
@@ -105,9 +103,8 @@ class BulkAssetModelsController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.0]
- * @return Redirect
*/
- public function destroy(Request $request)
+ public function destroy(Request $request) : RedirectResponse
{
$this->authorize('delete', AssetModel::class);
diff --git a/app/Http/Controllers/CategoriesController.php b/app/Http/Controllers/CategoriesController.php
index 5844b54dc8..ac57ad6a6d 100755
--- a/app/Http/Controllers/CategoriesController.php
+++ b/app/Http/Controllers/CategoriesController.php
@@ -4,10 +4,11 @@ namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Http\Requests\ImageUploadRequest;
-use App\Models\Category as Category;
-use Auth;
+use App\Models\Category;
+use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
-use Str;
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
/**
* This class controls all actions related to Categories for
@@ -25,10 +26,8 @@ class CategoriesController extends Controller
* @author [A. Gianotto] []
* @see CategoriesController::getDatatable() method that generates the JSON response
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function index()
+ public function index() : View
{
// Show the page
$this->authorize('view', Category::class);
@@ -42,10 +41,8 @@ class CategoriesController extends Controller
* @author [A. Gianotto] []
* @see CategoriesController::store() method that stores the data
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create()
+ public function create() : View
{
// Show the page
$this->authorize('create', Category::class);
@@ -61,10 +58,8 @@ class CategoriesController extends Controller
* @see CategoriesController::create() method that makes the form.
* @since [v1.0]
* @param ImageUploadRequest $request
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : RedirectResponse
{
$this->authorize('create', Category::class);
$category = new Category();
@@ -91,10 +86,8 @@ class CategoriesController extends Controller
* @see CategoriesController::postEdit() method saves the data
* @param int $categoryId
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit($categoryId = null)
+ public function edit($categoryId = null) : RedirectResponse | View
{
$this->authorize('update', Category::class);
if (is_null($item = Category::find($categoryId))) {
@@ -112,23 +105,31 @@ class CategoriesController extends Controller
* @see CategoriesController::getEdit() method that makes the form.
* @param ImageUploadRequest $request
* @param int $categoryId
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
* @since [v1.0]
*/
- public function update(ImageUploadRequest $request, $categoryId = null)
+ public function update(ImageUploadRequest $request, $categoryId = null) : RedirectResponse
{
$this->authorize('update', Category::class);
if (is_null($category = Category::find($categoryId))) {
// Redirect to the categories management page
- return redirect()->to('admin/categories')->with('error', trans('admin/categories/message.does_not_exist'));
+ return redirect()->route('categories.index')->with('error', trans('admin/categories/message.does_not_exist'));
}
// Update the category data
$category->name = $request->input('name');
// If the item count is > 0, we disable the category type in the edit. Disabled items
// don't POST, so if the category_type is blank we just set it to the default.
+
+
+ // Don't allow the user to change the category_type once it's been created
+ if (($request->filled('category_type') && ($category->itemCount() > 0))) {
+ $request->validate(['category_type' => 'in:'.$category->category_type]);
+ }
+
$category->category_type = $request->input('category_type', $category->category_type);
+
+ $category->fill($request->all());
+
$category->eula_text = $request->input('eula_text');
$category->use_default_eula = $request->input('use_default_eula', '0');
$category->require_acceptance = $request->input('require_acceptance', '0');
@@ -150,10 +151,8 @@ class CategoriesController extends Controller
* @author [A. Gianotto] []
* @since [v1.0]
* @param int $categoryId
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($categoryId)
+ public function destroy($categoryId) : RedirectResponse
{
$this->authorize('delete', Category::class);
// Check if the category exists
@@ -178,11 +177,9 @@ class CategoriesController extends Controller
* @author [A. Gianotto] []
* @see CategoriesController::getDataView() method that generates the JSON response
* @param $id
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
* @since [v1.8]
*/
- public function show($id)
+ public function show($id) : View | RedirectResponse
{
$this->authorize('view', Category::class);
if ($category = Category::find($id)) {
diff --git a/app/Http/Controllers/CheckInOutRequest.php b/app/Http/Controllers/CheckInOutRequest.php
index 6dd7e4aba3..328553eb49 100644
--- a/app/Http/Controllers/CheckInOutRequest.php
+++ b/app/Http/Controllers/CheckInOutRequest.php
@@ -11,9 +11,8 @@ trait CheckInOutRequest
{
/**
* Find target for checkout
- * @return SnipeModel Target asset is being checked out to.
*/
- protected function determineCheckoutTarget()
+ protected function determineCheckoutTarget() : ?SnipeModel
{
// This item is checked out to a location
switch (request('checkout_to_type')) {
@@ -34,7 +33,7 @@ trait CheckInOutRequest
* @param SnipeModel $target Target with location
* @return Asset Asset being updated
*/
- protected function updateAssetLocation($asset, $target)
+ protected function updateAssetLocation($asset, $target) : Asset
{
switch (request('checkout_to_type')) {
case 'location':
diff --git a/app/Http/Controllers/CompaniesController.php b/app/Http/Controllers/CompaniesController.php
index 6c4072362f..589832af72 100644
--- a/app/Http/Controllers/CompaniesController.php
+++ b/app/Http/Controllers/CompaniesController.php
@@ -6,6 +6,9 @@ use App\Http\Requests\ImageUploadRequest;
use App\Models\Company;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Storage;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
/**
* This controller handles all actions related to Companies for
@@ -20,10 +23,8 @@ final class CompaniesController extends Controller
*
* @author [Abdullah Alansari] []
* @since [v1.8]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function index()
+ public function index() : View
{
$this->authorize('view', Company::class);
@@ -35,10 +36,8 @@ final class CompaniesController extends Controller
*
* @author [Abdullah Alansari] []
* @since [v1.8]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create()
+ public function create() : View
{
$this->authorize('create', Company::class);
@@ -51,10 +50,8 @@ final class CompaniesController extends Controller
* @author [Abdullah Alansari] []
* @since [v1.8]
* @param Request $request
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : RedirectResponse
{
$this->authorize('create', Company::class);
@@ -80,10 +77,8 @@ final class CompaniesController extends Controller
* @author [Abdullah Alansari] []
* @since [v1.8]
* @param int $companyId
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit($companyId)
+ public function edit($companyId) : View | RedirectResponse
{
if (is_null($item = Company::find($companyId))) {
return redirect()->route('companies.index')
@@ -102,10 +97,8 @@ final class CompaniesController extends Controller
* @since [v1.8]
* @param ImageUploadRequest $request
* @param int $companyId
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function update(ImageUploadRequest $request, $companyId)
+ public function update(ImageUploadRequest $request, $companyId) : RedirectResponse
{
if (is_null($company = Company::find($companyId))) {
return redirect()->route('companies.index')->with('error', trans('admin/companies/message.does_not_exist'));
@@ -134,10 +127,8 @@ final class CompaniesController extends Controller
* @author [Abdullah Alansari] []
* @since [v1.8]
* @param int $companyId
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($companyId)
+ public function destroy($companyId) : RedirectResponse
{
if (is_null($company = Company::find($companyId))) {
return redirect()->route('companies.index')
@@ -154,7 +145,7 @@ final class CompaniesController extends Controller
try {
Storage::disk('public')->delete('companies'.'/'.$company->image);
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
}
}
@@ -164,7 +155,7 @@ final class CompaniesController extends Controller
->with('success', trans('admin/companies/message.delete.success'));
}
- public function show($id)
+ public function show($id) : View | RedirectResponse
{
$this->authorize('view', Company::class);
diff --git a/app/Http/Controllers/Components/ComponentCheckinController.php b/app/Http/Controllers/Components/ComponentCheckinController.php
index 9f4724e353..b59237a5d0 100644
--- a/app/Http/Controllers/Components/ComponentCheckinController.php
+++ b/app/Http/Controllers/Components/ComponentCheckinController.php
@@ -95,7 +95,7 @@ class ComponentCheckinController extends Controller
$asset = Asset::find($component_assets->asset_id);
- event(new CheckoutableCheckedIn($component, $asset, Auth::user(), $request->input('note'), Carbon::now()));
+ 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'));
diff --git a/app/Http/Controllers/Components/ComponentCheckoutController.php b/app/Http/Controllers/Components/ComponentCheckoutController.php
index 79ff57e7df..fc319b47de 100644
--- a/app/Http/Controllers/Components/ComponentCheckoutController.php
+++ b/app/Http/Controllers/Components/ComponentCheckoutController.php
@@ -100,14 +100,14 @@ class ComponentCheckoutController extends Controller
$component->asset_id = $request->input('asset_id');
$component->assets()->attach($component->id, [
'component_id' => $component->id,
- 'user_id' => Auth::user(),
+ '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'),
'note' => $request->input('note'),
]);
- event(new CheckoutableCheckedOut($component, $asset, Auth::user(), $request->input('note')));
+ event(new CheckoutableCheckedOut($component, $asset, auth()->user(), $request->input('note')));
return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success'));
}
diff --git a/app/Http/Controllers/Components/ComponentsController.php b/app/Http/Controllers/Components/ComponentsController.php
index 34c9aed16b..33ebde6456 100644
--- a/app/Http/Controllers/Components/ComponentsController.php
+++ b/app/Http/Controllers/Components/ComponentsController.php
@@ -11,6 +11,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
+use Illuminate\Support\Facades\Log;
/**
* This class controls all actions related to Components for
@@ -188,7 +189,7 @@ class ComponentsController extends Controller
try {
Storage::disk('public')->delete('components/'.$component->image);
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
}
}
diff --git a/app/Http/Controllers/Components/ComponentsFilesController.php b/app/Http/Controllers/Components/ComponentsFilesController.php
index 55ae7f61b6..a7d42bb072 100644
--- a/app/Http/Controllers/Components/ComponentsFilesController.php
+++ b/app/Http/Controllers/Components/ComponentsFilesController.php
@@ -10,6 +10,7 @@ use App\Models\Component;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use Symfony\Component\HttpFoundation\JsonResponse;
+use Illuminate\Support\Facades\Log;
class ComponentsFilesController extends Controller
{
@@ -84,7 +85,7 @@ class ComponentsFilesController extends Controller
try {
Storage::delete('components/'.$log->filename);
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
}
}
@@ -110,7 +111,7 @@ class ComponentsFilesController extends Controller
*/
public function show($componentId = null, $fileId = null)
{
- \Log::debug('Private filesystem is: '.config('filesystems.default'));
+ Log::debug('Private filesystem is: '.config('filesystems.default'));
$component = Component::find($componentId);
// the component is valid
@@ -126,8 +127,8 @@ class ComponentsFilesController extends Controller
$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));
+ 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');
diff --git a/app/Http/Controllers/Consumables/ConsumableCheckoutController.php b/app/Http/Controllers/Consumables/ConsumableCheckoutController.php
index f7a297aeee..fd690fede8 100644
--- a/app/Http/Controllers/Consumables/ConsumableCheckoutController.php
+++ b/app/Http/Controllers/Consumables/ConsumableCheckoutController.php
@@ -4,12 +4,11 @@ namespace App\Http\Controllers\Consumables;
use App\Events\CheckoutableCheckedOut;
use App\Http\Controllers\Controller;
-use App\Models\Accessory;
use App\Models\Consumable;
use App\Models\User;
use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\Input;
+use \Illuminate\Contracts\View\View;
+use \Illuminate\Http\RedirectResponse;
class ConsumableCheckoutController extends Controller
{
@@ -20,13 +19,11 @@ class ConsumableCheckoutController extends Controller
* @see ConsumableCheckoutController::store() method that stores the data.
* @since [v1.0]
* @param int $id
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create($id)
+ public function create($id) : View | RedirectResponse
{
- if ($consumable = Consumable::with('users')->find($id)) {
+ if ($consumable = Consumable::find($id)) {
$this->authorize('checkout', $consumable);
@@ -71,12 +68,18 @@ 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('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) {
+ if ($consumable->numRemaining() <= 0 || $quantity > $consumable->numRemaining()) {
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable'));
}
- $admin_user = Auth::user();
+ $admin_user = auth()->user();
$assigned_to = e($request->input('assigned_to'));
// Check if the user exists
@@ -88,14 +91,15 @@ class ConsumableCheckoutController extends Controller
// Update the consumable data
$consumable->assigned_to = e($request->input('assigned_to'));
+ for($i = 0; $i < $quantity; $i++){
$consumable->users()->attach($consumable->id, [
'consumable_id' => $consumable->id,
'user_id' => $admin_user->id,
'assigned_to' => e($request->input('assigned_to')),
'note' => $request->input('note'),
]);
-
- event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note')));
+ }
+ event(new CheckoutableCheckedOut($consumable, $user, auth()->user(), $request->input('note')));
// Redirect to the new consumable page
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.checkout.success'));
diff --git a/app/Http/Controllers/Consumables/ConsumablesController.php b/app/Http/Controllers/Consumables/ConsumablesController.php
index b33e6e07a9..5685944a5c 100644
--- a/app/Http/Controllers/Consumables/ConsumablesController.php
+++ b/app/Http/Controllers/Consumables/ConsumablesController.php
@@ -8,8 +8,10 @@ use App\Http\Requests\ImageUploadRequest;
use App\Models\Company;
use App\Models\Consumable;
use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Validator;
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
+use App\Http\Requests\StoreConsumableRequest;
/**
* This controller handles all actions related to Consumables for
@@ -62,7 +64,7 @@ class ConsumablesController extends Controller
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store(ImageUploadRequest $request)
+ public function store(StoreConsumableRequest $request)
{
$this->authorize('create', Consumable::class);
$consumable = new Consumable();
@@ -99,10 +101,8 @@ class ConsumablesController extends Controller
* @param int $consumableId
* @see ConsumablesController::postEdit() method that stores the form data.
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit($consumableId = null)
+ public function edit($consumableId = null) : View | RedirectResponse
{
if ($item = Consumable::find($consumableId)) {
$this->authorize($item);
@@ -124,7 +124,7 @@ class ConsumablesController extends Controller
* @see ConsumablesController::getEdit() method that stores the form data.
* @since [v1.0]
*/
- public function update(ImageUploadRequest $request, $consumableId = null)
+ public function update(StoreConsumableRequest $request, $consumableId = null)
{
if (is_null($consumable = Consumable::find($consumableId))) {
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
@@ -182,6 +182,7 @@ class ConsumablesController extends Controller
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
}
$this->authorize($consumable);
+
$consumable->delete();
// Redirect to the locations management page
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.delete.success'));
diff --git a/app/Http/Controllers/Consumables/ConsumablesFilesController.php b/app/Http/Controllers/Consumables/ConsumablesFilesController.php
index 977261edcd..35a4ae841e 100644
--- a/app/Http/Controllers/Consumables/ConsumablesFilesController.php
+++ b/app/Http/Controllers/Consumables/ConsumablesFilesController.php
@@ -10,7 +10,7 @@ use App\Models\Consumable;
use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
use Symfony\Consumable\HttpFoundation\JsonResponse;
-
+use Illuminate\Support\Facades\Log;
class ConsumablesFilesController extends Controller
{
/**
@@ -83,7 +83,7 @@ class ConsumablesFilesController extends Controller
try {
Storage::delete('consumables/'.$log->filename);
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
}
}
@@ -124,8 +124,8 @@ class ConsumablesFilesController extends Controller
$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));
+ 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');
diff --git a/app/Http/Controllers/Controller.php b/app/Http/Controllers/Controller.php
index c0e9454d62..74fff19a37 100644
--- a/app/Http/Controllers/Controller.php
+++ b/app/Http/Controllers/Controller.php
@@ -22,7 +22,7 @@
namespace App\Http\Controllers;
-use Auth;
+use Illuminate\Support\Facades\Auth;
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
use Illuminate\Foundation\Bus\DispatchesJobs;
use Illuminate\Foundation\Validation\ValidatesRequests;
@@ -35,6 +35,6 @@ abstract class Controller extends BaseController
public function __construct()
{
view()->share('signedIn', Auth::check());
- view()->share('user', Auth::user());
+ view()->share('user', auth()->user());
}
}
diff --git a/app/Http/Controllers/CustomFieldsController.php b/app/Http/Controllers/CustomFieldsController.php
index 23ea9da34b..42f6c212db 100644
--- a/app/Http/Controllers/CustomFieldsController.php
+++ b/app/Http/Controllers/CustomFieldsController.php
@@ -8,7 +8,8 @@ use App\Models\CustomField;
use App\Models\CustomFieldset;
use Illuminate\Support\Facades\Auth;
use Illuminate\Http\Request;
-use Redirect;
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
/**
* This controller handles all actions related to Custom Asset Fields for
@@ -26,10 +27,8 @@ class CustomFieldsController extends Controller
*
* @author [Brady Wetherington] []
* @since [v1.8]
- * @return \Illuminate\Support\Facades\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function index()
+ public function index() : View
{
$this->authorize('view', CustomField::class);
@@ -46,10 +45,8 @@ class CustomFieldsController extends Controller
* @see CustomFieldsController::storeField()
* @author [A. Gianotto] []
* @since [v5.1.5]
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function show()
+ public function show() : RedirectResponse
{
return redirect()->route('fields.index');
}
@@ -61,10 +58,8 @@ class CustomFieldsController extends Controller
* @see CustomFieldsController::storeField()
* @author [Brady Wetherington] []
* @since [v1.8]
- * @return \Illuminate\Support\Facades\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create(Request $request)
+ public function create(Request $request) : View
{
$this->authorize('create', CustomField::class);
$fieldsets = CustomFieldset::get();
@@ -83,10 +78,8 @@ class CustomFieldsController extends Controller
* @see CustomFieldsController::createField()
* @author [Brady Wetherington] []
* @since [v1.8]
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store(CustomFieldRequest $request)
+ public function store(CustomFieldRequest $request) : RedirectResponse
{
$this->authorize('create', CustomField::class);
@@ -145,10 +138,8 @@ class CustomFieldsController extends Controller
*
* @author [A. Gianotto] []
* @since [v3.0]
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function deleteFieldFromFieldset($field_id, $fieldset_id)
+ public function deleteFieldFromFieldset($field_id, $fieldset_id) : RedirectResponse
{
$field = CustomField::find($field_id);
@@ -177,10 +168,8 @@ class CustomFieldsController extends Controller
*
* @author [Brady Wetherington] []
* @since [v1.8]
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($field_id)
+ public function destroy($field_id) : RedirectResponse
{
if ($field = CustomField::find($field_id)) {
$this->authorize('delete', $field);
@@ -203,10 +192,8 @@ class CustomFieldsController extends Controller
* @author [A. Gianotto] []
* @param int $id
* @since [v4.0]
- * @return \Illuminate\Support\Facades\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit(Request $request, $id)
+ public function edit(Request $request, $id) : View | RedirectResponse
{
if ($field = CustomField::find($id)) {
@@ -242,7 +229,7 @@ class CustomFieldsController extends Controller
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function update(CustomFieldRequest $request, $id)
+ public function update(CustomFieldRequest $request, $id) : RedirectResponse
{
$field = CustomField::find($id);
diff --git a/app/Http/Controllers/CustomFieldsetsController.php b/app/Http/Controllers/CustomFieldsetsController.php
index abf7c1d18e..8b9844d152 100644
--- a/app/Http/Controllers/CustomFieldsetsController.php
+++ b/app/Http/Controllers/CustomFieldsetsController.php
@@ -6,10 +6,9 @@ use App\Models\AssetModel;
use App\Models\CustomField;
use App\Models\CustomFieldset;
use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Auth;
-use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Validator;
-use Redirect;
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
/**
* This controller handles all actions related to Custom Asset Fields for
@@ -23,7 +22,7 @@ use Redirect;
class CustomFieldsetsController extends Controller
{
- public function index()
+ public function index() : RedirectResponse
{
return redirect()->route("fields.index")
->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist'));
@@ -34,11 +33,9 @@ class CustomFieldsetsController extends Controller
*
* @author [Brady Wetherington] []
* @param int $id
- * @return \Illuminate\Support\Facades\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
* @since [v1.8]
*/
- public function show($id)
+ public function show($id) : View | RedirectResponse
{
$cfset = CustomFieldset::with('fields')
->where('id', '=', $id)->orderBy('id', 'ASC')->first();
@@ -70,10 +67,8 @@ class CustomFieldsetsController extends Controller
*
* @author [Brady Wetherington] []
* @since [v1.8]
- * @return \Illuminate\Support\Facades\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create()
+ public function create() : View
{
$this->authorize('create', CustomField::class);
@@ -86,16 +81,16 @@ class CustomFieldsetsController extends Controller
* @author [Brady Wetherington] []
* @since [v1.8]
* @param Request $request
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store(Request $request)
+ public function store(Request $request) : RedirectResponse
{
$this->authorize('create', CustomField::class);
$fieldset = new CustomFieldset([
'name' => $request->get('name'),
- 'user_id' => Auth::user()->id,
+ 'user_id' => auth()->id(),
]);
$validator = Validator::make($request->all(), $fieldset->rules);
@@ -126,10 +121,8 @@ class CustomFieldsetsController extends Controller
* @author [A. Gianotto] []
* @param int $id
* @since [v6.0.14]
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit($id)
+ public function edit($id) : View | RedirectResponse
{
$this->authorize('create', CustomField::class);
@@ -147,10 +140,8 @@ class CustomFieldsetsController extends Controller
* @author [A. Gianotto] []
* @param int $id
* @since [v6.0.14]
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function update(Request $request, $id)
+ public function update(Request $request, $id) : RedirectResponse
{
$this->authorize('create', CustomField::class);
@@ -175,10 +166,8 @@ class CustomFieldsetsController extends Controller
* @author [Brady Wetherington] []
* @param int $id
* @since [v1.8]
- * @return View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($id)
+ public function destroy($id) : RedirectResponse
{
$fieldset = CustomFieldset::find($id);
@@ -203,9 +192,8 @@ class CustomFieldsetsController extends Controller
*
* @author [Brady Wetherington] []
* @since [v1.8]
- * @return View
*/
- public function associate(Request $request, $id)
+ public function associate(Request $request, $id) : RedirectResponse
{
$set = CustomFieldset::find($id);
@@ -223,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', 'No field selected.');
+ return redirect()->route('fieldsets.show', [$id])->with('error', trans('admin/custom_fields/message.field.none_selected'));
}
/**
@@ -232,7 +220,7 @@ class CustomFieldsetsController extends Controller
* @author [A. Gianotto] []
* @since [v5.0]
*/
- public function makeFieldRequired($fieldset_id, $field_id)
+ public function makeFieldRequired($fieldset_id, $field_id) : RedirectResponse
{
$this->authorize('update', CustomField::class);
$field = CustomField::findOrFail($field_id);
@@ -250,7 +238,7 @@ class CustomFieldsetsController extends Controller
* @author [A. Gianotto] []
* @since [v5.0]
*/
- public function makeFieldOptional($fieldset_id, $field_id)
+ public function makeFieldOptional($fieldset_id, $field_id) : RedirectResponse
{
$this->authorize('update', CustomField::class);
$field = CustomField::findOrFail($field_id);
diff --git a/app/Http/Controllers/DashboardController.php b/app/Http/Controllers/DashboardController.php
index 89283a7c21..fc01c496c2 100755
--- a/app/Http/Controllers/DashboardController.php
+++ b/app/Http/Controllers/DashboardController.php
@@ -2,8 +2,9 @@
namespace App\Http\Controllers;
-use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Artisan;
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
/**
@@ -21,12 +22,11 @@ class DashboardController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.0]
- * @return View
*/
- public function index()
+ public function index() : View | RedirectResponse
{
// Show the page
- if (Auth::user()->hasAccess('admin')) {
+ if (auth()->user()->hasAccess('admin')) {
$asset_stats = null;
$counts['asset'] = \App\Models\Asset::count();
@@ -34,7 +34,7 @@ class DashboardController extends Controller
$counts['license'] = \App\Models\License::assetcount();
$counts['consumable'] = \App\Models\Consumable::count();
$counts['component'] = \App\Models\Component::count();
- $counts['user'] = \App\Models\Company::scopeCompanyables(Auth::user())->count();
+ $counts['user'] = \App\Models\Company::scopeCompanyables(auth()->user())->count();
$counts['grand_total'] = $counts['asset'] + $counts['accessory'] + $counts['license'] + $counts['consumable'];
if ((! file_exists(storage_path().'/oauth-private.key')) || (! file_exists(storage_path().'/oauth-public.key'))) {
diff --git a/app/Http/Controllers/DepartmentsController.php b/app/Http/Controllers/DepartmentsController.php
index 2d456c0a4a..5818435deb 100644
--- a/app/Http/Controllers/DepartmentsController.php
+++ b/app/Http/Controllers/DepartmentsController.php
@@ -4,9 +4,12 @@ namespace App\Http\Controllers;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Department;
+use App\Models\Company;
use Illuminate\Http\Request;
-use Illuminate\Support\Facades\Auth;
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
use Illuminate\Support\Facades\Storage;
+use Illuminate\Support\Facades\Log;
class DepartmentsController extends Controller
{
@@ -24,10 +27,8 @@ class DepartmentsController extends Controller
* @see AssetController::getDatatable() method that generates the JSON response
* @since [v4.0]
* @param Request $request
- * @return \Illuminate\Support\Facades\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function index(Request $request)
+ public function index(Request $request) : View
{
$this->authorize('index', Department::class);
$company = null;
@@ -44,15 +45,13 @@ class DepartmentsController extends Controller
* @author [A. Gianotto] []
* @since [v4.0]
* @param ImageUploadRequest $request
- * @return \Illuminate\Http\Response
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : RedirectResponse
{
$this->authorize('create', Department::class);
$department = new Department;
$department->fill($request->all());
- $department->user_id = Auth::user()->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);
@@ -72,10 +71,8 @@ class DepartmentsController extends Controller
* @author [A. Gianotto] []
* @param int $id
* @since [v4.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function show($id)
+ public function show($id) : View | RedirectResponse
{
$department = Department::find($id);
@@ -94,10 +91,8 @@ class DepartmentsController extends Controller
* @author [A. Gianotto] []
* @see DepartmentsController::postCreate() method that validates and stores the data
* @since [v4.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create()
+ public function create() : View
{
$this->authorize('create', Department::class);
@@ -110,10 +105,8 @@ class DepartmentsController extends Controller
* @author [A. Gianotto] []
* @param int $locationId
* @since [v4.0]
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($id)
+ public function destroy($id) : RedirectResponse
{
if (is_null($department = Department::find($id))) {
return redirect()->to(route('departments.index'))->with('error', trans('admin/departments/message.not_found'));
@@ -129,7 +122,7 @@ class DepartmentsController extends Controller
try {
Storage::disk('public')->delete('departments'.'/'.$department->image);
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
}
}
$department->delete();
@@ -144,10 +137,8 @@ class DepartmentsController extends Controller
* @see LocationsController::postCreate() method that validates and stores
* @param int $departmentId
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit($departmentId = null)
+ public function edit($departmentId = null) : View | RedirectResponse
{
if (is_null($item = Department::find($departmentId))) {
return redirect()->back()->with('error', trans('admin/locations/message.does_not_exist'));
@@ -158,7 +149,15 @@ class DepartmentsController extends Controller
return view('departments/edit', compact('item'));
}
- public function update(ImageUploadRequest $request, $id)
+ /**
+ * Save updated Department information.
+ *
+ * @author [A. Gianotto] []
+ * @see LocationsController::postCreate() method that validates and stores
+ * @param int $departmentId
+ * @since [v1.0]
+ */
+ public function update(ImageUploadRequest $request, $id) : RedirectResponse
{
if (is_null($department = Department::find($id))) {
return redirect()->route('departments.index')->with('error', trans('admin/departments/message.does_not_exist'));
diff --git a/app/Http/Controllers/DepreciationsController.php b/app/Http/Controllers/DepreciationsController.php
index 70bfb78cb5..57ad35fea5 100755
--- a/app/Http/Controllers/DepreciationsController.php
+++ b/app/Http/Controllers/DepreciationsController.php
@@ -5,7 +5,8 @@ namespace App\Http\Controllers;
use App\Models\Depreciation;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
-
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
/**
* This controller handles all actions related to Depreciations for
* the Snipe-IT Asset Management application.
@@ -21,14 +22,10 @@ class DepreciationsController extends Controller
* @author [A. Gianotto] [authorize('view', Depreciation::class);
-
- // Show the page
return view('depreciations/index');
}
@@ -38,10 +35,8 @@ class DepreciationsController extends Controller
* @author [A. Gianotto] [authorize('create', Depreciation::class);
@@ -56,10 +51,8 @@ class DepreciationsController extends Controller
* @see DepreciationsController::postCreate()
* @since [v1.0]
* @param Request $request
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store(Request $request)
+ public function store(Request $request) : RedirectResponse
{
$this->authorize('create', Depreciation::class);
@@ -87,10 +80,8 @@ class DepreciationsController extends Controller
* @see DepreciationsController::postEdit()
* @param int $depreciationId
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit($depreciationId = null)
+ public function edit($depreciationId = null) : RedirectResponse | View
{
// Check if the depreciation exists
if (is_null($item = Depreciation::find($depreciationId))) {
@@ -110,11 +101,9 @@ class DepreciationsController extends Controller
* @see DepreciationsController::getEdit()
* @param Request $request
* @param int $depreciationId
- * @return \Illuminate\Http\RedirectResponse
* @since [v1.0]
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function update(Request $request, $depreciationId = null)
+ public function update(Request $request, $depreciationId = null) : RedirectResponse
{
// Check if the depreciation exists
if (is_null($depreciation = Depreciation::find($depreciationId))) {
@@ -146,10 +135,8 @@ class DepreciationsController extends Controller
* @author [A. Gianotto] [find($depreciationId))) {
@@ -175,10 +162,8 @@ class DepreciationsController extends Controller
* @see DepreciationsController::postEdit()
* @param int $depreciationId
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function show($id)
+ public function show($id) : View | RedirectResponse
{
if (is_null($depreciation = Depreciation::find($id))) {
// Redirect to the blogs management page
diff --git a/app/Http/Controllers/GoogleAuthController.php b/app/Http/Controllers/GoogleAuthController.php
index a93fcd1fc2..d873491c5b 100644
--- a/app/Http/Controllers/GoogleAuthController.php
+++ b/app/Http/Controllers/GoogleAuthController.php
@@ -2,13 +2,13 @@
namespace App\Http\Controllers;
-use Illuminate\Http\Request;
+use Illuminate\Http\RedirectResponse;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
use Laravel\Socialite\Facades\Socialite;
use Laravel\Socialite\Two\InvalidStateException;
use App\Models\Setting;
-
+use Illuminate\Support\Facades\Log;
class GoogleAuthController extends Controller
{
@@ -30,13 +30,13 @@ class GoogleAuthController extends Controller
return Socialite::driver('google')->redirect();
}
- public function handleGoogleCallback()
+ public function handleGoogleCallback() : RedirectResponse
{
try {
$socialUser = Socialite::driver('google')->user();
- \Log::debug('Google user found in Google Workspace');
+ Log::debug('Google user found in Google Workspace');
} catch (InvalidStateException $exception) {
- \Log::debug('Google user NOT found in Google Workspace');
+ Log::debug('Google user NOT found in Google Workspace');
return redirect()->route('login')
->withErrors(
[
@@ -52,7 +52,7 @@ class GoogleAuthController extends Controller
if ($user) {
- \Log::debug('Google user '.$socialUser->getEmail().' found in Snipe-IT');
+ Log::debug('Google user '.$socialUser->getEmail().' found in Snipe-IT');
$user->update([
'avatar' => $socialUser->avatar,
]);
@@ -61,7 +61,7 @@ class GoogleAuthController extends Controller
return redirect()->route('home');
}
- \Log::debug('Google user '.$socialUser->getEmail().' NOT found in Snipe-IT');
+ Log::debug('Google user '.$socialUser->getEmail().' NOT found in Snipe-IT');
return redirect()->route('login')
->withErrors(
[
diff --git a/app/Http/Controllers/GroupsController.php b/app/Http/Controllers/GroupsController.php
index 544ebb34ed..a85cabf246 100755
--- a/app/Http/Controllers/GroupsController.php
+++ b/app/Http/Controllers/GroupsController.php
@@ -5,7 +5,8 @@ namespace App\Http\Controllers;
use App\Helpers\Helper;
use App\Models\Group;
use Illuminate\Http\Request;
-use Auth;
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
/**
* This controller handles all actions related to User Groups for
@@ -22,11 +23,9 @@ class GroupsController extends Controller
* @author [A. Gianotto] [name = $request->input('name');
$group->permissions = json_encode($request->input('permission'));
- $group->created_by = Auth::user()->id;
+ $group->created_by = auth()->id();
if ($group->save()) {
return redirect()->route('groups.index')->with('success', trans('admin/groups/message.success.create'));
@@ -80,9 +77,8 @@ class GroupsController extends Controller
* @see GroupsController::postEdit()
* @param int $id
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
*/
- public function edit($id)
+ public function edit($id) : View | RedirectResponse
{
$group = Group::find($id);
@@ -104,9 +100,8 @@ class GroupsController extends Controller
* @see GroupsController::getEdit()
* @param int $id
* @since [v1.0]
- * @return \Illuminate\Http\RedirectResponse
*/
- public function update(Request $request, $id = null)
+ public function update(Request $request, $id = null) : RedirectResponse
{
if (! $group = Group::find($id)) {
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', ['id' => $id]));
@@ -132,10 +127,8 @@ class GroupsController extends Controller
* @see GroupsController::getEdit()
* @param int $id
* @since [v1.0]
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Exception
*/
- public function destroy($id)
+ public function destroy($id) : RedirectResponse
{
if (! config('app.lock_passwords')) {
if (! $group = Group::find($id)) {
@@ -154,10 +147,9 @@ class GroupsController extends Controller
*
* @author [A. Gianotto] []
* @param $id
- * @return \Illuminate\Contracts\View\View
* @since [v4.0.11]
*/
- public function show($id)
+ public function show($id) : View | RedirectResponse
{
$group = Group::find($id);
diff --git a/app/Http/Controllers/HealthController.php b/app/Http/Controllers/HealthController.php
index 456f6b6f94..c75b903b0b 100644
--- a/app/Http/Controllers/HealthController.php
+++ b/app/Http/Controllers/HealthController.php
@@ -5,10 +5,13 @@ namespace App\Http\Controllers;
use Illuminate\Routing\Controller as BaseController;
/**
- * This controller provide the healthz route for
+ * This controller provide the health route for
* the Snipe-IT Asset Management application.
*
- * @version v1.0
+ * @version v1.0
+ *
+ * @return \Illuminate\Http\JsonResponse
+
*/
class HealthController extends BaseController
{
diff --git a/app/Http/Controllers/Kits/CheckoutKitController.php b/app/Http/Controllers/Kits/CheckoutKitController.php
index 7a0f93391d..c75e4ea8f0 100644
--- a/app/Http/Controllers/Kits/CheckoutKitController.php
+++ b/app/Http/Controllers/Kits/CheckoutKitController.php
@@ -33,7 +33,7 @@ class CheckoutKitController extends Controller
* Show Bulk Checkout Page
*
* @author [D. Minaev.] []
- * @return View View to checkout
+ * @return \Illuminate\Contracts\View\View View to checkout
*/
public function showCheckout($kit_id)
{
@@ -48,7 +48,7 @@ class CheckoutKitController extends Controller
* Validate and process the new Predefined Kit data.
*
* @author [D. Minaev.] []
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
public function store(Request $request, $kit_id)
{
diff --git a/app/Http/Controllers/Kits/PredefinedKitsController.php b/app/Http/Controllers/Kits/PredefinedKitsController.php
index c6e5cf72a3..187f5aad14 100644
--- a/app/Http/Controllers/Kits/PredefinedKitsController.php
+++ b/app/Http/Controllers/Kits/PredefinedKitsController.php
@@ -47,7 +47,7 @@ class PredefinedKitsController extends Controller
* Validate and process the new Predefined Kit data.
*
* @author [D. Minaev] []
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
public function store(ImageUploadRequest $request)
{
@@ -73,7 +73,7 @@ class PredefinedKitsController extends Controller
* @author [D. Minaev] []
* @since [v1.0]
* @param int $kit_id
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function edit($kit_id = null)
{
@@ -95,7 +95,7 @@ class PredefinedKitsController extends Controller
* @author [D. Minaev] []
* @since [v1.0]
* @param int $kit_id
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
public function update(ImageUploadRequest $request, $kit_id = null)
{
@@ -122,7 +122,7 @@ class PredefinedKitsController extends Controller
* @author [D. Minaev] []
* @since [v1.0]
* @param int $kit_id
- * @return Redirect
+ * @return \Illuminate\Http\RedirectResponse
*/
public function destroy($kit_id)
{
@@ -150,7 +150,7 @@ class PredefinedKitsController extends Controller
* @author [D. Minaev] []
* @since [v1.0]
* @param int $modelId
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function show($kit_id = null)
{
@@ -162,7 +162,7 @@ class PredefinedKitsController extends Controller
*
* @author [D. Minaev] []
* @param int $kit_id
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function editModel($kit_id, $model_id)
{
@@ -184,7 +184,7 @@ class PredefinedKitsController extends Controller
*
* @author [D. Minaev] []
* @param int $modelId
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function updateModel(Request $request, $kit_id, $model_id)
{
@@ -214,7 +214,7 @@ class PredefinedKitsController extends Controller
*
* @author [D. Minaev] []
* @param int $modelId
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function detachModel($kit_id, $model_id)
{
@@ -237,7 +237,7 @@ class PredefinedKitsController extends Controller
* @author [D. Minaev] []
* @param int $kit_id
* @param int $license_id
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function editLicense($kit_id, $license_id)
{
@@ -262,7 +262,7 @@ class PredefinedKitsController extends Controller
* @author [D. Minaev] []
* @param int $kit_id
* @param int $license_id
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function updateLicense(Request $request, $kit_id, $license_id)
{
@@ -293,7 +293,7 @@ class PredefinedKitsController extends Controller
* @author [D. Minaev] []
* @param int $kit_id
* @param int $license_id
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function detachLicense($kit_id, $license_id)
{
@@ -316,7 +316,7 @@ class PredefinedKitsController extends Controller
* @author [D. Minaev] []
* @param int $kit_id
* @param int $accessoryId
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function editAccessory($kit_id, $accessory_id)
{
@@ -341,7 +341,7 @@ class PredefinedKitsController extends Controller
* @author [D. Minaev] []
* @param int $kit_id
* @param int $accessory_id
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function updateAccessory(Request $request, $kit_id, $accessory_id)
{
@@ -371,7 +371,7 @@ class PredefinedKitsController extends Controller
*
* @author [D. Minaev] []
* @param int $accessory_id
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function detachAccessory($kit_id, $accessory_id)
{
@@ -394,7 +394,7 @@ class PredefinedKitsController extends Controller
* @author [D. Minaev] []
* @param int $kit_id
* @param int $consumable_id
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function editConsumable($kit_id, $consumable_id)
{
@@ -419,7 +419,7 @@ class PredefinedKitsController extends Controller
* @author [D. Minaev] []
* @param int $kit_id
* @param int $consumableId
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function updateConsumable(Request $request, $kit_id, $consumable_id)
{
@@ -449,7 +449,7 @@ class PredefinedKitsController extends Controller
*
* @author [D. Minaev] []
* @param int $consumable_id
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
public function detachConsumable($kit_id, $consumable_id)
{
diff --git a/app/Http/Controllers/LabelsController.php b/app/Http/Controllers/LabelsController.php
index 799d910384..8e6ba5e2cd 100755
--- a/app/Http/Controllers/LabelsController.php
+++ b/app/Http/Controllers/LabelsController.php
@@ -14,16 +14,14 @@ use App\Models\Setting;
use App\Models\Supplier;
use App\Models\User;
use App\View\Label as LabelView;
-use Illuminate\Support\Facades\Storage;
class LabelsController extends Controller
{
/**
* Returns the Label view with test data
*
+ * @param string $labelName
* @author Grant Le Roux
- * @param string $labelName
- * @return \Illuminate\Contracts\View\View
*/
public function show(string $labelName)
{
@@ -66,7 +64,7 @@ class LabelsController extends Controller
$exampleAsset->model->category->id = 999999;
$exampleAsset->model->category->name = trans('admin/labels/table.example_category');
- $customFieldColumns = CustomField::all()->pluck('db_column');
+ $customFieldColumns = CustomField::where('field_encrypted', '=', 0)->pluck('db_column');
collect(explode(';', Setting::getSettings()->label2_fields))
->filter()
@@ -95,6 +93,5 @@ class LabelsController extends Controller
->with('bulkedit', false)
->with('count', 0);
- return redirect()->route('home')->with('error', trans('admin/labels/message.does_not_exist'));
}
}
diff --git a/app/Http/Controllers/Licenses/LicenseCheckinController.php b/app/Http/Controllers/Licenses/LicenseCheckinController.php
index 367ff3f1d9..e863aa860e 100644
--- a/app/Http/Controllers/Licenses/LicenseCheckinController.php
+++ b/app/Http/Controllers/Licenses/LicenseCheckinController.php
@@ -13,6 +13,7 @@ use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Session;
use Illuminate\Support\Facades\Validator;
+use Illuminate\Support\Facades\Log;
class LicenseCheckinController extends Controller
{
@@ -101,7 +102,7 @@ class LicenseCheckinController extends Controller
// Was the asset updated?
if ($licenseSeat->save()) {
- event(new CheckoutableCheckedIn($licenseSeat, $return_to, Auth::user(), $request->input('notes')));
+ 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'));
@@ -145,7 +146,7 @@ class LicenseCheckinController extends Controller
$user_seat->assigned_to = null;
if ($user_seat->save()) {
- \Log::debug('Checking in '.$license->name.' from user '.$user_seat->username);
+ Log::debug('Checking in '.$license->name.' from user '.$user_seat->username);
$user_seat->logCheckin($user_seat->user, trans('admin/licenses/general.bulk.checkin_all.log_msg'));
}
}
@@ -160,7 +161,7 @@ class LicenseCheckinController extends Controller
$asset_seat->asset_id = null;
if ($asset_seat->save()) {
- \Log::debug('Checking in '.$license->name.' from asset '.$asset_seat->asset_tag);
+ Log::debug('Checking in '.$license->name.' from asset '.$asset_seat->asset_tag);
$asset_seat->logCheckin($asset_seat->asset, trans('admin/licenses/general.bulk.checkin_all.log_msg'));
$count++;
}
diff --git a/app/Http/Controllers/Licenses/LicenseCheckoutController.php b/app/Http/Controllers/Licenses/LicenseCheckoutController.php
index d61a1ad819..2fb0434f62 100644
--- a/app/Http/Controllers/Licenses/LicenseCheckoutController.php
+++ b/app/Http/Controllers/Licenses/LicenseCheckoutController.php
@@ -11,6 +11,7 @@ use App\Models\License;
use App\Models\LicenseSeat;
use App\Models\User;
use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Log;
class LicenseCheckoutController extends Controller
{
@@ -93,14 +94,14 @@ class LicenseCheckoutController extends Controller
if (! $licenseSeat) {
if ($seatId) {
- 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.unavailable')));
}
- throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', 'There are no available seats for this license.'));
+ throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.not_enough_seats')));
}
if (! $licenseSeat->license->is($license)) {
- throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', 'The license seat provided does not match the license.'));
+ throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkout.mismatch')));
}
return $licenseSeat;
@@ -118,7 +119,7 @@ class LicenseCheckoutController extends Controller
$licenseSeat->assigned_to = $target->assigned_to;
}
if ($licenseSeat->save()) {
- event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('notes')));
+ event(new CheckoutableCheckedOut($licenseSeat, $target, auth()->user(), request('notes')));
return true;
}
@@ -135,7 +136,7 @@ class LicenseCheckoutController extends Controller
$licenseSeat->assigned_to = request('assigned_to');
if ($licenseSeat->save()) {
- event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('notes')));
+ event(new CheckoutableCheckedOut($licenseSeat, $target, auth()->user(), request('notes')));
return true;
}
@@ -155,16 +156,16 @@ class LicenseCheckoutController extends Controller
public function bulkCheckout($licenseId) {
- \Log::debug('Checking out '.$licenseId.' via bulk');
+ Log::debug('Checking out '.$licenseId.' via bulk');
$license = License::findOrFail($licenseId);
$this->authorize('checkin', $license);
$avail_count = $license->getAvailSeatsCountAttribute();
$users = User::whereNull('deleted_at')->where('autoassign_licenses', '=', 1)->with('licenses')->get();
- \Log::debug($avail_count.' will be assigned');
+ Log::debug($avail_count.' will be assigned');
if ($users->count() > $avail_count) {
- \Log::debug('You do not have enough free seats to complete this task, so we will check out as many as we can. ');
+ Log::debug('You do not have enough free seats to complete this task, so we will check out as many as we can. ');
}
// If the license is valid, check that there is an available seat
@@ -179,7 +180,7 @@ class LicenseCheckoutController extends Controller
// Check to make sure this user doesn't already have this license checked out to them
if ($user->licenses->where('id', '=', $licenseId)->count()) {
- \Log::debug($user->username.' already has this license checked out to them. Skipping... ');
+ Log::debug($user->username.' already has this license checked out to them. Skipping... ');
continue;
}
@@ -192,7 +193,7 @@ class LicenseCheckoutController extends Controller
$avail_count--;
$assigned_count++;
$licenseSeat->logCheckout(trans('admin/licenses/general.bulk.checkout_all.log_msg'), $user);
- \Log::debug('License '.$license->name.' seat '.$licenseSeat->id.' checked out to '.$user->username);
+ Log::debug('License '.$license->name.' seat '.$licenseSeat->id.' checked out to '.$user->username);
}
if ($avail_count == 0) {
diff --git a/app/Http/Controllers/Licenses/LicenseFilesController.php b/app/Http/Controllers/Licenses/LicenseFilesController.php
index 037d78d230..fa18e8cf48 100644
--- a/app/Http/Controllers/Licenses/LicenseFilesController.php
+++ b/app/Http/Controllers/Licenses/LicenseFilesController.php
@@ -7,9 +7,8 @@ use App\Http\Controllers\Controller;
use App\Http\Requests\UploadFileRequest;
use App\Models\Actionlog;
use App\Models\License;
-use Illuminate\Support\Facades\Response;
use Illuminate\Support\Facades\Storage;
-use Symfony\Component\HttpFoundation\JsonResponse;
+use Illuminate\Support\Facades\Log;
class LicenseFilesController extends Controller
{
@@ -20,7 +19,7 @@ class LicenseFilesController extends Controller
* @param int $licenseId
* @return \Illuminate\Http\RedirectResponse
* @throws \Illuminate\Auth\Access\AuthorizationException
- *@author [A. Gianotto] []
+ * @author [A. Gianotto] []
* @since [v1.0]
* @todo Switch to using the AssetFileRequest form request validator.
*/
@@ -78,7 +77,7 @@ class LicenseFilesController extends Controller
try {
Storage::delete('licenses/'.$log->filename);
} catch (\Exception $e) {
- \Log::debug($e);
+ Log::debug($e);
}
}
@@ -121,8 +120,8 @@ class LicenseFilesController extends Controller
$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));
+ 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');
diff --git a/app/Http/Controllers/Licenses/LicensesController.php b/app/Http/Controllers/Licenses/LicensesController.php
index c55181c518..01de4b4d46 100755
--- a/app/Http/Controllers/Licenses/LicensesController.php
+++ b/app/Http/Controllers/Licenses/LicensesController.php
@@ -11,6 +11,7 @@ use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\DB;
+use Symfony\Component\HttpFoundation\StreamedResponse;
/**
* This controller handles all actions related to Licenses for
@@ -289,4 +290,106 @@ class LicensesController extends Controller
->with('item', $license)
->with('maintained_list', $maintained_list);
}
+
+ /**
+ * Exports Licenses to CSV
+ *
+ * @author [G. Martinez]
+ * @since [v6.3]
+ * @return StreamedResponse
+ * @throws \Illuminate\Auth\Access\AuthorizationException
+ */
+ public function getExportLicensesCsv()
+ {
+ $this->authorize('view', License::class);
+ \Debugbar::disable();
+
+ $response = new StreamedResponse(function () {
+ // Open output stream
+ $handle = fopen('php://output', 'w');
+ $licenses= License::with('company',
+ 'manufacturer',
+ 'category',
+ 'supplier',
+ 'adminuser',
+ 'assignedusers')
+ ->orderBy('created_at', 'DESC');
+ Company::scopeCompanyables($licenses)
+ ->chunk(500, function ($licenses) use ($handle) {
+ $headers = [
+ // strtolower to prevent Excel from trying to open it as a SYLK file
+ strtolower(trans('general.id')),
+ trans('general.company'),
+ trans('general.name'),
+ trans('general.serial_number'),
+ trans('general.purchase_date'),
+ trans('general.purchase_cost'),
+ trans('general.order_number'),
+ trans('general.licenses_available'),
+ trans('admin/licenses/table.seats'),
+ trans('general.created_by'),
+ trans('general.depreciation'),
+ trans('general.updated_at'),
+ trans('admin/licenses/table.deleted_at'),
+ trans('general.email'),
+ trans('admin/hardware/form.fully_depreciated'),
+ trans('general.supplier'),
+ trans('admin/licenses/form.expiration'),
+ trans('admin/licenses/form.purchase_order'),
+ trans('admin/licenses/form.termination_date'),
+ trans('admin/licenses/form.maintained'),
+ trans('general.manufacturer'),
+ trans('general.category'),
+ trans('general.min_amt'),
+ trans('admin/licenses/form.reassignable'),
+ trans('general.notes'),
+ trans('general.created_at'),
+ ];
+
+ fputcsv($handle, $headers);
+
+ foreach ($licenses as $license) {
+ // Add a new row with data
+ $values = [
+ $license->id,
+ $license->company ? $license->company->name: '',
+ $license->name,
+ $license->serial,
+ $license->purchase_date,
+ $license->purchase_cost,
+ $license->order_number,
+ $license->free_seat_count,
+ $license->seats,
+ ($license->adminuser ? $license->adminuser->present()->fullName() : trans('admin/reports/general.deleted_user')),
+ $license->depreciation ? $license->depreciation->name: '',
+ $license->updated_at,
+ $license->deleted_at,
+ $license->email,
+ ( $license->depreciate == '1') ? trans('general.yes') : trans('general.no'),
+ ($license->supplier) ? $license->supplier->name: '',
+ $license->expiration_date,
+ $license->purchase_order,
+ $license->termination_date,
+ ( $license->maintained == '1') ? trans('general.yes') : trans('general.no'),
+ $license->manufacturer ? $license->manufacturer->name: '',
+ $license->category ? $license->category->name: '',
+ $license->min_amt,
+ ( $license->reassignable == '1') ? trans('general.yes') : trans('general.no'),
+ $license->notes,
+ $license->created_at,
+ ];
+
+ fputcsv($handle, $values);
+ }
+ });
+
+ // Close the output stream
+ fclose($handle);
+ }, 200, [
+ 'Content-Type' => 'text/csv; charset=UTF-8',
+ 'Content-Disposition' => 'attachment; filename="licenses-'.date('Y-m-d-his').'.csv"',
+ ]);
+
+ return $response;
+ }
}
diff --git a/app/Http/Controllers/LocationsController.php b/app/Http/Controllers/LocationsController.php
index 897d127580..c498f09926 100755
--- a/app/Http/Controllers/LocationsController.php
+++ b/app/Http/Controllers/LocationsController.php
@@ -6,10 +6,11 @@ use App\Http\Requests\ImageUploadRequest;
use App\Models\Asset;
use App\Models\Location;
use App\Models\User;
-use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
use Illuminate\Http\Request;
-
+use Illuminate\Support\Facades\Log;
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
/**
* This controller handles all actions related to Locations for
* the Snipe-IT Asset Management application.
@@ -25,10 +26,8 @@ class LocationsController extends Controller
* @author [A. Gianotto] []
* @see LocationsController::getDatatable() method that generates the JSON response
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function index()
+ public function index() : View
{
// Grab all the locations
$this->authorize('view', Location::class);
@@ -42,10 +41,8 @@ class LocationsController extends Controller
* @author [A. Gianotto] []
* @see LocationsController::postCreate() method that validates and stores the data
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create()
+ public function create() : View
{
$this->authorize('create', Location::class);
@@ -61,10 +58,8 @@ class LocationsController extends Controller
* @see LocationsController::getCreate() method that makes the form
* @since [v1.0]
* @param ImageUploadRequest $request
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : RedirectResponse
{
$this->authorize('create', Location::class);
$location = new Location();
@@ -79,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->user_id = Auth::id();
+ $location->user_id = auth()->id();
$location->phone = request('phone');
$location->fax = request('fax');
@@ -99,10 +94,8 @@ class LocationsController extends Controller
* @see LocationsController::postCreate() method that validates and stores
* @param int $locationId
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit($locationId = null)
+ public function edit($locationId = null) : View | RedirectResponse
{
$this->authorize('update', Location::class);
// Check if the location exists
@@ -120,11 +113,9 @@ class LocationsController extends Controller
* @see LocationsController::getEdit() method that makes the form view
* @param ImageUploadRequest $request
* @param int $locationId
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
* @since [v1.0]
*/
- public function update(ImageUploadRequest $request, $locationId = null)
+ public function update(ImageUploadRequest $request, $locationId = null) : RedirectResponse
{
$this->authorize('update', Location::class);
// Check if the location exists
@@ -162,10 +153,8 @@ class LocationsController extends Controller
* @author [A. Gianotto] []
* @param int $locationId
* @since [v1.0]
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($locationId)
+ public function destroy($locationId) : RedirectResponse
{
$this->authorize('delete', Location::class);
if (is_null($location = Location::find($locationId))) {
@@ -186,7 +175,7 @@ class LocationsController extends Controller
try {
Storage::disk('public')->delete('locations/'.$location->image);
} catch (\Exception $e) {
- \Log::error($e);
+ Log::error($e);
}
}
$location->delete();
@@ -201,9 +190,8 @@ class LocationsController extends Controller
* @author [A. Gianotto] []
* @param int $id
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
*/
- public function show($id = null)
+ public function show($id = null) : View | RedirectResponse
{
$location = Location::find($id);
@@ -214,7 +202,7 @@ class LocationsController extends Controller
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
}
- public function print_assigned($id)
+ public function print_assigned($id) : View | RedirectResponse
{
if ($location = Location::where('id', $id)->first()) {
@@ -239,9 +227,8 @@ class LocationsController extends Controller
* @author [A. Gianotto] []
* @param int $locationId
* @since [v6.0.14]
- * @return \Illuminate\Contracts\View\View
*/
- public function getClone($locationId = null)
+ public function getClone($locationId = null) : View | RedirectResponse
{
$this->authorize('create', Location::class);
@@ -262,7 +249,7 @@ class LocationsController extends Controller
}
- public function print_all_assigned($id)
+ public function print_all_assigned($id) : View | RedirectResponse
{
if ($location = Location::where('id', $id)->first()) {
$parent = Location::where('id', $location->parent_id)->first();
@@ -281,9 +268,8 @@ class LocationsController extends Controller
*
* @author [A. Gianotto] []
* @since [v6.3.1]
- * @return \Illuminate\Contracts\View\View
*/
- public function postBulkDelete(Request $request)
+ public function postBulkDelete(Request $request) : View | RedirectResponse
{
$locations_raw_array = $request->input('ids');
@@ -314,9 +300,10 @@ class LocationsController extends Controller
*
* @author [A. Gianotto] []
* @since [v6.3.1]
- * @return \Illuminate\Http\RedirectResponse
+
*/
- public function postBulkDeleteStore(Request $request) {
+ public function postBulkDeleteStore(Request $request) : RedirectResponse
+ {
$locations_raw_array = $request->input('ids');
if ((is_array($locations_raw_array)) && (count($locations_raw_array) > 0)) {
@@ -341,8 +328,8 @@ class LocationsController extends Controller
}
}
- \Log::debug('Success count: '.$success_count);
- \Log::debug('Error count: '.$error_count);
+ Log::debug('Success count: '.$success_count);
+ Log::debug('Error count: '.$error_count);
// Complete success
if ($success_count == count($locations_raw_array)) {
return redirect()
diff --git a/app/Http/Controllers/ManufacturersController.php b/app/Http/Controllers/ManufacturersController.php
index c927a5affb..8e979e3896 100755
--- a/app/Http/Controllers/ManufacturersController.php
+++ b/app/Http/Controllers/ManufacturersController.php
@@ -2,16 +2,15 @@
namespace App\Http\Controllers;
-use App\Helpers\Helper;
use App\Http\Requests\ImageUploadRequest;
use App\Models\Actionlog;
-use App\Models\Asset;
use App\Models\Manufacturer;
-use App\Models\User;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\Auth;
use Illuminate\Support\Facades\Storage;
-use Redirect;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Http\RedirectResponse;
+use \Illuminate\Contracts\View\View;
/**
* This controller handles all actions related to Manufacturers for
@@ -28,13 +27,10 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] []
* @see Api\ManufacturersController::index() method that generates the JSON response
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function index()
+ public function index() : View
{
$this->authorize('index', Manufacturer::class);
-
return view('manufacturers/index');
}
@@ -44,10 +40,8 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] []
* @see ManufacturersController::store()
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function create()
+ public function create() : View
{
$this->authorize('create', Manufacturer::class);
@@ -61,10 +55,8 @@ class ManufacturersController extends Controller
* @see ManufacturersController::create()
* @since [v1.0]
* @param ImageUploadRequest $request
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function store(ImageUploadRequest $request)
+ public function store(ImageUploadRequest $request) : RedirectResponse
{
$this->authorize('create', Manufacturer::class);
$manufacturer = new Manufacturer;
@@ -91,10 +83,8 @@ class ManufacturersController extends Controller
* @see ManufacturersController::update()
* @param int $manufacturerId
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function edit($manufacturerId = null)
+ public function edit($manufacturerId = null) : View | RedirectResponse
{
// Handles manufacturer checks and permissions.
$this->authorize('update', Manufacturer::class);
@@ -115,11 +105,9 @@ class ManufacturersController extends Controller
* @see ManufacturersController::getEdit()
* @param Request $request
* @param int $manufacturerId
- * @return \Illuminate\Http\RedirectResponse
* @since [v1.0]
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function update(ImageUploadRequest $request, $manufacturerId = null)
+ public function update(ImageUploadRequest $request, $manufacturerId = null) : RedirectResponse
{
$this->authorize('update', Manufacturer::class);
// Check if the manufacturer exists
@@ -156,10 +144,8 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] []
* @param int $manufacturerId
* @since [v1.0]
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function destroy($manufacturerId)
+ public function destroy($manufacturerId) : RedirectResponse
{
$this->authorize('delete', Manufacturer::class);
if (is_null($manufacturer = Manufacturer::withTrashed()->withCount('models as models_count')->find($manufacturerId))) {
@@ -174,7 +160,7 @@ class ManufacturersController extends Controller
try {
Storage::disk('public')->delete('manufacturers/'.$manufacturer->image);
} catch (\Exception $e) {
- \Log::info($e);
+ Log::info($e);
}
}
@@ -196,10 +182,8 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] []
* @param int $manufacturerId
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function show($manufacturerId = null)
+ public function show($manufacturerId = null) : View | RedirectResponse
{
$this->authorize('view', Manufacturer::class);
$manufacturer = Manufacturer::find($manufacturerId);
@@ -219,10 +203,8 @@ class ManufacturersController extends Controller
* @author [A. Gianotto] []
* @since [v4.1.15]
* @param int $manufacturers_id
- * @return Redirect
- * @throws \Illuminate\Auth\Access\AuthorizationException
*/
- public function restore($id)
+ public function restore($id) : RedirectResponse
{
$this->authorize('delete', Manufacturer::class);
@@ -237,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->user_id = Auth::user()->id;
+ $logaction->user_id = auth()->id();
$logaction->logaction('restore');
// Redirect them to the deleted page if there are more, otherwise the section index
diff --git a/app/Http/Controllers/ModalController.php b/app/Http/Controllers/ModalController.php
index 6f6b39dd12..fab491a5f4 100644
--- a/app/Http/Controllers/ModalController.php
+++ b/app/Http/Controllers/ModalController.php
@@ -15,7 +15,7 @@ class ModalController extends Controller
* @version v5.3.7-pre
* @author [Brady Wetherington] []
* @author [A. Gianotto] []
* @since [v1.0]
- * @return \Illuminate\Contracts\View\View
*/
- public function getIndex()
+ public function getIndex() : View
{
- $user = Auth::user();
-
+ $this->authorize('self.profile');
+ $user = auth()->user();
return view('account/profile', compact('user'));
}
@@ -43,11 +38,11 @@ class ProfileController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.0]
- * @return \Illuminate\Http\RedirectResponse
*/
- public function postIndex(ImageUploadRequest $request)
+ public function postIndex(ImageUploadRequest $request) : RedirectResponse
{
- $user = Auth::user();
+ $this->authorize('self.profile');
+ $user = auth()->user();
$user->first_name = $request->input('first_name');
$user->last_name = $request->input('last_name');
$user->website = $request->input('website');
@@ -72,7 +67,7 @@ class ProfileController extends Controller
if ($user->save()) {
- return redirect()->route('profile')->with('success', 'Account successfully updated');
+ return redirect()->route('profile')->with('success', trans('account/general.profile_updated'));
}
return redirect()->back()->withInput()->withErrors($user->getErrors());
@@ -87,11 +82,9 @@ class ProfileController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return View
*/
- public function api()
+ public function api(): View
{
-
// Make sure the self.api permission has been granted
if (!Gate::allows('self.api')) {
abort(403);
@@ -103,27 +96,23 @@ class ProfileController extends Controller
/**
* User change email page.
*
- * @return View
*/
- public function password()
+ public function password() : View
{
- $user = Auth::user();
-
+ $user = auth()->user();
return view('account/change-password', compact('user'));
}
/**
* Users change password form processing page.
- *
- * @return Redirect
*/
- public function passwordSave(Request $request)
+ public function passwordSave(Request $request) : RedirectResponse
{
if (config('app.lock_passwords')) {
return redirect()->route('account.password.index')->with('error', trans('admin/users/table.lock_passwords'));
}
- $user = Auth::user();
+ $user = auth()->user();
if ($user->ldap_import == '1') {
return redirect()->route('account.password.index')->with('error', trans('admin/users/message.error.password_ldap'));
}
@@ -184,9 +173,8 @@ class ProfileController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return View
*/
- public function getMenuState(Request $request)
+ public function getMenuState(Request $request) : void
{
if ($request->input('state') == 'open') {
$request->session()->put('menu_state', 'open');
@@ -201,14 +189,13 @@ class ProfileController extends Controller
*
* @author A. Gianotto
* @since [v6.0.12]
- * @return Illuminate\View\View
*/
- public function printInventory()
+ public function printInventory() : View
{
- $show_user = Auth::user();
+ $show_user = auth()->user();
return view('users/print')
- ->with('assets', Auth::user()->assets)
+ ->with('assets', auth()->user()->assets)
->with('licenses', $show_user->licenses()->get())
->with('accessories', $show_user->accessories()->get())
->with('consumables', $show_user->consumables()->get())
@@ -221,12 +208,11 @@ class ProfileController extends Controller
*
* @author A. Gianotto
* @since [v6.0.12]
- * @return \Illuminate\Http\RedirectResponse
*/
- public function emailAssetList()
+ public function emailAssetList() : RedirectResponse
{
- if (!$user = User::find(Auth::user()->id)) {
+ if (!$user = User::find(auth()->id())) {
return redirect()->back()
->with('error', trans('admin/users/message.user_not_found', ['id' => $id]));
}
diff --git a/app/Http/Controllers/ReportsController.php b/app/Http/Controllers/ReportsController.php
index 6372c37beb..c4b7ee0609 100644
--- a/app/Http/Controllers/ReportsController.php
+++ b/app/Http/Controllers/ReportsController.php
@@ -6,6 +6,8 @@ use App\Helpers\Helper;
use App\Models\Accessory;
use App\Models\Actionlog;
use App\Models\Asset;
+use App\Models\AssetModel;
+use App\Models\Category;
use App\Models\AssetMaintenance;
use App\Models\CheckoutAcceptance;
use App\Models\CustomField;
@@ -14,17 +16,16 @@ use App\Models\License;
use App\Models\Setting;
use App\Notifications\CheckoutAssetNotification;
use Carbon\Carbon;
-use Illuminate\Auth\Access\AuthorizationException;
use Illuminate\Http\Request;
+use Illuminate\Http\Response;
use Illuminate\Support\Facades\Notification;
-use Illuminate\Support\Facades\Response;
-use Illuminate\Support\Facades\View;
-use Input;
+use \Illuminate\Contracts\View\View;
use League\Csv\Reader;
use Symfony\Component\HttpFoundation\StreamedResponse;
use League\Csv\EscapeFormula;
use App\Http\Requests\CustomAssetReportRequest;
-
+use Illuminate\Support\Facades\Log;
+use Illuminate\Http\RedirectResponse;
/**
* This controller handles all actions related to Reports for
@@ -47,9 +48,9 @@ class ReportsController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.0]
- * @return View
+ * @return \Illuminate\Contracts\View\View
*/
- public function getAccessoryReport()
+ public function getAccessoryReport() : View
{
$this->authorize('reports.view');
@@ -65,7 +66,7 @@ class ReportsController extends Controller
* @since [v1.0]
* @return \Illuminate\Http\Response
*/
- public function exportAccessoryReport()
+ public function exportAccessoryReport() : Response
{
$this->authorize('reports.view');
$accessories = Accessory::orderBy('created_at', 'DESC')->get();
@@ -92,7 +93,7 @@ class ReportsController extends Controller
}
$csv = implode("\n", $rows);
- $response = Response::make($csv, 200);
+ $response = response()->make($csv, 200);
$response->header('Content-Type', 'text/csv');
$response->header('Content-disposition', 'attachment;filename=report.csv');
@@ -104,9 +105,8 @@ class ReportsController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.0]
- * @return View
*/
- public function getDeprecationReport()
+ public function getDeprecationReport() : View
{
$this->authorize('reports.view');
$depreciations = Depreciation::get();
@@ -119,9 +119,8 @@ class ReportsController extends Controller
* @deprecated Server-side exports have been replaced by datatables export since v2.
* @author [A. Gianotto] []
* @since [v1.0]
- * @return \Illuminate\Http\Response
*/
- public function exportDeprecationReport()
+ public function exportDeprecationReport() : Response
{
$this->authorize('reports.view');
// Grab all the assets
@@ -197,12 +196,10 @@ class ReportsController extends Controller
*
* @author [A. Gianotto] []
* @since [v4.0]
- * @return View
*/
- public function audit()
+ public function audit() : View
{
$this->authorize('reports.view');
-
return view('reports/audit');
}
@@ -212,9 +209,8 @@ class ReportsController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.0]
- * @return View
*/
- public function getActivityReport()
+ public function getActivityReport() : View
{
$this->authorize('reports.view');
@@ -226,16 +222,15 @@ class ReportsController extends Controller
*
* @author [A. Gianotto] []
* @since [v5.0.7]
- * @return \Illuminate\Http\Response
*/
- public function postActivityReport(Request $request)
+ public function postActivityReport(Request $request) : StreamedResponse
{
ini_set('max_execution_time', 12000);
$this->authorize('reports.view');
\Debugbar::disable();
$response = new StreamedResponse(function () {
- \Log::debug('Starting streamed response');
+ Log::debug('Starting streamed response');
// Open output stream
$handle = fopen('php://output', 'w');
@@ -259,16 +254,16 @@ class ReportsController extends Controller
];
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
- \Log::debug('Starting headers: '.$executionTime);
+ Log::debug('Starting headers: '.$executionTime);
fputcsv($handle, $header);
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
- \Log::debug('Added headers: '.$executionTime);
+ Log::debug('Added headers: '.$executionTime);
$actionlogs = Actionlog::with('item', 'user', 'target', 'location')
->orderBy('created_at', 'DESC')
->chunk(20, function ($actionlogs) use ($handle) {
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
- \Log::debug('Walking results: '.$executionTime);
+ Log::debug('Walking results: '.$executionTime);
$count = 0;
foreach ($actionlogs as $actionlog) {
@@ -312,7 +307,7 @@ class ReportsController extends Controller
// Close the output stream
fclose($handle);
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
- \Log::debug('-- SCRIPT COMPLETED IN '.$executionTime);
+ Log::debug('-- SCRIPT COMPLETED IN '.$executionTime);
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="activity-report-'.date('Y-m-d-his').'.csv"',
@@ -328,9 +323,8 @@ class ReportsController extends Controller
*
* @author [A. Gianotto] []
* @since [v1.0]
- * @return View
*/
- public function getLicenseReport()
+ public function getLicenseReport() : View
{
$this->authorize('reports.view');
$licenses = License::with('depreciation')->orderBy('created_at', 'DESC')
@@ -346,9 +340,8 @@ class ReportsController extends Controller
* @deprecated Server-side exports have been replaced by datatables export since v2.
* @author [A. Gianotto] []
* @since [v1.0]
- * @return \Illuminate\Http\Response
*/
- public function exportLicenseReport()
+ public function exportLicenseReport() : Response
{
$this->authorize('reports.view');
$licenses = License::orderBy('created_at', 'DESC')->get();
@@ -385,7 +378,7 @@ class ReportsController extends Controller
$csv = implode("\n", $rows);
- $response = Response::make($csv, 200);
+ $response = response()->make($csv, 200);
$response->header('Content-Type', 'text/csv');
$response->header('Content-disposition', 'attachment;filename=report.csv');
@@ -398,9 +391,8 @@ class ReportsController extends Controller
* @author [A. Gianotto] []
* @see ReportsController::postCustomReport() method that generates the CSV
* @since [v1.0]
- * @return \Illuminate\Http\Response
*/
- public function getCustomReport()
+ public function getCustomReport() : View
{
$this->authorize('reports.view');
$customfields = CustomField::get();
@@ -414,9 +406,8 @@ class ReportsController extends Controller
* @author [A. Gianotto] []
* @see ReportsController::getCustomReport() method that generates form view
* @since [v1.0]
- * @return \Illuminate\Http\Response
*/
- public function postCustom(CustomAssetReportRequest $request)
+ public function postCustom(CustomAssetReportRequest $request) : StreamedResponse
{
ini_set('max_execution_time', env('REPORT_TIME_LIMIT', 12000)); //12000 seconds = 200 minutes
$this->authorize('reports.view');
@@ -425,8 +416,8 @@ class ReportsController extends Controller
\Debugbar::disable();
$customfields = CustomField::get();
$response = new StreamedResponse(function () use ($customfields, $request) {
- \Log::debug('Starting streamed response');
- \Log::debug('CSV escaping is set to: '.config('app.escape_formulas'));
+ Log::debug('Starting streamed response');
+ Log::debug('CSV escaping is set to: '.config('app.escape_formulas'));
// Open output stream
$handle = fopen('php://output', 'w');
@@ -627,10 +618,10 @@ class ReportsController extends Controller
}
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
- \Log::debug('Starting headers: '.$executionTime);
+ Log::debug('Starting headers: '.$executionTime);
fputcsv($handle, $header);
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
- \Log::debug('Added headers: '.$executionTime);
+ Log::debug('Added headers: '.$executionTime);
$assets = Asset::select('assets.*')->with(
'location', 'assetstatus', 'company', 'defaultLoc', 'assignedTo',
@@ -681,28 +672,28 @@ class ReportsController extends Controller
}
if (($request->filled('created_start')) && ($request->filled('created_end'))) {
- $created_start = \Carbon::parse($request->input('created_start'))->startOfDay();
- $created_end = \Carbon::parse($request->input('created_end'))->endOfDay();
+ $created_start = Carbon::parse($request->input('created_start'))->startOfDay();
+ $created_end = Carbon::parse($request->input('created_end'))->endOfDay();
$assets->whereBetween('assets.created_at', [$created_start, $created_end]);
}
if (($request->filled('checkout_date_start')) && ($request->filled('checkout_date_end'))) {
- $checkout_start = \Carbon::parse($request->input('checkout_date_start'))->startOfDay();
- $checkout_end = \Carbon::parse($request->input('checkout_date_end',now()))->endOfDay();
+ $checkout_start = Carbon::parse($request->input('checkout_date_start'))->startOfDay();
+ $checkout_end = Carbon::parse($request->input('checkout_date_end',now()))->endOfDay();
$actionlogassets = Actionlog::where('action_type','=', 'checkout')
->where('item_type', 'LIKE', '%Asset%',)
->whereBetween('action_date',[$checkout_start, $checkout_end])
->pluck('item_id');
- $assets->whereIn('id',$actionlogassets);
+ $assets->whereIn('assets.id',$actionlogassets);
}
if (($request->filled('checkin_date_start'))) {
- $checkin_start = \Carbon::parse($request->input('checkin_date_start'))->startOfDay();
+ $checkin_start = Carbon::parse($request->input('checkin_date_start'))->startOfDay();
// use today's date is `checkin_date_end` is not provided
- $checkin_end = \Carbon::parse($request->input('checkin_date_end', now()))->endOfDay();
+ $checkin_end = Carbon::parse($request->input('checkin_date_end', now()))->endOfDay();
$assets->whereBetween('assets.last_checkin', [$checkin_start, $checkin_end ]);
}
@@ -713,8 +704,8 @@ class ReportsController extends Controller
}
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();
+ $last_audit_start = Carbon::parse($request->input('last_audit_start'))->startOfDay();
+ $last_audit_end = Carbon::parse($request->input('last_audit_end'))->endOfDay();
$assets->whereBetween('assets.last_audit_date', [$last_audit_start, $last_audit_end]);
}
@@ -732,11 +723,11 @@ class ReportsController extends Controller
$assets->onlyTrashed();
}
- \Log::debug($assets->toSql());
+ Log::debug($assets->toSql());
$assets->orderBy('assets.id', 'ASC')->chunk(20, function ($assets) use ($handle, $customfields, $request) {
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
- \Log::debug('Walking results: '.$executionTime);
+ Log::debug('Walking results: '.$executionTime);
$count = 0;
$formatter = new EscapeFormula("`");
@@ -933,7 +924,7 @@ class ReportsController extends Controller
$diff = ($asset->purchase_cost - $depreciation);
$row[] = Helper::formatCurrencyOutput($depreciation);
$row[] = Helper::formatCurrencyOutput($diff);
- $row[] = ($asset->depreciation) ? $asset->depreciated_date()->format('Y-m-d') : '';
+ $row[] = (($asset->depreciation) && ($asset->depreciated_date())) ? $asset->depreciated_date()->format('Y-m-d') : '';
}
if ($request->filled('checkout_date')) {
@@ -996,14 +987,14 @@ class ReportsController extends Controller
}
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
- \Log::debug('-- Record '.$count.' Asset ID:'.$asset->id.' in '.$executionTime);
+ Log::debug('-- Record '.$count.' Asset ID:'.$asset->id.' in '.$executionTime);
}
});
// Close the output stream
fclose($handle);
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
- \Log::debug('-- SCRIPT COMPLETED IN '.$executionTime);
+ Log::debug('-- SCRIPT COMPLETED IN '.$executionTime);
}, 200, [
'Content-Type' => 'text/csv',
'Content-Disposition' => 'attachment; filename="custom-assets-report-'.date('Y-m-d-his').'.csv"',
@@ -1015,11 +1006,10 @@ class ReportsController extends Controller
/**
* getImprovementsReport
*
- * @return View
* @author Vincent Sposato
* @version v1.0
*/
- public function getAssetMaintenancesReport()
+ public function getAssetMaintenancesReport() : View
{
$this->authorize('reports.view');
@@ -1029,11 +1019,10 @@ class ReportsController extends Controller
/**
* exportImprovementsReport
*
- * @return \Illuminate\Http\Response
* @author Vincent Sposato
* @version v1.0
*/
- public function exportAssetMaintenancesReport()
+ public function exportAssetMaintenancesReport() : Response
{
$this->authorize('reports.view');
// Grab all the improvements
@@ -1080,7 +1069,7 @@ class ReportsController extends Controller
// spit out a csv
$csv = implode("\n", $rows);
- $response = Response::make($csv, 200);
+ $response = response()->make($csv, 200);
$response->header('Content-Type', 'text/csv');
$response->header('Content-disposition', 'attachment;filename=report.csv');
@@ -1090,13 +1079,10 @@ class ReportsController extends Controller
/**
* getAssetAcceptanceReport
*
- * @return mixed
- * @throws \Illuminate\Auth\Access\AuthorizationException
-
* @author Vincent Sposato
* @version v1.0
*/
- public function getAssetAcceptanceReport($deleted = false)
+ public function getAssetAcceptanceReport($deleted = false) : View
{
$this->authorize('reports.view');
$showDeleted = $deleted == 'deleted';
@@ -1132,32 +1118,30 @@ class ReportsController extends Controller
* sentAssetAcceptanceReminder
*
* @param integer|null $acceptanceId
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
* @version v1.0
*/
- public function sentAssetAcceptanceReminder(Request $request)
+ public function sentAssetAcceptanceReminder(Request $request) : RedirectResponse
{
$this->authorize('reports.view');
if (!$acceptance = CheckoutAcceptance::pending()->find($request->input('acceptance_id'))) {
- \Log::debug('No pending acceptances');
+ Log::debug('No pending acceptances');
// Redirect to the unaccepted assets report page with error
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
}
$assetItem = $acceptance->checkoutable;
- \Log::debug(print_r($assetItem, true));
+ Log::debug(print_r($assetItem, true));
if (is_null($acceptance->created_at)){
- \Log::debug('No acceptance created_at');
+ Log::debug('No acceptance created_at');
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
} else {
$logItem_res = $assetItem->checkouts()->where('created_at', '=', $acceptance->created_at)->get();
if ($logItem_res->isEmpty()){
- \Log::debug('Acceptance date mismatch');
+ Log::debug('Acceptance date mismatch');
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
}
$logItem = $logItem_res[0];
@@ -1190,11 +1174,9 @@ class ReportsController extends Controller
* sentAssetAcceptanceReminder
*
* @param integer|null $acceptanceId
- * @return \Illuminate\Http\RedirectResponse
- * @throws \Illuminate\Auth\Access\AuthorizationException
* @version v1.0
*/
- public function deleteAssetAcceptance($acceptanceId = null)
+ public function deleteAssetAcceptance($acceptanceId = null) : RedirectResponse
{
$this->authorize('reports.view');
@@ -1213,11 +1195,10 @@ class ReportsController extends Controller
/**
* Exports the AssetAcceptance report to CSV
*
- * @return \Illuminate\Http\Response
* @author Vincent Sposato
* @version v1.0
*/
- public function postAssetAcceptanceReport($deleted = false)
+ public function postAssetAcceptanceReport($deleted = false) : Response
{
$this->authorize('reports.view');
$showDeleted = $deleted == 'deleted';
@@ -1268,7 +1249,7 @@ class ReportsController extends Controller
// spit out a csv
$csv = implode("\n", $rows);
- $response = Response::make($csv, 200);
+ $response = response()->make($csv, 200);
$response->header('Content-Type', 'text/csv');
$response->header('Content-disposition', 'attachment;filename=report.csv');
@@ -1284,7 +1265,7 @@ class ReportsController extends Controller
* @author Vincent Sposato
* @version v1.0
*/
- protected function getCheckedOutAssetsRequiringAcceptance($modelsInCategoriesThatRequireAcceptance)
+ protected function getCheckedOutAssetsRequiringAcceptance($modelsInCategoriesThatRequireAcceptance) : View
{
$this->authorize('reports.view');
$assets = Asset::deployed()
@@ -1304,11 +1285,11 @@ class ReportsController extends Controller
* @author Vincent Sposato
* @version v1.0
*/
- protected function getModelsInCategoriesThatRequireAcceptance($assetCategoriesRequiringAcceptance)
+ protected function getModelsInCategoriesThatRequireAcceptance($assetCategoriesRequiringAcceptance) : array
{
$this->authorize('reports.view');
- return array_pluck(Model::inCategory($assetCategoriesRequiringAcceptance)
+ return array_pluck(AssetModel::inCategory($assetCategoriesRequiringAcceptance)
->select('id')
->get()
->toArray(), 'id');
@@ -1321,7 +1302,7 @@ class ReportsController extends Controller
* @author Vincent Sposato
* @version v1.0
*/
- protected function getCategoriesThatRequireAcceptance()
+ protected function getCategoriesThatRequireAcceptance() : array
{
$this->authorize('reports.view');
@@ -1334,11 +1315,10 @@ class ReportsController extends Controller
/**
* getAssetsCheckedOutRequiringAcceptance
*
- * @return array
* @author Vincent Sposato
* @version v1.0
*/
- protected function getAssetsCheckedOutRequiringAcceptance()
+ protected function getAssetsCheckedOutRequiringAcceptance() : array
{
$this->authorize('reports.view');
diff --git a/app/Http/Controllers/SettingsController.php b/app/Http/Controllers/SettingsController.php
index dbb6f66222..c5c36d7b81 100755
--- a/app/Http/Controllers/SettingsController.php
+++ b/app/Http/Controllers/SettingsController.php
@@ -14,22 +14,25 @@ use App\Models\Asset;
use App\Models\User;
use App\Notifications\FirstAdminNotification;
use App\Notifications\MailTest;
-use Auth;
-use Crypt;
-use DB;
-use enshrined\svgSanitize\Sanitizer;
+use Illuminate\Http\Client\HttpClientException;
use Illuminate\Http\Request;
+use Illuminate\Support\Facades\App;
use Illuminate\Support\Facades\Storage;
use Illuminate\Validation\Rule;
-use Image;
-use Input;
-use Redirect;
-use Response;
-use App\Http\Requests\SlackSettingsRequest;
+use Illuminate\Http\RedirectResponse;
+use Illuminate\Http\JsonResponse;
+use \Illuminate\Contracts\View\View;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Artisan;
+use Illuminate\Support\Facades\Auth;
+use Illuminate\Support\Facades\Crypt;
+use Illuminate\Support\Facades\DB;
+use Illuminate\Support\Facades\File;
+use Illuminate\Support\Facades\Http;
+use Illuminate\Support\Facades\Log;
+use Illuminate\Support\Facades\URL;
use Illuminate\Support\Facades\Validator;
-use Carbon\Carbon;
+use Symfony\Component\HttpFoundation\BinaryFileResponse;
/**
* This controller handles all actions related to Settings for
@@ -47,9 +50,9 @@ class SettingsController extends Controller
*
* @since [v3.0]
*
- * @return View
+ * @return \Illuminate\Contracts\View\View | \Illuminate\Http\Response
*/
- public function getSetupIndex()
+ public function getSetupIndex() : View
{
$start_settings['php_version_min'] = false;
@@ -68,47 +71,15 @@ class SettingsController extends Controller
$start_settings['db_error'] = $e->getMessage();
}
- if (array_key_exists("HTTP_X_FORWARDED_PROTO", $_SERVER)) {
- $protocol = $_SERVER["HTTP_X_FORWARDED_PROTO"] . "://";
- } elseif (array_key_exists('HTTPS', $_SERVER) && ('on' == $_SERVER['HTTPS'])) {
- $protocol = "https://";
- } else {
- $protocol = "http://";
- }
-
- if (array_key_exists("HTTP_X_FORWARDED_HOST", $_SERVER)) {
- $host = $_SERVER["HTTP_X_FORWARDED_HOST"];
- } else {
- $host = array_key_exists('SERVER_NAME', $_SERVER) ? $_SERVER['SERVER_NAME'] : null;
- $port = array_key_exists('SERVER_PORT', $_SERVER) ? $_SERVER['SERVER_PORT'] : null;
- if (('http://' === $protocol && '80' != $port) || ('https://' === $protocol && '443' != $port)) {
- $host .= ':'.$port;
- }
- }
- $pageURL = $protocol.$host.$_SERVER['REQUEST_URI'];
-
- $start_settings['url_config'] = config('app.url').'/setup';
- $start_settings['url_valid'] = ($start_settings['url_config'] === $pageURL);
- $start_settings['real_url'] = $pageURL;
+ $start_settings['url_config'] = trim(config('app.url'), '/'). '/setup';
+ $start_settings['real_url'] = request()->url();
+ $start_settings['url_valid'] = $start_settings['url_config'] === $start_settings['real_url'];
$start_settings['php_version_min'] = true;
// Curl the .env file to make sure it's not accessible via a browser
- $ch = curl_init($protocol.$host.'/.env');
- curl_setopt($ch, CURLOPT_HEADER, true); // we want headers
- curl_setopt($ch, CURLOPT_NOBODY, true); // we don't need body
- curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
- curl_setopt($ch, CURLOPT_TIMEOUT, 10);
- $output = curl_exec($ch);
- $httpcode = curl_getinfo($ch, CURLINFO_HTTP_CODE);
- curl_close($ch);
+ $start_settings['env_exposed'] = $this->dotEnvFileIsExposed();
- if (404 == $httpcode || 403 == $httpcode || 0 == $httpcode) {
- $start_settings['env_exposed'] = false;
- } else {
- $start_settings['env_exposed'] = true;
- }
-
- if (\App::Environment('production') && (true == config('app.debug'))) {
+ if (App::Environment('production') && (true == config('app.debug'))) {
$start_settings['debug_exposed'] = true;
} else {
$start_settings['debug_exposed'] = false;
@@ -139,17 +110,7 @@ class SettingsController extends Controller
$start_settings['owner_is_admin'] = false;
}
- if ((is_writable(storage_path()))
- && (is_writable(storage_path().'/framework'))
- && (is_writable(storage_path().'/framework/cache'))
- && (is_writable(storage_path().'/framework/sessions'))
- && (is_writable(storage_path().'/framework/views'))
- && (is_writable(storage_path().'/logs'))
- ) {
- $start_settings['writable'] = true;
- } else {
- $start_settings['writable'] = false;
- }
+ $start_settings['writable'] = $this->storagePathIsWritable();
$start_settings['gd'] = extension_loaded('gd');
@@ -159,17 +120,48 @@ class SettingsController extends Controller
->with('section', 'Pre-Flight Check');
}
+ /**
+ * Determine if the .env file accessible via a browser.
+ *
+ * @return bool This method will return true when exceptions (such as curl exception) is thrown.
+ * Check the log files to see more details about the exception.
+ */
+ protected function dotEnvFileIsExposed() : bool
+ {
+ try {
+ return Http::timeout(10)
+ ->accept('*/*')
+ ->get(URL::to('.env'))
+ ->successful();
+ } catch (HttpClientException $e) {
+ Log::debug($e->getMessage());
+ return true;
+ }
+ }
+
+ /**
+ * Determine if the app storage path is writable.
+ */
+ protected function storagePathIsWritable(): bool
+ {
+ return File::isWritable(storage_path()) &&
+ File::isWritable(storage_path('framework')) &&
+ File::isWritable(storage_path('framework/cache')) &&
+ File::isWritable(storage_path('framework/sessions')) &&
+ File::isWritable(storage_path('framework/views')) &&
+ File::isWritable(storage_path('logs'));
+ }
+
/**
* Save the first admin user from Setup.
*
* @author [A. Gianotto] []
- *
* @since [v3.0]
*
- * @return Redirect
*/
- public function postSaveFirstAdmin(SetupUserRequest $request)
+ public function postSaveFirstAdmin(SetupUserRequest $request) : RedirectResponse
{
+
$user = new User();
$user->first_name = $data['first_name'] = $request->input('first_name');
$user->last_name = $request->input('last_name');
@@ -224,10 +216,8 @@ class SettingsController extends Controller
* @author [A. Gianotto] []
*
* @since [v3.0]
- *
- * @return View
*/
- public function getSetupUser()
+ public function getSetupUser() : View
{
return view('setup/user')
->with('step', 3)
@@ -240,10 +230,8 @@ class SettingsController extends Controller
* @author [A. Gianotto] []
*
* @since [v3.0]
- *
- * @return View
*/
- public function getSetupDone()
+ public function getSetupDone() : View
{
return view('setup/done')
->with('step', 4)
@@ -257,10 +245,8 @@ class SettingsController extends Controller
* @author [A. Gianotto] []
*
* @since [v3.0]
- *
- * @return View
*/
- public function getSetupMigrate()
+ public function getSetupMigrate() : View
{
Artisan::call('migrate', ['--force' => true]);
if ((! file_exists(storage_path().'/oauth-private.key')) || (! file_exists(storage_path().'/oauth-public.key'))) {
@@ -280,10 +266,8 @@ class SettingsController extends Controller
* @author [A. Gianotto] []
*
* @since [v1.0]
- *
- * @return View
*/
- public function index()
+ public function index() : View
{
$settings = Setting::getSettings();
@@ -296,10 +280,9 @@ class SettingsController extends Controller
* @author [A. Gianotto] [