Compare commits
12 Commits
custom_fie
...
features/s
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
28e8db400a | ||
|
|
cde1ab241b | ||
|
|
cc1f9451da | ||
|
|
5d16f5d0d8 | ||
|
|
1d47e87d54 | ||
|
|
d2ab358c6a | ||
|
|
6a6c356cf3 | ||
|
|
262204568e | ||
|
|
3340d8ffcf | ||
|
|
dd3fcdf018 | ||
|
|
be404d34c5 | ||
|
|
79b9b097a8 |
@@ -2837,130 +2837,6 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "AndrewSav",
|
||||
"name": "Andrew Savinykh",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/658865?v=4",
|
||||
"profile": "https://github.com/AndrewSav",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "kenchan0130",
|
||||
"name": "Tadayuki Onishi",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1155067?v=4",
|
||||
"profile": "https://kenchan0130.github.io",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "floschoepfer",
|
||||
"name": "Florian",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/112496896?v=4",
|
||||
"profile": "https://github.com/floschoepfer",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "spencerrlongg",
|
||||
"name": "Spencer Long",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/7305753?v=4",
|
||||
"profile": "http://spencerlong.com",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "marcusmoore",
|
||||
"name": "Marcus Moore",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1141514?v=4",
|
||||
"profile": "https://github.com/marcusmoore",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Mezzle",
|
||||
"name": "Martin Meredith",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/570639?v=4",
|
||||
"profile": "https://github.com/Mezzle",
|
||||
"contributions": []
|
||||
},
|
||||
{
|
||||
"login": "dboth",
|
||||
"name": "dboth",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5731963?v=4",
|
||||
"profile": "http://dboth.de",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "zacharyfleck",
|
||||
"name": "Zachary Fleck",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/87536651?v=4",
|
||||
"profile": "https://github.com/zacharyfleck",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "vikaas-cyper",
|
||||
"name": "VIKAAS-A",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/74609912?v=4",
|
||||
"profile": "https://github.com/vikaas-cyper",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "ak-piracha",
|
||||
"name": "Abdul Kareem",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/88882041?v=4",
|
||||
"profile": "https://github.com/ak-piracha",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "NojoudAlshehri",
|
||||
"name": "NojoudAlshehri",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/111287779?v=4",
|
||||
"profile": "https://github.com/NojoudAlshehri",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "stefanstidlffg",
|
||||
"name": "Stefan Stidl",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/54367449?v=4",
|
||||
"profile": "https://github.com/stefanstidlffg",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "qay21",
|
||||
"name": "Quentin Aymard",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/87803479?v=4",
|
||||
"profile": "https://github.com/qay21",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "cram42",
|
||||
"name": "Grant Le Roux",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5396871?v=4",
|
||||
"profile": "https://github.com/cram42",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
@@ -1,44 +0,0 @@
|
||||
version: 1
|
||||
|
||||
environment:
|
||||
php: 8.0
|
||||
node: 12
|
||||
|
||||
services:
|
||||
- mysql: 5.7
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
|
||||
pull_request:
|
||||
branches: .*
|
||||
|
||||
pipeline:
|
||||
- name: Setup
|
||||
cmd: |
|
||||
cp -v .env.testing.example .env
|
||||
cp -v .env.testing.example .env.testing
|
||||
composer install --no-interaction --prefer-dist --optimize-autoloader
|
||||
|
||||
- name: Generate Key
|
||||
cmd: |
|
||||
php artisan key:generate --force
|
||||
|
||||
- name: Passport Keys
|
||||
cmd: |
|
||||
php artisan passport:keys
|
||||
|
||||
- name: Run Migrations
|
||||
cmd: |
|
||||
php artisan migrate --force
|
||||
|
||||
- name: PHPUnit Unit Tests
|
||||
cmd: |
|
||||
php artisan test --testsuite Unit
|
||||
|
||||
- name: PHPUnit Feature Tests
|
||||
cmd: |
|
||||
php artisan test --testsuite Feature
|
||||
11
.env.example
11
.env.example
@@ -85,7 +85,6 @@ COOKIE_NAME=snipeit_session
|
||||
COOKIE_DOMAIN=null
|
||||
SECURE_COOKIES=false
|
||||
API_TOKEN_EXPIRATION_YEARS=15
|
||||
BS_TABLE_STORAGE=cookieStorage
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SECURITY HEADER SETTINGS
|
||||
@@ -149,7 +148,6 @@ AWS_DEFAULT_REGION=null
|
||||
# --------------------------------------------
|
||||
LOGIN_MAX_ATTEMPTS=5
|
||||
LOGIN_LOCKOUT_DURATION=60
|
||||
LOGIN_AUTOCOMPLETE=false
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: FORGOTTEN PASSWORD SETTINGS
|
||||
@@ -177,15 +175,6 @@ REQUIRE_SAML=false
|
||||
API_THROTTLE_PER_MINUTE=120
|
||||
CSV_ESCAPE_FORMULAS=true
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: HASHING
|
||||
# --------------------------------------------
|
||||
HASHING_DRIVER='bcrypt'
|
||||
BCRYPT_ROUNDS=10
|
||||
ARGON_MEMORY=1024
|
||||
ARGON_THREADS=2
|
||||
ARGON_TIME=2
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SCIM
|
||||
# --------------------------------------------
|
||||
|
||||
75
.env.testing
Normal file
75
.env.testing
Normal file
@@ -0,0 +1,75 @@
|
||||
# --------------------------------------------
|
||||
# REQUIRED: BASIC APP SETTINGS
|
||||
# --------------------------------------------
|
||||
APP_ENV=testing
|
||||
APP_DEBUG=true
|
||||
APP_KEY=base64:glJpcM7BYwWiBggp3SQ/+NlRkqsBQMaGEOjemXqJzOU=
|
||||
APP_URL=http://localhost:8000
|
||||
APP_TIMEZONE='US/Pacific'
|
||||
APP_LOCALE=en
|
||||
FILESYSTEM_DISK=local
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: DATABASE SETTINGS
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=sqlite_testing
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=testing.sqlite
|
||||
DB_USERNAME=null
|
||||
DB_PASSWORD=null
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
||||
# --------------------------------------------
|
||||
MAIL_DRIVER=log
|
||||
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
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: IMAGE LIBRARY
|
||||
# This should be gd or imagick
|
||||
# --------------------------------------------
|
||||
IMAGE_LIB=gd
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: AWS SETTINGS
|
||||
# --------------------------------------------
|
||||
AWS_SECRET_ACCESS_KEY=null
|
||||
AWS_ACCESS_KEY_ID=null
|
||||
AWS_DEFAULT_REGION=null
|
||||
AWS_BUCKET=null
|
||||
AWS_BUCKET_ROOT=null
|
||||
AWS_URL=null
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: CACHE SETTINGS
|
||||
# --------------------------------------------
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
QUEUE_DRIVER=sync
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SESSION SETTINGS
|
||||
# --------------------------------------------
|
||||
SESSION_LIFETIME=12000
|
||||
EXPIRE_ON_CLOSE=false
|
||||
ENCRYPT=false
|
||||
COOKIE_NAME=snipeittest_session
|
||||
COOKIE_DOMAIN=null
|
||||
SECURE_COOKIES=false
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: APP LOG FORMAT
|
||||
# --------------------------------------------
|
||||
LOG_CHANNEL=single
|
||||
LOG_LEVEL=debug
|
||||
@@ -1,19 +0,0 @@
|
||||
# --------------------------------------------
|
||||
# REQUIRED: BASIC APP SETTINGS
|
||||
# --------------------------------------------
|
||||
APP_ENV=testing
|
||||
APP_DEBUG=true
|
||||
APP_KEY=base64:glJpcM7BYwWiBggp3SQ/+NlRkqsBQMaGEOjemXqJzOU=
|
||||
APP_URL=http://localhost:8000
|
||||
APP_TIMEZONE='UTC'
|
||||
APP_LOCALE=en
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: DATABASE SETTINGS
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=null
|
||||
DB_USERNAME=null
|
||||
DB_PASSWORD=null
|
||||
2
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
2
.github/ISSUE_TEMPLATE/feature_request.yml
vendored
@@ -2,6 +2,8 @@ name: Feature Request
|
||||
description: Suggest an idea for this project
|
||||
title: "[Feature Request]: "
|
||||
labels: ["feature request"]
|
||||
assignees:
|
||||
- snipe
|
||||
body:
|
||||
- type: textarea
|
||||
attributes:
|
||||
|
||||
16
.github/autolabeler.yml
vendored
16
.github/autolabeler.yml
vendored
@@ -1,22 +1,18 @@
|
||||
frontend: ["*.js", "*.css", "*.vue", "*.scss", "*.less", "*.blade.*", "resources/views/livewire/*"]
|
||||
frontend: ["*.js", "*.css", "*.vue", "*.scss", "*.less", "*.blade.*", "*livewire*"]
|
||||
skins: ["*.js", "*.css", "*.scss", "*.less"]
|
||||
css: ["*.css","*.scss", "*.less"]
|
||||
javascript: ["*.js", "package.json", "package.lock"]
|
||||
backend: ["/app/*", "composer.json", "composer.lock"]
|
||||
translations: ["/resources/lang"]
|
||||
livewire: ["/app/Http/Livewire/*", "resources/views/livewire/*"]
|
||||
backend: ["/app/*", "*.php"]
|
||||
backups: ["*backup*"]
|
||||
restore: ["*restore*"]
|
||||
saml: ["*saml*"]
|
||||
scim: ["*scim*"]
|
||||
custom fields: ["*fields*", "*fieldsets*"]
|
||||
dependencies: ["composer.json", "composer.lock", "package.json", "package.lock"]
|
||||
dependencies: ["composer.json"]
|
||||
consumables: ["*consumables*"]
|
||||
api: ["/app/Http/Controllers/Api/*"]
|
||||
api: ["/app/Http/Controllers/api/*"]
|
||||
notifications: ["/app/Notifications/*"]
|
||||
importer: ["/app/Importer/*","/app/Http/Livewire/Importer.php", "resources/views/livewire/importer.php"]
|
||||
importer: ["/app/Importer/*"]
|
||||
cli / artisan: ["/app/Console/*"]
|
||||
LDAP: ["*Ldap*", "/app/Console/Commands/Ldap*","/app/Models/Ldap.php"]
|
||||
LDAP: ["*LDAP*", "/app/Console/Commands/Ldap*","/app/Models/Ldap.php"]
|
||||
docker: ["*docker/*", "Dockerfile", "Dockerfile.alpine", "Dockerfile.fpm-alpine", ".dockerignore", ".env.docker"]
|
||||
tests: ["/tests/*", "/stubs"]
|
||||
config: .github
|
||||
|
||||
2
.github/workflows/codacy-analysis.yml
vendored
2
.github/workflows/codacy-analysis.yml
vendored
@@ -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.3.0
|
||||
uses: codacy/codacy-analysis-cli-action@v4.2.0
|
||||
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
|
||||
|
||||
21
.github/workflows/crowdin-upload.yml
vendored
21
.github/workflows/crowdin-upload.yml
vendored
@@ -1,21 +0,0 @@
|
||||
name: Crowdin Action
|
||||
|
||||
on:
|
||||
push:
|
||||
branches: [ develop ]
|
||||
|
||||
jobs:
|
||||
upload-sources-to-crowdin:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: Crowdin push
|
||||
uses: crowdin/github-action@v1
|
||||
with:
|
||||
upload_sources: true
|
||||
upload_translations: false
|
||||
download_translations: false
|
||||
project_id: ${{ secrets.CROWDIN_PROJECT_ID }}
|
||||
token: ${{ secrets.CROWDIN_PERSONAL_TOKEN }}
|
||||
4
.github/workflows/docker-alpine.yml
vendored
4
.github/workflows/docker-alpine.yml
vendored
@@ -72,11 +72,11 @@ jobs:
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push 'snipe-it' image
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.alpine
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: linux/amd64
|
||||
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
|
||||
# but we ONLY do an image push to DockerHub if it's NOT a PR
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
4
.github/workflows/docker.yml
vendored
4
.github/workflows/docker.yml
vendored
@@ -72,11 +72,11 @@ jobs:
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push 'snipe-it' image
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v4
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
platforms: linux/amd64,linux/arm64
|
||||
platforms: linux/amd64
|
||||
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
|
||||
# but we ONLY do an image push to DockerHub if it's NOT a PR
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
73
.github/workflows/tests.yml
vendored
73
.github/workflows/tests.yml
vendored
@@ -1,73 +0,0 @@
|
||||
name: Tests
|
||||
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
- develop
|
||||
pull_request:
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
mysql:
|
||||
image: mysql:5.7
|
||||
env:
|
||||
MYSQL_ALLOW_EMPTY_PASSWORD: yes
|
||||
MYSQL_DATABASE: snipeit
|
||||
ports:
|
||||
- 33306:3306
|
||||
options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-version:
|
||||
- "7.4"
|
||||
- "8.0"
|
||||
- "8.1.1"
|
||||
|
||||
name: PHP ${{ matrix.php-version }}
|
||||
|
||||
steps:
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
coverage: none
|
||||
|
||||
- uses: actions/checkout@v3
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache@v3
|
||||
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: Generate key
|
||||
run: php artisan key:generate
|
||||
|
||||
- name: Directory Permissions
|
||||
run: chmod -R 777 storage bootstrap/cache
|
||||
|
||||
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
||||
env:
|
||||
DB_CONNECTION: mysql
|
||||
DB_DATABASE: snipeit
|
||||
DB_PORT: ${{ job.services.mysql.ports[3306] }}
|
||||
DB_USERNAME: root
|
||||
run: php artisan test --parallel
|
||||
4
.gitignore
vendored
4
.gitignore
vendored
@@ -1,8 +1,8 @@
|
||||
.couscous
|
||||
.DS_Store
|
||||
.env
|
||||
.env.testing
|
||||
phpstan.neon
|
||||
.env.dusk.*
|
||||
!.env.dusk.example
|
||||
.idea
|
||||
/bin/
|
||||
/bootstrap/compiled.php
|
||||
|
||||
33
Dockerfile
33
Dockerfile
@@ -1,4 +1,4 @@
|
||||
FROM ubuntu:22.04
|
||||
FROM ubuntu:20.04
|
||||
LABEL maintainer="Brady Wetherington <bwetherington@grokability.com>"
|
||||
|
||||
# No need to add `apt-get clean` here, reference:
|
||||
@@ -14,16 +14,16 @@ RUN export DEBIAN_FRONTEND=noninteractive; \
|
||||
apt-utils \
|
||||
apache2 \
|
||||
apache2-bin \
|
||||
libapache2-mod-php8.1 \
|
||||
php8.1-curl \
|
||||
php8.1-ldap \
|
||||
php8.1-mysql \
|
||||
php8.1-gd \
|
||||
php8.1-xml \
|
||||
php8.1-mbstring \
|
||||
php8.1-zip \
|
||||
php8.1-bcmath \
|
||||
php8.1-redis \
|
||||
libapache2-mod-php7.4 \
|
||||
php7.4-curl \
|
||||
php7.4-ldap \
|
||||
php7.4-mysql \
|
||||
php7.4-gd \
|
||||
php7.4-xml \
|
||||
php7.4-mbstring \
|
||||
php7.4-zip \
|
||||
php7.4-bcmath \
|
||||
php7.4-redis \
|
||||
php-memcached \
|
||||
patch \
|
||||
curl \
|
||||
@@ -38,10 +38,9 @@ gcc \
|
||||
make \
|
||||
autoconf \
|
||||
libc-dev \
|
||||
libldap-common \
|
||||
pkg-config \
|
||||
libmcrypt-dev \
|
||||
php8.1-dev \
|
||||
php7.4-dev \
|
||||
ca-certificates \
|
||||
unzip \
|
||||
dnsutils \
|
||||
@@ -51,16 +50,16 @@ dnsutils \
|
||||
RUN curl -L -O https://github.com/pear/pearweb_phars/raw/master/go-pear.phar
|
||||
RUN php go-pear.phar
|
||||
|
||||
RUN pecl install mcrypt
|
||||
RUN pecl install mcrypt-1.0.3
|
||||
|
||||
RUN bash -c "echo extension=/usr/lib/php/20210902/mcrypt.so > /etc/php/8.1/mods-available/mcrypt.ini"
|
||||
RUN bash -c "echo extension=/usr/lib/php/20190902/mcrypt.so > /etc/php/7.4/mods-available/mcrypt.ini"
|
||||
|
||||
RUN phpenmod mcrypt
|
||||
RUN phpenmod gd
|
||||
RUN phpenmod bcmath
|
||||
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/8.1/apache2/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/8.1/cli/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.4/apache2/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.4/cli/php.ini
|
||||
|
||||
RUN useradd -m --uid 1000 --gid 50 docker
|
||||
|
||||
|
||||
@@ -1,34 +1,34 @@
|
||||
FROM alpine:3.17.3
|
||||
FROM alpine:3.14.2
|
||||
# Apache + PHP
|
||||
RUN apk add --no-cache \
|
||||
apache2 \
|
||||
php81 \
|
||||
php81-common \
|
||||
php81-apache2 \
|
||||
php81-curl \
|
||||
php81-ldap \
|
||||
php81-mysqli \
|
||||
php81-gd \
|
||||
php81-xml \
|
||||
php81-mbstring \
|
||||
php81-zip \
|
||||
php81-ctype \
|
||||
php81-tokenizer \
|
||||
php81-pdo_mysql \
|
||||
php81-openssl \
|
||||
php81-bcmath \
|
||||
php81-phar \
|
||||
php81-json \
|
||||
php81-iconv \
|
||||
php81-fileinfo \
|
||||
php81-simplexml \
|
||||
php81-session \
|
||||
php81-dom \
|
||||
php81-xmlwriter \
|
||||
php81-xmlreader \
|
||||
php81-sodium \
|
||||
php81-redis \
|
||||
php81-pecl-memcached \
|
||||
php7 \
|
||||
php7-common \
|
||||
php7-apache2 \
|
||||
php7-curl \
|
||||
php7-ldap \
|
||||
php7-mysqli \
|
||||
php7-gd \
|
||||
php7-xml \
|
||||
php7-mbstring \
|
||||
php7-zip \
|
||||
php7-ctype \
|
||||
php7-tokenizer \
|
||||
php7-pdo_mysql \
|
||||
php7-openssl \
|
||||
php7-bcmath \
|
||||
php7-phar \
|
||||
php7-json \
|
||||
php7-iconv \
|
||||
php7-fileinfo \
|
||||
php7-simplexml \
|
||||
php7-session \
|
||||
php7-dom \
|
||||
php7-xmlwriter \
|
||||
php7-xmlreader \
|
||||
php7-sodium \
|
||||
php7-redis \
|
||||
php7-pecl-memcached \
|
||||
curl \
|
||||
wget \
|
||||
vim \
|
||||
@@ -41,7 +41,7 @@ COPY docker/column-statistics.cnf /etc/mysql/conf.d/column-statistics.cnf
|
||||
# Where apache's PID lives
|
||||
RUN mkdir -p /run/apache2 && chown apache:apache /run/apache2
|
||||
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php81/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php7/php.ini
|
||||
COPY docker/000-default-2.4.conf /etc/apache2/conf.d/default.conf
|
||||
|
||||
# Enable mod_rewrite
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
ARG ENVIRONMENT=production
|
||||
ARG SNIPEIT_RELEASE=6.1.0
|
||||
ARG PHP_VERSION=8.2
|
||||
ARG PHP_ALPINE_VERSION=3.17
|
||||
ARG COMPOSER_VERSION=2
|
||||
ARG SNIPEIT_RELEASE=5.1.3
|
||||
ARG PHP_VERSION=7.4.16
|
||||
ARG PHP_ALPINE_VERSION=3.13
|
||||
ARG COMPOSER_VERSION=2.0.11
|
||||
|
||||
# Cannot use arguments with 'COPY --from' workaround
|
||||
# https://github.com/moby/moby/issues/34482#issuecomment-454716952
|
||||
@@ -52,7 +52,7 @@ RUN { \
|
||||
|
||||
# Install php extensions inside docker containers easily
|
||||
# https://github.com/mlocati/docker-php-extension-installer
|
||||
COPY --from=mlocati/php-extension-installer:2.1.15 /usr/bin/install-php-extensions /usr/local/bin/
|
||||
COPY --from=mlocati/php-extension-installer:1.2.19 /usr/bin/install-php-extensions /usr/local/bin/
|
||||
RUN set -eux; \
|
||||
install-php-extensions \
|
||||
bcmath \
|
||||
|
||||
11
README.md
11
README.md
@@ -1,5 +1,5 @@
|
||||
 [](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)
|
||||
[](#contributors) [](https://discord.gg/yZFtShAcKk) [](https://huntr.dev)
|
||||
[](#contributors) [](https://discord.gg/yZFtShAcKk) [](https://huntr.dev)
|
||||
|
||||
## Snipe-IT - Open Source Asset Management System
|
||||
|
||||
@@ -66,11 +66,8 @@ Since the release of the JSON REST API, several third-party developers have been
|
||||
- [Python 3 CSV importer](https://github.com/gastamper/snipeit-csvimporter) - allows importing assets into Snipe-IT based on Item Name rather than Asset Tag.
|
||||
- [Snipe-IT Kubernetes Helm Chart](https://github.com/t3n/helm-charts/tree/master/snipeit) - For more information, [click here](https://hub.helm.sh/charts/t3n/snipeit).
|
||||
- [Snipe-IT Bulk Edit](https://github.com/bricelabelle/snipe-it-bulkedit) - Google Script files to use Google Sheets as a bulk checkout/checkin/edit tool for Snipe-it.
|
||||
- [MosyleSnipeSync](https://github.com/RodneyLeeBrands/MosyleSnipeSync) by [@Karpadiem](https://github.com/Karpadiem) - Python script to synchronize information between Mosyle and Snipe-IT
|
||||
- [MosyleSnipeSync](https://github.com/RodneyLeeBrands/MosyleSnipeSync) by [@RodneyLeeBrands](https://github.com/RodneyLeeBrands) - Python script to synchronize information between Mosyle and Snipe-IT
|
||||
- [WWW::SnipeIT](https://github.com/SEDC/perl-www-snipeit) by [@SEDC](https://github.com/SEDC) - perl module for accessing the API
|
||||
- [UniFi to Snipe-IT](https://github.com/RodneyLeeBrands/UnifiSnipeSync) by [@karpadiem](https://github.com/karpadiem) - Python script that synchronizes UniFi devices with Snipe-IT.
|
||||
- [Kandji2Snipe](https://github.com/grokability/kandji2snipe) by [@briangoldstein](https://github.com/briangoldstein) - Python script that synchronizes Kandji with Snipe-IT.
|
||||
- [SnipeAgent](https://github.com/ReticentRobot/SnipeAgent) by @ReticentRobot - Windows agent for Snipe-IT
|
||||
|
||||
As these were created by third-parties, Snipe-IT cannot provide support for these project, and you should contact the developers directly if you need assistance. Additionally, Snipe-IT makes no guarantees as to the reliability, accuracy or maintainability of these libraries. Use at your own risk. :)
|
||||
|
||||
@@ -143,9 +140,7 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
| [<img src="https://avatars.githubusercontent.com/u/97299851?v=4" width="110px;"/><br /><sub>Christian Weirich</sub>](https://github.com/chrisweirich)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chrisweirich "Code") | [<img src="https://avatars.githubusercontent.com/u/1294403?v=4" width="110px;"/><br /><sub>denzfarid</sub>](https://github.com/denzfarid)<br /> | [<img src="https://avatars.githubusercontent.com/u/94018771?v=4" width="110px;"/><br /><sub>ntbutler-nbcs</sub>](https://github.com/ntbutler-nbcs)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ntbutler-nbcs "Code") | [<img src="https://avatars.githubusercontent.com/u/172697?v=4" width="110px;"/><br /><sub>Naveen</sub>](https://naveensrinivasan.dev)<br />[💻](https://github.com/snipe/snipe-it/commits?author=naveensrinivasan "Code") | [<img src="https://avatars.githubusercontent.com/u/55674383?v=4" width="110px;"/><br /><sub>Mike Roquemore</sub>](https://github.com/mikeroq)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mikeroq "Code") | [<img src="https://avatars.githubusercontent.com/u/7991086?v=4" width="110px;"/><br /><sub>Daniel Reeder</sub>](https://github.com/reederda)<br />[🌍](#translation-reederda "Translation") [🌍](#translation-reederda "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=reederda "Code") | [<img src="https://avatars.githubusercontent.com/u/109422491?v=4" width="110px;"/><br /><sub>vickyjaura183</sub>](https://github.com/vickyjaura183)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vickyjaura183 "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/32363424?v=4" width="110px;"/><br /><sub>Peace</sub>](https://github.com/julian-piehl)<br />[💻](https://github.com/snipe/snipe-it/commits?author=julian-piehl "Code") | [<img src="https://avatars.githubusercontent.com/u/231528?v=4" width="110px;"/><br /><sub>Kyle Gordon</sub>](https://github.com/kylegordon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kylegordon "Code") | [<img src="https://avatars.githubusercontent.com/u/53009155?v=4" width="110px;"/><br /><sub>Katharina Drexel</sub>](http://www.bfh.ch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sunflowerbofh "Code") | [<img src="https://avatars.githubusercontent.com/u/1931963?v=4" width="110px;"/><br /><sub>David Sferruzza</sub>](https://david.sferruzza.fr/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dsferruzza "Code") | [<img src="https://avatars.githubusercontent.com/u/19511639?v=4" width="110px;"/><br /><sub>Rick Nelson</sub>](https://github.com/rnelsonee)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rnelsonee "Code") | [<img src="https://avatars.githubusercontent.com/u/94169344?v=4" width="110px;"/><br /><sub>BasO12</sub>](https://github.com/BasO12)<br />[💻](https://github.com/snipe/snipe-it/commits?author=BasO12 "Code") | [<img src="https://avatars.githubusercontent.com/u/111710123?v=4" width="110px;"/><br /><sub>Vautia</sub>](https://github.com/Vautia)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Vautia "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/28321?v=4" width="110px;"/><br /><sub>Chris Hartjes</sub>](http://www.littlehart.net/atthekeyboard)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chartjes "Code") | [<img src="https://avatars.githubusercontent.com/u/2404584?v=4" width="110px;"/><br /><sub>geo-chen</sub>](https://github.com/geo-chen)<br />[💻](https://github.com/snipe/snipe-it/commits?author=geo-chen "Code") | [<img src="https://avatars.githubusercontent.com/u/6006620?v=4" width="110px;"/><br /><sub>Phan Nguyen</sub>](https://github.com/nh314)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nh314 "Code") | [<img src="https://avatars.githubusercontent.com/u/115993812?v=4" width="110px;"/><br /><sub>Iisakki Jaakkola</sub>](https://github.com/StarlessNights)<br />[💻](https://github.com/snipe/snipe-it/commits?author=StarlessNights "Code") | [<img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="110px;"/><br /><sub>Ikko Ashimine</sub>](https://bandism.net/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=eltociear "Code") | [<img src="https://avatars.githubusercontent.com/u/56871540?v=4" width="110px;"/><br /><sub>Lukas Fehling</sub>](https://github.com/lukasfehling)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lukasfehling "Code") | [<img src="https://avatars.githubusercontent.com/u/1975990?v=4" width="110px;"/><br /><sub>Fernando Almeida</sub>](https://github.com/fernando-almeida)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fernando-almeida "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/116301219?v=4" width="110px;"/><br /><sub>akemidx</sub>](https://github.com/akemidx)<br />[💻](https://github.com/snipe/snipe-it/commits?author=akemidx "Code") | [<img src="https://avatars.githubusercontent.com/u/144778?v=4" width="110px;"/><br /><sub>Oguz Bilgic</sub>](http://oguz.site)<br />[💻](https://github.com/snipe/snipe-it/commits?author=oguzbilgic "Code") | [<img src="https://avatars.githubusercontent.com/u/9262438?v=4" width="110px;"/><br /><sub>Scooter Crawford</sub>](https://github.com/scoo73r)<br />[💻](https://github.com/snipe/snipe-it/commits?author=scoo73r "Code") | [<img src="https://avatars.githubusercontent.com/u/5957345?v=4" width="110px;"/><br /><sub>subdriven</sub>](https://github.com/subdriven)<br />[💻](https://github.com/snipe/snipe-it/commits?author=subdriven "Code") | [<img src="https://avatars.githubusercontent.com/u/658865?v=4" width="110px;"/><br /><sub>Andrew Savinykh</sub>](https://github.com/AndrewSav)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AndrewSav "Code") | [<img src="https://avatars.githubusercontent.com/u/1155067?v=4" width="110px;"/><br /><sub>Tadayuki Onishi</sub>](https://kenchan0130.github.io)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kenchan0130 "Code") | [<img src="https://avatars.githubusercontent.com/u/112496896?v=4" width="110px;"/><br /><sub>Florian</sub>](https://github.com/floschoepfer)<br />[💻](https://github.com/snipe/snipe-it/commits?author=floschoepfer "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/7305753?v=4" width="110px;"/><br /><sub>Spencer Long</sub>](http://spencerlong.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=spencerrlongg "Code") | [<img src="https://avatars.githubusercontent.com/u/1141514?v=4" width="110px;"/><br /><sub>Marcus Moore</sub>](https://github.com/marcusmoore)<br />[💻](https://github.com/snipe/snipe-it/commits?author=marcusmoore "Code") | [<img src="https://avatars.githubusercontent.com/u/570639?v=4" width="110px;"/><br /><sub>Martin Meredith</sub>](https://github.com/Mezzle)<br /> | [<img src="https://avatars.githubusercontent.com/u/5731963?v=4" width="110px;"/><br /><sub>dboth</sub>](http://dboth.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dboth "Code") | [<img src="https://avatars.githubusercontent.com/u/87536651?v=4" width="110px;"/><br /><sub>Zachary Fleck</sub>](https://github.com/zacharyfleck)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zacharyfleck "Code") | [<img src="https://avatars.githubusercontent.com/u/74609912?v=4" width="110px;"/><br /><sub>VIKAAS-A</sub>](https://github.com/vikaas-cyper)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vikaas-cyper "Code") | [<img src="https://avatars.githubusercontent.com/u/88882041?v=4" width="110px;"/><br /><sub>Abdul Kareem</sub>](https://github.com/ak-piracha)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ak-piracha "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/111287779?v=4" width="110px;"/><br /><sub>NojoudAlshehri</sub>](https://github.com/NojoudAlshehri)<br />[💻](https://github.com/snipe/snipe-it/commits?author=NojoudAlshehri "Code") | [<img src="https://avatars.githubusercontent.com/u/54367449?v=4" width="110px;"/><br /><sub>Stefan Stidl</sub>](https://github.com/stefanstidlffg)<br />[💻](https://github.com/snipe/snipe-it/commits?author=stefanstidlffg "Code") | [<img src="https://avatars.githubusercontent.com/u/87803479?v=4" width="110px;"/><br /><sub>Quentin Aymard</sub>](https://github.com/qay21)<br />[💻](https://github.com/snipe/snipe-it/commits?author=qay21 "Code") | [<img src="https://avatars.githubusercontent.com/u/5396871?v=4" width="110px;"/><br /><sub>Grant Le Roux</sub>](https://github.com/cram42)<br />[💻](https://github.com/snipe/snipe-it/commits?author=cram42 "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/116301219?v=4" width="110px;"/><br /><sub>akemidx</sub>](https://github.com/akemidx)<br />[💻](https://github.com/snipe/snipe-it/commits?author=akemidx "Code") | [<img src="https://avatars.githubusercontent.com/u/144778?v=4" width="110px;"/><br /><sub>Oguz Bilgic</sub>](http://oguz.site)<br />[💻](https://github.com/snipe/snipe-it/commits?author=oguzbilgic "Code") | [<img src="https://avatars.githubusercontent.com/u/9262438?v=4" width="110px;"/><br /><sub>Scooter Crawford</sub>](https://github.com/scoo73r)<br />[💻](https://github.com/snipe/snipe-it/commits?author=scoo73r "Code") | [<img src="https://avatars.githubusercontent.com/u/5957345?v=4" width="110px;"/><br /><sub>subdriven</sub>](https://github.com/subdriven)<br />[💻](https://github.com/snipe/snipe-it/commits?author=subdriven "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
91
TESTING.md
91
TESTING.md
@@ -1,52 +1,75 @@
|
||||
# Running the Test Suite
|
||||
# Using the Test Suite
|
||||
|
||||
This document is targeted at developers looking to make modifications to this application's code base and want to run the existing test suite.
|
||||
This document is targeted at developers looking to make modifications to
|
||||
this application's code base and want to run the existing test suite.
|
||||
|
||||
Before starting, follow the [instructions](README.md#installation) for installing the application locally and ensure you can load it in a browser properly.
|
||||
|
||||
## Unit and Feature Tests
|
||||
## Setup
|
||||
|
||||
Before attempting to run the test suite copy the example environment file for tests and update the values to match your environment:
|
||||
Follow the instructions for installing the application locally,
|
||||
making sure to have also run the [database migrations](link to db migrations).
|
||||
|
||||
`cp .env.testing.example .env.testing`
|
||||
|
||||
The following should work for running tests in memory with sqlite:
|
||||
```
|
||||
# --------------------------------------------
|
||||
# REQUIRED: BASIC APP SETTINGS
|
||||
# --------------------------------------------
|
||||
APP_ENV=testing
|
||||
APP_DEBUG=true
|
||||
APP_KEY=base64:glJpcM7BYwWiBggp3SQ/+NlRkqsBQMaGEOjemXqJzOU=
|
||||
APP_URL=http://localhost:8000
|
||||
APP_TIMEZONE='UTC'
|
||||
APP_LOCALE=en
|
||||
## Unit Tests
|
||||
|
||||
The application will use values in the `.env.testing` file located
|
||||
in the root directory to override the
|
||||
default settings and/or other values that exist in your `.env` files.
|
||||
|
||||
Make sure to modify the section in `.env.testing` that has the
|
||||
database settings. In the example below, it is connecting to the
|
||||
[MariaDB](link-to-maria-db) server that is used if you install the
|
||||
application using [Docker](https://docker.com).
|
||||
|
||||
```dotenv
|
||||
# --------------------------------------------
|
||||
# REQUIRED: DATABASE SETTINGS
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=sqlite_testing
|
||||
#DB_HOST=127.0.0.1
|
||||
#DB_PORT=3306
|
||||
#DB_DATABASE=null
|
||||
#DB_USERNAME=null
|
||||
#DB_PASSWORD=null
|
||||
```
|
||||
|
||||
To use MySQL you should update the `DB_` variables to match your local test database:
|
||||
```
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3306
|
||||
DB_DATABASE={}
|
||||
DB_USERNAME={}
|
||||
DB_PASSWORD={}
|
||||
DB_DATABASE=snipeit
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=changeme1234
|
||||
```
|
||||
|
||||
Now you are ready to run the entire test suite from your terminal:
|
||||
To run the entire unit test suite, use the following command from your terminal:
|
||||
|
||||
`php artisan test`
|
||||
`php artisan test --env=testing`
|
||||
|
||||
To run individual test files, you can pass the path to the test that
|
||||
you want to run.
|
||||
|
||||
`php artisan test --env=testing tests/Unit/AccessoryTest.php`
|
||||
|
||||
## Browser Tests
|
||||
|
||||
Browser tests are run via [Laravel Dusk](https://laravel.com/docs/8.x/dusk) and require Google Chrome to be installed.
|
||||
|
||||
Before attempting to run Dusk tests copy the example environment file for Dusk and update the values to match your environment:
|
||||
|
||||
`cp .env.dusk.example .env.dusk.local`
|
||||
> `local` refers to the value of `APP_ENV` in your `.env` so if you have it set to `dev` then the file should be named `.env.dusk.dev`.
|
||||
|
||||
**Important**: Dusk tests cannot be run using an in-memory SQLite database. Additionally, the Dusk test suite uses the `DatabaseMigrations` trait which will leave the database in a fresh state after running. Therefore, it is recommended that you create a test database and point `DB_DATABASE` in `.env.dusk.local` to it.
|
||||
|
||||
### Test Setup
|
||||
|
||||
Your application needs to be configured and up and running in order for the browser
|
||||
tests to actually run. When running the tests locally, you can start the application
|
||||
using the following command:
|
||||
|
||||
`php artisan serve`
|
||||
|
||||
Now you are ready to run the test suite. Use the following command from another terminal tab or window:
|
||||
|
||||
`php artisan dusk`
|
||||
|
||||
To run individual test files, you can pass the path to the test that you want to run:
|
||||
|
||||
`php artisan test tests/Unit/AccessoryTest.php`
|
||||
`php artisan dusk tests/Browser/LoginTest.php`
|
||||
|
||||
If you get an error when attempting to run Dusk tests that says `Couldn't connect to server` run:
|
||||
|
||||
`php artisan dusk:chrome-driver --detect`
|
||||
|
||||
This command will install the specific ChromeDriver Dusk needs for your operating system and Chrome version.
|
||||
|
||||
@@ -56,7 +56,7 @@ class CheckoutLicenseToAllUsers extends Command
|
||||
return false;
|
||||
}
|
||||
|
||||
$users = User::whereNull('deleted_at')->where('autoassign_licenses', '=', 1)->with('licenses')->get();
|
||||
$users = User::whereNull('deleted_at')->with('licenses')->get();
|
||||
|
||||
if ($users->count() > $license->getAvailSeatsCountAttribute()) {
|
||||
$this->info('You do not have enough free seats to complete this task, so we will check out as many as we can. ');
|
||||
|
||||
@@ -3,31 +3,15 @@
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use \App\Models\User;
|
||||
|
||||
|
||||
class CreateAdmin extends Command
|
||||
{
|
||||
|
||||
/** @mixin User **/
|
||||
/**
|
||||
* App\Console\CreateAdmin
|
||||
* @property mixed $first_name
|
||||
* @property string $last_name
|
||||
* @property string $username
|
||||
* @property string $email
|
||||
* @property string $permissions
|
||||
* @property string $password
|
||||
* @property boolean $activated
|
||||
* @property boolean $show_in_list
|
||||
* @property boolean $autoassign_licenses
|
||||
* @property \Illuminate\Support\Carbon|null $created_at
|
||||
* @property mixed $created_by
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
|
||||
|
||||
|
||||
protected $signature = 'snipeit:create-admin {--first_name=} {--last_name=} {--email=} {--username=} {--password=} {show_in_list?} {autoassign_licenses?}';
|
||||
protected $signature = 'snipeit:create-admin {--first_name=} {--last_name=} {--email=} {--username=} {--password=} {show_in_list?}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@@ -46,7 +30,11 @@ class CreateAdmin extends Command
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
$first_name = $this->option('first_name');
|
||||
@@ -55,14 +43,11 @@ class CreateAdmin extends Command
|
||||
$email = $this->option('email');
|
||||
$password = $this->option('password');
|
||||
$show_in_list = $this->argument('show_in_list');
|
||||
$autoassign_licenses = $this->argument('autoassign_licenses');
|
||||
|
||||
|
||||
|
||||
if (($first_name == '') || ($last_name == '') || ($username == '') || ($email == '') || ($password == '')) {
|
||||
$this->info('ERROR: All fields are required.');
|
||||
} else {
|
||||
$user = new User;
|
||||
$user = new \App\Models\User;
|
||||
$user->first_name = $first_name;
|
||||
$user->last_name = $last_name;
|
||||
$user->username = $username;
|
||||
@@ -74,11 +59,6 @@ class CreateAdmin extends Command
|
||||
if ($show_in_list == 'false') {
|
||||
$user->show_in_list = 0;
|
||||
}
|
||||
|
||||
if ($autoassign_licenses == 'false') {
|
||||
$user->autoassign_licenses = 0;
|
||||
}
|
||||
|
||||
if ($user->save()) {
|
||||
$this->info('New user created');
|
||||
$user->groups()->attach(1);
|
||||
|
||||
@@ -62,7 +62,6 @@ class LdapSync extends Command
|
||||
$ldap_result_phone = Setting::getSettings()->ldap_phone_field;
|
||||
$ldap_result_jobtitle = Setting::getSettings()->ldap_jobtitle;
|
||||
$ldap_result_country = Setting::getSettings()->ldap_country;
|
||||
$ldap_result_location = Setting::getSettings()->ldap_location;
|
||||
$ldap_result_dept = Setting::getSettings()->ldap_dept;
|
||||
$ldap_result_manager = Setting::getSettings()->ldap_manager;
|
||||
$ldap_default_group = Setting::getSettings()->ldap_default_group;
|
||||
@@ -75,7 +74,7 @@ class LdapSync extends Command
|
||||
$json_summary = ['error' => true, 'error_message' => $e->getMessage(), 'summary' => []];
|
||||
$this->info(json_encode($json_summary));
|
||||
}
|
||||
Log::info($e);
|
||||
LOG::info($e);
|
||||
|
||||
return [];
|
||||
}
|
||||
@@ -85,7 +84,7 @@ class LdapSync extends Command
|
||||
try {
|
||||
if ($this->option('base_dn') != '') {
|
||||
$search_base = $this->option('base_dn');
|
||||
Log::debug('Importing users from specified base DN: \"'.$search_base.'\".');
|
||||
LOG::debug('Importing users from specified base DN: \"'.$search_base.'\".');
|
||||
} else {
|
||||
$search_base = null;
|
||||
}
|
||||
@@ -99,7 +98,7 @@ class LdapSync extends Command
|
||||
$json_summary = ['error' => true, 'error_message' => $e->getMessage(), 'summary' => []];
|
||||
$this->info(json_encode($json_summary));
|
||||
}
|
||||
Log::info($e);
|
||||
LOG::info($e);
|
||||
|
||||
return [];
|
||||
}
|
||||
@@ -109,16 +108,16 @@ class LdapSync extends Command
|
||||
|
||||
if ($this->option('location') != '') {
|
||||
$location = Location::where('name', '=', $this->option('location'))->first();
|
||||
Log::debug('Location name '.$this->option('location').' passed');
|
||||
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||
LOG::debug('Location name '.$this->option('location').' passed');
|
||||
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||
} elseif ($this->option('location_id') != '') {
|
||||
$location = Location::where('id', '=', $this->option('location_id'))->first();
|
||||
Log::debug('Location ID '.$this->option('location_id').' passed');
|
||||
Log::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||
LOG::debug('Location ID '.$this->option('location_id').' passed');
|
||||
LOG::debug('Importing to '.$location->name.' ('.$location->id.')');
|
||||
}
|
||||
|
||||
if (! isset($location)) {
|
||||
Log::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
|
||||
LOG::debug('That location is invalid or a location was not provided, so no location will be assigned by default.');
|
||||
}
|
||||
|
||||
/* Process locations with explicitly defined OUs, if doing a full import. */
|
||||
@@ -134,7 +133,7 @@ class LdapSync extends Command
|
||||
array_multisort($ldap_ou_lengths, SORT_ASC, $ldap_ou_locations);
|
||||
|
||||
if (count($ldap_ou_locations) > 0) {
|
||||
Log::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.');
|
||||
LOG::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.');
|
||||
}
|
||||
|
||||
// Inject location information fields
|
||||
@@ -152,7 +151,7 @@ class LdapSync extends Command
|
||||
$json_summary = ['error' => true, 'error_message' => trans('admin/users/message.error.ldap_could_not_search').' Location: '.$ldap_loc['name'].' (ID: '.$ldap_loc['id'].') cannot connect to "'.$ldap_loc['ldap_ou'].'" - '.$e->getMessage(), 'summary' => []];
|
||||
$this->info(json_encode($json_summary));
|
||||
}
|
||||
Log::info($e);
|
||||
LOG::info($e);
|
||||
|
||||
return [];
|
||||
}
|
||||
@@ -198,26 +197,20 @@ class LdapSync extends Command
|
||||
|
||||
for ($i = 0; $i < $results['count']; $i++) {
|
||||
$item = [];
|
||||
$item['username'] = $results[$i][$ldap_result_username][0] ?? '';
|
||||
$item['employee_number'] = $results[$i][$ldap_result_emp_num][0] ?? '';
|
||||
$item['lastname'] = $results[$i][$ldap_result_last_name][0] ?? '';
|
||||
$item['firstname'] = $results[$i][$ldap_result_first_name][0] ?? '';
|
||||
$item['email'] = $results[$i][$ldap_result_email][0] ?? '';
|
||||
$item['ldap_location_override'] = $results[$i]['ldap_location_override'] ?? '';
|
||||
$item['location_id'] = $results[$i]['location_id'] ?? '';
|
||||
$item['telephone'] = $results[$i][$ldap_result_phone][0] ?? '';
|
||||
$item['jobtitle'] = $results[$i][$ldap_result_jobtitle][0] ?? '';
|
||||
$item['country'] = $results[$i][$ldap_result_country][0] ?? '';
|
||||
$item['department'] = $results[$i][$ldap_result_dept][0] ?? '';
|
||||
$item['manager'] = $results[$i][$ldap_result_manager][0] ?? '';
|
||||
$item['location'] = $results[$i][$ldap_result_location][0] ?? '';
|
||||
$item['username'] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : '';
|
||||
$item['employee_number'] = isset($results[$i][$ldap_result_emp_num][0]) ? $results[$i][$ldap_result_emp_num][0] : '';
|
||||
$item['lastname'] = isset($results[$i][$ldap_result_last_name][0]) ? $results[$i][$ldap_result_last_name][0] : '';
|
||||
$item['firstname'] = isset($results[$i][$ldap_result_first_name][0]) ? $results[$i][$ldap_result_first_name][0] : '';
|
||||
$item['email'] = isset($results[$i][$ldap_result_email][0]) ? $results[$i][$ldap_result_email][0] : '';
|
||||
$item['ldap_location_override'] = isset($results[$i]['ldap_location_override']) ? $results[$i]['ldap_location_override'] : '';
|
||||
$item['location_id'] = isset($results[$i]['location_id']) ? $results[$i]['location_id'] : '';
|
||||
$item['telephone'] = isset($results[$i][$ldap_result_phone][0]) ? $results[$i][$ldap_result_phone][0] : '';
|
||||
$item['jobtitle'] = isset($results[$i][$ldap_result_jobtitle][0]) ? $results[$i][$ldap_result_jobtitle][0] : '';
|
||||
$item['country'] = isset($results[$i][$ldap_result_country][0]) ? $results[$i][$ldap_result_country][0] : '';
|
||||
$item['department'] = isset($results[$i][$ldap_result_dept][0]) ? $results[$i][$ldap_result_dept][0] : '';
|
||||
$item['manager'] = isset($results[$i][$ldap_result_manager][0]) ? $results[$i][$ldap_result_manager][0] : '';
|
||||
|
||||
|
||||
// ONLY if you are using the "ldap_location" option *AND* you have an actual result
|
||||
if ($ldap_result_location && $item['location']) {
|
||||
$location = Location::firstOrCreate([
|
||||
'name' => $item['location'],
|
||||
]);
|
||||
}
|
||||
$department = Department::firstOrCreate([
|
||||
'name' => $item['department'],
|
||||
]);
|
||||
@@ -234,39 +227,16 @@ class LdapSync extends Command
|
||||
$item['createorupdate'] = 'created';
|
||||
}
|
||||
|
||||
//If a sync option is not filled in on the LDAP settings don't populate the user field
|
||||
if($ldap_result_username != null){
|
||||
$user->username = $item['username'];
|
||||
}
|
||||
if($ldap_result_last_name != null){
|
||||
$user->last_name = $item['lastname'];
|
||||
}
|
||||
if($ldap_result_first_name != null){
|
||||
$user->first_name = $item['firstname'];
|
||||
}
|
||||
if($ldap_result_emp_num != null){
|
||||
$user->employee_num = e($item['employee_number']);
|
||||
}
|
||||
if($ldap_result_email != null){
|
||||
$user->last_name = $item['lastname'];
|
||||
$user->username = $item['username'];
|
||||
$user->email = $item['email'];
|
||||
}
|
||||
if($ldap_result_phone != null){
|
||||
$user->employee_num = e($item['employee_number']);
|
||||
$user->phone = $item['telephone'];
|
||||
}
|
||||
if($ldap_result_jobtitle != null){
|
||||
$user->jobtitle = $item['jobtitle'];
|
||||
}
|
||||
if($ldap_result_country != null){
|
||||
$user->country = $item['country'];
|
||||
}
|
||||
if($ldap_result_dept != null){
|
||||
$user->department_id = $department->id;
|
||||
}
|
||||
if($ldap_result_location != null){
|
||||
$user->location_id = $location ? $location->id : null;
|
||||
}
|
||||
|
||||
if($ldap_result_manager != null){
|
||||
if($item['manager'] != null) {
|
||||
// Check Cache first
|
||||
if (isset($manager_cache[$item['manager']])) {
|
||||
@@ -306,7 +276,6 @@ class LdapSync extends Command
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Sync activated state for Active Directory.
|
||||
if ( !empty($ldap_result_active_flag)) { // IF we have an 'active' flag set....
|
||||
|
||||
@@ -1,52 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Models\User;
|
||||
|
||||
class NormalizeUserNames extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:normalize-names';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Normalizes weirdly formatted names as first-letter upercased';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$users = User::get();
|
||||
$this->info($users->count() . ' users');
|
||||
|
||||
foreach ($users as $user) {
|
||||
$user->first_name = ucwords(strtolower($user->first_name));
|
||||
$user->last_name = ucwords(strtolower($user->last_name));
|
||||
$user->email = strtolower($user->email);
|
||||
$user->save();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -11,7 +11,7 @@ class SystemBackup extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:backup {--filename=}';
|
||||
protected $name = 'snipeit:backup';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
@@ -37,18 +37,7 @@ class SystemBackup extends Command
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
if ($this->option('filename')) {
|
||||
$filename = $this->option('filename');
|
||||
|
||||
// Make sure the filename ends in .zip
|
||||
if (!ends_with($filename, '.zip')) {
|
||||
$filename = $filename.'.zip';
|
||||
}
|
||||
|
||||
$this->call('backup:run', ['--filename' => $filename]);
|
||||
} else {
|
||||
$this->call('backup:run');
|
||||
}
|
||||
|
||||
//
|
||||
$this->call('backup:run');
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,20 +15,18 @@ class CheckoutableCheckedIn
|
||||
public $checkedInBy;
|
||||
public $note;
|
||||
public $action_date; // Date setted in the hardware.checkin view at the checkin_at input, for the action log
|
||||
public $originalValues;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($checkoutable, $checkedOutTo, User $checkedInBy, $note, $action_date = null, $originalValues = [])
|
||||
public function __construct($checkoutable, $checkedOutTo, User $checkedInBy, $note, $action_date = null)
|
||||
{
|
||||
$this->checkoutable = $checkoutable;
|
||||
$this->checkedOutTo = $checkedOutTo;
|
||||
$this->checkedInBy = $checkedInBy;
|
||||
$this->note = $note;
|
||||
$this->action_date = $action_date ?? date('Y-m-d');
|
||||
$this->originalValues = $originalValues;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,19 +14,17 @@ class CheckoutableCheckedOut
|
||||
public $checkedOutTo;
|
||||
public $checkedOutBy;
|
||||
public $note;
|
||||
public $originalValues;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($checkoutable, $checkedOutTo, User $checkedOutBy, $note, $originalValues = [])
|
||||
public function __construct($checkoutable, $checkedOutTo, User $checkedOutBy, $note)
|
||||
{
|
||||
$this->checkoutable = $checkoutable;
|
||||
$this->checkedOutTo = $checkedOutTo;
|
||||
$this->checkedOutBy = $checkedOutBy;
|
||||
$this->note = $note;
|
||||
$this->originalValues = $originalValues;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,24 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
use App\Models\User;
|
||||
|
||||
class UserMerged
|
||||
{
|
||||
use Dispatchable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $from_user, User $to_user, User $admin)
|
||||
{
|
||||
$this->merged_from = $from_user;
|
||||
$this->merged_to = $to_user;
|
||||
$this->admin = $admin;
|
||||
}
|
||||
}
|
||||
@@ -6,11 +6,10 @@ use Illuminate\Foundation\Exceptions\Handler as ExceptionHandler;
|
||||
use App\Helpers\Helper;
|
||||
use Illuminate\Validation\ValidationException;
|
||||
use Illuminate\Auth\AuthenticationException;
|
||||
use ArieTimmerman\Laravel\SCIMServer\Exceptions\SCIMException;
|
||||
use Log;
|
||||
use Throwable;
|
||||
use JsonException;
|
||||
use Carbon\Exceptions\InvalidFormatException;
|
||||
|
||||
|
||||
class Handler extends ExceptionHandler
|
||||
{
|
||||
@@ -29,8 +28,6 @@ class Handler extends ExceptionHandler
|
||||
\Intervention\Image\Exception\NotSupportedException::class,
|
||||
\League\OAuth2\Server\Exception\OAuthServerException::class,
|
||||
JsonException::class,
|
||||
SCIMException::class, //these generally don't need to be reported
|
||||
InvalidFormatException::class,
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -44,9 +41,7 @@ class Handler extends ExceptionHandler
|
||||
public function report(Throwable $exception)
|
||||
{
|
||||
if ($this->shouldReport($exception)) {
|
||||
if (class_exists(\Log::class)) {
|
||||
\Log::error($exception);
|
||||
}
|
||||
\Log::error($exception);
|
||||
return parent::report($exception);
|
||||
}
|
||||
}
|
||||
@@ -56,7 +51,7 @@ class Handler extends ExceptionHandler
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Exception $e
|
||||
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse|\Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function render($request, Throwable $e)
|
||||
{
|
||||
@@ -70,39 +65,18 @@ class Handler extends ExceptionHandler
|
||||
// Invalid JSON exception
|
||||
// TODO: don't understand why we have to do this when we have the invalidJson() method, below, but, well, whatever
|
||||
if ($e instanceof JsonException) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Invalid JSON'), 422);
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'invalid JSON'), 422);
|
||||
}
|
||||
|
||||
// Handle SCIM exceptions
|
||||
if ($e instanceof SCIMException) {
|
||||
try {
|
||||
$e->report(); // logs as 'debug', so shouldn't get too noisy
|
||||
} catch(\Exception $reportException) {
|
||||
//do nothing
|
||||
}
|
||||
return $e->render($request); // ALL SCIMExceptions have the 'render()' method
|
||||
}
|
||||
|
||||
// Handle standard requests that fail because Carbon cannot parse the date on validation (when a submitted date value is definitely not a date)
|
||||
if ($e instanceof InvalidFormatException) {
|
||||
return redirect()->back()->withInput()->with('error', trans('validation.date', ['attribute' => 'date']));
|
||||
}
|
||||
|
||||
// Handle API requests that fail
|
||||
// Handle Ajax requests that fail because the model doesn't exist
|
||||
if ($request->ajax() || $request->wantsJson()) {
|
||||
|
||||
// Handle API requests that fail because Carbon cannot parse the date on validation (when a submitted date value is definitely not a date)
|
||||
if ($e instanceof InvalidFormatException) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('validation.date', ['attribute' => 'date'])), 200);
|
||||
}
|
||||
|
||||
// Handle API requests that fail because the model doesn't exist
|
||||
if ($e instanceof \Illuminate\Database\Eloquent\ModelNotFoundException) {
|
||||
$className = last(explode('\\', $e->getModel()));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $className . ' not found'), 200);
|
||||
}
|
||||
|
||||
// Handle API requests that fail because of an HTTP status code and return a useful error message
|
||||
if ($this->isHttpException($e)) {
|
||||
|
||||
$statusCode = $e->getStatusCode();
|
||||
@@ -122,8 +96,6 @@ class Handler extends ExceptionHandler
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
if ($this->isHttpException($e) && (isset($statusCode)) && ($statusCode == '404' )) {
|
||||
return response()->view('layouts/basic', [
|
||||
'content' => view('errors/404')
|
||||
@@ -139,8 +111,8 @@ class Handler extends ExceptionHandler
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param \Illuminate\Auth\AuthenticationException $exception
|
||||
* @return \Illuminate\Http\JsonResponse|\Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
protected function unauthenticated($request, AuthenticationException $exception)
|
||||
{
|
||||
if ($request->expectsJson()) {
|
||||
|
||||
@@ -1,77 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Helpers;
|
||||
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
/*********************
|
||||
* These two helper methods are more designed for being re-used with the new HasCustomFields Trait
|
||||
*
|
||||
* The 'transform' method is designed for BlahTransformer things that need to return custom field values.
|
||||
*
|
||||
* The 'present' method is designed for when you're trying to generate fieldlists for use in Bootstrap tables
|
||||
* - typically the 'dataTableLayout' method
|
||||
*
|
||||
*********************/
|
||||
class CustomFieldHelper {
|
||||
|
||||
static function transform($fieldset, $item) {
|
||||
if ($fieldset && ($fieldset->fields->count() > 0)) {
|
||||
$fields_array = [];
|
||||
|
||||
foreach ($fieldset->fields as $field) {
|
||||
if ($field->isFieldDecryptable($item->{$field->db_column})) {
|
||||
$decrypted = Helper::gracefulDecrypt($field, $item->{$field->db_column});
|
||||
$value = (Gate::allows('assets.view.encrypted_custom_fields')) ? $decrypted : strtoupper(trans('admin/custom_fields/general.encrypted'));
|
||||
|
||||
if ($field->format == 'DATE'){
|
||||
if (Gate::allows('assets.view.encrypted_custom_fields')){
|
||||
$value = Helper::getFormattedDateObject($value, 'date', false);
|
||||
} else {
|
||||
$value = strtoupper(trans('admin/custom_fields/general.encrypted'));
|
||||
}
|
||||
}
|
||||
|
||||
$fields_array[$field->name] = [
|
||||
'field' => e($field->db_column),
|
||||
'value' => e($value),
|
||||
'field_format' => $field->format,
|
||||
'element' => $field->element,
|
||||
];
|
||||
|
||||
} else {
|
||||
$value = $item->{$field->db_column};
|
||||
|
||||
if (($field->format == 'DATE') && (!is_null($value)) && ($value!='')){
|
||||
$value = Helper::getFormattedDateObject($value, 'date', false);
|
||||
}
|
||||
|
||||
$fields_array[$field->name] = [
|
||||
'field' => e($field->db_column),
|
||||
'value' => e($value),
|
||||
'field_format' => $field->format,
|
||||
'element' => $field->element,
|
||||
];
|
||||
}
|
||||
|
||||
return $fields_array;
|
||||
}
|
||||
} else {
|
||||
return new \stdClass; // HACK to force generation of empty object instead of empty list
|
||||
}
|
||||
}
|
||||
|
||||
static function present($field) {
|
||||
return [
|
||||
'field' => 'custom_fields.'.$field->db_column,
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => $field->name,
|
||||
'formatter'=> 'customFieldsFormatter',
|
||||
'escape' => true,
|
||||
'class' => ($field->field_encrypted == '1') ? 'css-padlock' : '',
|
||||
'visible' => ($field->show_in_listview == '1') ? true : false,
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Helpers;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Component;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\CustomField;
|
||||
@@ -35,16 +33,6 @@ class Helper
|
||||
}
|
||||
}
|
||||
|
||||
public static function parseEscapedMarkedownInline($str = null)
|
||||
{
|
||||
$Parsedown = new \Parsedown();
|
||||
$Parsedown->setSafeMode(true);
|
||||
|
||||
if ($str) {
|
||||
return $Parsedown->line($str);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The importer has formatted number strings since v3,
|
||||
* so the value might be a string, or an integer.
|
||||
@@ -346,11 +334,7 @@ class Helper
|
||||
'#92896B',
|
||||
];
|
||||
|
||||
$total_colors = count($colors);
|
||||
|
||||
if ($index >= $total_colors) {
|
||||
$index = $index - $total_colors;
|
||||
}
|
||||
|
||||
return $colors[$index];
|
||||
}
|
||||
@@ -544,23 +528,20 @@ class Helper
|
||||
* @since [v2.5]
|
||||
* @return array
|
||||
*/
|
||||
public static function categoryTypeList($selection=null)
|
||||
public static function categoryTypeList()
|
||||
{
|
||||
$category_types = [
|
||||
'' => '',
|
||||
'accessory' => trans('general.accessory'),
|
||||
'asset' => trans('general.asset'),
|
||||
'consumable' => trans('general.consumable'),
|
||||
'component' => trans('general.component'),
|
||||
'license' => trans('general.license'),
|
||||
'accessory' => 'Accessory',
|
||||
'asset' => 'Asset',
|
||||
'consumable' => 'Consumable',
|
||||
'component' => 'Component',
|
||||
'license' => 'License',
|
||||
];
|
||||
|
||||
if ($selection != null){
|
||||
return $category_types[strtolower($selection)];
|
||||
}
|
||||
else
|
||||
return $category_types;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the list of custom fields in an array to make a dropdown menu
|
||||
*
|
||||
@@ -575,17 +556,6 @@ class Helper
|
||||
return $customfields;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all of the different types of custom fields there are
|
||||
* TODO - how to make this more general? Or more useful? or more dynamic?
|
||||
* idea - key of classname, *value* of trans? (thus having to make this a method, which is fine)
|
||||
*/
|
||||
static $itemtypes_having_custom_fields = [
|
||||
0 => \App\Models\Asset::class,
|
||||
1 => \App\Models\User::class,
|
||||
// 2 => \App\Models\Accessory::class
|
||||
];
|
||||
|
||||
/**
|
||||
* Get the list of custom field formats in an array to make a dropdown menu
|
||||
*
|
||||
@@ -656,7 +626,6 @@ class Helper
|
||||
$consumables = Consumable::withCount('consumableAssignments as consumable_assignments_count')->whereNotNull('min_amt')->get();
|
||||
$accessories = Accessory::withCount('users as users_count')->whereNotNull('min_amt')->get();
|
||||
$components = Component::whereNotNull('min_amt')->get();
|
||||
$asset_models = AssetModel::where('min_amt', '>', 0)->get();
|
||||
|
||||
$avail_consumables = 0;
|
||||
$items_array = [];
|
||||
@@ -719,28 +688,6 @@ class Helper
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($asset_models as $asset_model){
|
||||
|
||||
$asset = new Asset();
|
||||
$total_owned = $asset->where('model_id', '=', $asset_model->id)->count();
|
||||
$avail = $asset->where('model_id', '=', $asset_model->id)->whereNull('assigned_to')->count();
|
||||
|
||||
if ($avail < ($asset_model->min_amt)+ \App\Models\Setting::getSettings()->alert_threshold) {
|
||||
if ($avail > 0) {
|
||||
$percent = number_format((($avail / $total_owned) * 100), 0);
|
||||
} else {
|
||||
$percent = 100;
|
||||
}
|
||||
$items_array[$all_count]['id'] = $asset_model->id;
|
||||
$items_array[$all_count]['name'] = $asset_model->name;
|
||||
$items_array[$all_count]['type'] = 'models';
|
||||
$items_array[$all_count]['percent'] = $percent;
|
||||
$items_array[$all_count]['remaining'] = $avail;
|
||||
$items_array[$all_count]['min_amt'] = $asset_model->min_amt;
|
||||
$all_count++;
|
||||
}
|
||||
}
|
||||
|
||||
return $items_array;
|
||||
}
|
||||
|
||||
@@ -1145,15 +1092,6 @@ class Helper
|
||||
return $file_name;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Universal helper to show file size in human-readable formats
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since 5.0
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function formatFilesizeUnits($bytes)
|
||||
{
|
||||
if ($bytes >= 1073741824)
|
||||
@@ -1183,141 +1121,30 @@ class Helper
|
||||
|
||||
return $bytes;
|
||||
}
|
||||
|
||||
/**
|
||||
* This is weird but used by the side nav to determine which URL to point the user to
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since 5.0
|
||||
*
|
||||
* @return string[]
|
||||
*/
|
||||
public static function SettingUrls(){
|
||||
$settings=['#','fields.index', 'statuslabels.index', 'models.index', 'categories.index', 'manufacturers.index', 'suppliers.index', 'departments.index', 'locations.index', 'companies.index', 'depreciations.index'];
|
||||
|
||||
return $settings;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Generic helper (largely used by livewire right now) that returns the font-awesome icon
|
||||
* for the object type.
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since 6.1.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function iconTypeByItem($item) {
|
||||
|
||||
switch ($item) {
|
||||
case 'asset':
|
||||
return 'fas fa-barcode';
|
||||
break;
|
||||
case 'accessory':
|
||||
return 'fas fa-keyboard';
|
||||
break;
|
||||
case 'component':
|
||||
return 'fas fa-hdd';
|
||||
break;
|
||||
case 'consumable':
|
||||
return 'fas fa-tint';
|
||||
break;
|
||||
case 'license':
|
||||
return 'far fa-save';
|
||||
break;
|
||||
case 'location':
|
||||
return 'fas fa-map-marker-alt';
|
||||
break;
|
||||
case 'user':
|
||||
return 'fas fa-user';
|
||||
break;
|
||||
public static function AgeFormat($date) {
|
||||
$year = Carbon::parse($date)
|
||||
->diff(now())->y;
|
||||
$month = Carbon::parse($date)
|
||||
->diff(now())->m;
|
||||
$days = Carbon::parse($date)
|
||||
->diff(now())->d;
|
||||
$age='';
|
||||
if ($year) {
|
||||
$age .= $year.'y ';
|
||||
}
|
||||
if ($month) {
|
||||
$age .= $month.'m ';
|
||||
}
|
||||
if ($days) {
|
||||
$age .= $days.'d';
|
||||
}
|
||||
|
||||
}
|
||||
return $age;
|
||||
|
||||
|
||||
/*
|
||||
* This is a shorter way to see if the app is in demo mode.
|
||||
*
|
||||
* This makes it cleanly available in blades and in controllers, e.g.
|
||||
*
|
||||
* Blade:
|
||||
* {{ Helper::isDemoMode() ? ' disabled' : ''}} for form blades where we need to disable a form
|
||||
*
|
||||
* Controller:
|
||||
* if (Helper::isDemoMode()) {
|
||||
* // don't allow the thing
|
||||
* }
|
||||
* @todo - use this everywhere else in the app where we have very long if/else config('app.lock_passwords') stuff
|
||||
*/
|
||||
public static function isDemoMode() {
|
||||
if (config('app.lock_passwords') === true) {
|
||||
return true;
|
||||
\Log::debug('app locked!');
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Conversion between units of measurement
|
||||
*
|
||||
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
|
||||
* @since 5.0
|
||||
* @param float $value Measurement value to convert
|
||||
* @param string $srcUnit Source unit of measurement
|
||||
* @param string $dstUnit Destination unit of measurement
|
||||
* @param int $round Round the result to decimals (Default false - No rounding)
|
||||
* @return float
|
||||
*/
|
||||
public static function convertUnit($value, $srcUnit, $dstUnit, $round=false) {
|
||||
$srcFactor = static::getUnitConversionFactor($srcUnit);
|
||||
$dstFactor = static::getUnitConversionFactor($dstUnit);
|
||||
$output = $value * $srcFactor / $dstFactor;
|
||||
return ($round !== false) ? round($output, $round) : $output;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get conversion factor from unit of measurement to mm
|
||||
*
|
||||
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
|
||||
* @since 5.0
|
||||
* @param string $unit Unit of measurement
|
||||
* @return float
|
||||
*/
|
||||
public static function getUnitConversionFactor($unit) {
|
||||
switch (strtolower($unit)) {
|
||||
case 'mm':
|
||||
return 1.0;
|
||||
case 'cm':
|
||||
return 10.0;
|
||||
case 'm':
|
||||
return 1000.0;
|
||||
case 'in':
|
||||
return 25.4;
|
||||
case 'ft':
|
||||
return 12 * static::getUnitConversionFactor('in');
|
||||
case 'yd':
|
||||
return 3 * static::getUnitConversionFactor('ft');
|
||||
case 'pt':
|
||||
return (1 / 72) * static::getUnitConversionFactor('in');
|
||||
default:
|
||||
throw new \InvalidArgumentException('Unit: \'' . $unit . '\' is not supported');
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
* I know it's gauche to return a shitty HTML string, but this is just a helper and since it will be the same every single time,
|
||||
* it seemed pretty safe to do here. Don't you judge me.
|
||||
*/
|
||||
public static function showDemoModeFieldWarning() {
|
||||
if (Helper::isDemoMode()) {
|
||||
return "<p class=\"text-warning\"><i class=\"fas fa-lock\"></i>" . trans('general.feature_disabled') . "</p>";
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,7 +77,7 @@ class AccessoriesController extends Controller
|
||||
$accessory->manufacturer_id = request('manufacturer_id');
|
||||
$accessory->model_number = request('model_number');
|
||||
$accessory->purchase_date = request('purchase_date');
|
||||
$accessory->purchase_cost = request('purchase_cost');
|
||||
$accessory->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->user_id = Auth::user()->id;
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
@@ -115,34 +115,6 @@ class AccessoriesController extends Controller
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view that presents a form to clone an accessory.
|
||||
*
|
||||
* @author [J. Vinsmoke]
|
||||
* @param int $accessoryId
|
||||
* @since [v6.0]
|
||||
* @return View
|
||||
*/
|
||||
public function getClone($accessoryId = null)
|
||||
{
|
||||
|
||||
$this->authorize('create', Accessory::class);
|
||||
|
||||
// Check if the asset exists
|
||||
if (is_null($accessory_to_clone = Accessory::find($accessoryId))) {
|
||||
// Redirect to the asset management page
|
||||
return redirect()->route('accessories.index')
|
||||
->with('error', trans('admin/accessories/message.does_not_exist', ['id' => $accessoryId]));
|
||||
}
|
||||
|
||||
$accessory = clone $accessory_to_clone;
|
||||
$accessory->id = null;
|
||||
$accessory->location_id = null;
|
||||
|
||||
return view('accessories/edit')
|
||||
->with('item', $accessory);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Save edited Accessory from form post
|
||||
@@ -181,7 +153,7 @@ class AccessoriesController extends Controller
|
||||
$accessory->order_number = request('order_number');
|
||||
$accessory->model_number = request('model_number');
|
||||
$accessory->purchase_date = request('purchase_date');
|
||||
$accessory->purchase_cost = request('purchase_cost');
|
||||
$accessory->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
$accessory->notes = request('notes');
|
||||
|
||||
@@ -161,19 +161,22 @@ class AccessoriesFilesController extends Controller
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
|
||||
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
|
||||
// won't work, as they're not accessible via the web
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
} else {
|
||||
if ($download != 'true') {
|
||||
\Log::debug('display the file');
|
||||
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
|
||||
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
|
||||
}
|
||||
|
||||
return JsonResponse::create(['error' => 'Failed validation: '], 500);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,16 +25,11 @@ class AccessoryCheckoutController extends Controller
|
||||
public function create($accessoryId)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory = Accessory::withCount('users as users_count')->find($accessoryId))) {
|
||||
if (is_null($accessory = Accessory::find($accessoryId))) {
|
||||
// Redirect to the accessory management page with error
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
|
||||
}
|
||||
|
||||
// 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'));
|
||||
}
|
||||
|
||||
if ($accessory->category) {
|
||||
$this->authorize('checkout', $accessory);
|
||||
|
||||
@@ -60,23 +55,17 @@ class AccessoryCheckoutController extends Controller
|
||||
public function store(Request $request, $accessoryId)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory = Accessory::withCount('users as users_count')->find($accessoryId))) {
|
||||
if (is_null($accessory = Accessory::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);
|
||||
|
||||
if (!$user = User::find($request->input('assigned_to'))) {
|
||||
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'));
|
||||
}
|
||||
|
||||
// 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'));
|
||||
|
||||
|
||||
@@ -69,7 +69,7 @@ class AcceptanceController extends Controller
|
||||
}
|
||||
|
||||
if (! Company::isCurrentUserHasAccess($acceptance->checkoutable)) {
|
||||
return redirect()->route('account.accept')->with('error', trans('general.error_user_company'));
|
||||
return redirect()->route('account.accept')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
return view('account/accept.create', compact('acceptance'));
|
||||
@@ -121,6 +121,7 @@ class AcceptanceController extends Controller
|
||||
$pdf_filename = 'accepted-eula-'.date('Y-m-d-h-i-s').'.pdf';
|
||||
$sig_filename='';
|
||||
|
||||
|
||||
if ($request->input('asset_acceptance') == 'accepted') {
|
||||
|
||||
/**
|
||||
@@ -152,14 +153,12 @@ class AcceptanceController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// this is horrible
|
||||
switch($acceptance->checkoutable_type){
|
||||
case 'App\Models\Asset':
|
||||
$pdf_view_route ='account.accept.accept-asset-eula';
|
||||
$asset_model = AssetModel::find($item->model_id);
|
||||
if (!$asset_model) {
|
||||
return redirect()->back()->with('error', trans('admin/models/message.does_not_exist'));
|
||||
}
|
||||
$display_model = $asset_model->name;
|
||||
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
||||
break;
|
||||
@@ -168,7 +167,7 @@ class AcceptanceController extends Controller
|
||||
$pdf_view_route ='account.accept.accept-accessory-eula';
|
||||
$accessory = Accessory::find($item->id);
|
||||
$display_model = $accessory->name;
|
||||
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
||||
$assigned_to = User::find($item->assignedTo);
|
||||
break;
|
||||
|
||||
case 'App\Models\LicenseSeat':
|
||||
@@ -245,51 +244,17 @@ class AcceptanceController extends Controller
|
||||
$return_msg = trans('admin/users/message.accepted');
|
||||
|
||||
} else {
|
||||
|
||||
/**
|
||||
* Check for the eula-pdfs directory
|
||||
*/
|
||||
if (! Storage::exists('private_uploads/eula-pdfs')) {
|
||||
Storage::makeDirectory('private_uploads/eula-pdfs', 775);
|
||||
}
|
||||
|
||||
if (Setting::getSettings()->require_accept_signature == '1') {
|
||||
|
||||
// Check if the signature directory exists, if not create it
|
||||
if (!Storage::exists('private_uploads/signatures')) {
|
||||
Storage::makeDirectory('private_uploads/signatures', 775);
|
||||
}
|
||||
|
||||
// The item was accepted, check for a signature
|
||||
if ($request->filled('signature_output')) {
|
||||
$sig_filename = 'siglog-' . Str::uuid() . '-' . date('Y-m-d-his') . '.png';
|
||||
$data_uri = $request->input('signature_output');
|
||||
$encoded_image = explode(',', $data_uri);
|
||||
$decoded_image = base64_decode($encoded_image[1]);
|
||||
Storage::put('private_uploads/signatures/' . $sig_filename, (string)$decoded_image);
|
||||
|
||||
// No image data is present, kick them back.
|
||||
// This mostly only applies to users on super-duper crapola browsers *cough* IE *cough*
|
||||
} else {
|
||||
return redirect()->back()->with('error', trans('general.shitty_browser'));
|
||||
}
|
||||
}
|
||||
|
||||
// Format the data to send the declined notification
|
||||
$branding_settings = SettingsController::getPDFBranding();
|
||||
|
||||
// This is the most horriblest
|
||||
switch($acceptance->checkoutable_type){
|
||||
case 'App\Models\Asset':
|
||||
$asset_model = AssetModel::find($item->model_id);
|
||||
$display_model = $asset_model->name;
|
||||
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
||||
break;
|
||||
|
||||
case 'App\Models\Accessory':
|
||||
$accessory = Accessory::find($item->id);
|
||||
$display_model = $accessory->name;
|
||||
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
||||
$assigned_to = User::find($item->assignedTo);
|
||||
break;
|
||||
|
||||
case 'App\Models\LicenseSeat':
|
||||
@@ -301,8 +266,6 @@ class AcceptanceController extends Controller
|
||||
break;
|
||||
|
||||
case 'App\Models\Consumable':
|
||||
$consumable = Consumable::find($item->id);
|
||||
$display_model = $consumable->name;
|
||||
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
||||
break;
|
||||
}
|
||||
@@ -311,18 +274,11 @@ class AcceptanceController extends Controller
|
||||
'item_model' => $display_model,
|
||||
'item_serial' => $item->serial,
|
||||
'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,
|
||||
'company_name' => $branding_settings->site_name,
|
||||
'date_settings' => $branding_settings->date_display_format,
|
||||
];
|
||||
|
||||
if ($pdf_view_route!='') {
|
||||
\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->notify(new AcceptanceAssetDeclinedNotification($data));
|
||||
event(new CheckoutDeclined($acceptance));
|
||||
@@ -333,4 +289,4 @@ class AcceptanceController extends Controller
|
||||
return redirect()->to('account/accept')->with('success', $return_msg);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -26,10 +26,7 @@ class AccessoriesController extends Controller
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
if ($request->user()->cannot('reports.view')) {
|
||||
$this->authorize('view', Accessory::class);
|
||||
}
|
||||
|
||||
$this->authorize('view', Accessory::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.
|
||||
@@ -80,9 +77,12 @@ class AccessoriesController extends Controller
|
||||
$accessories->where('notes','=',$request->input('notes'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $accessories->count()) ? $accessories->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($accessories) && ($request->get('offset') > $accessories->count())) ? $accessories->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort_override = $request->input('sort');
|
||||
@@ -150,7 +150,7 @@ class AccessoriesController extends Controller
|
||||
public function show($id)
|
||||
{
|
||||
$this->authorize('view', Accessory::class);
|
||||
$accessory = Accessory::withCount('users as users_count')->findOrFail($id);
|
||||
$accessory = Accessory::findOrFail($id);
|
||||
|
||||
return (new AccessoriesTransformer)->transformAccessory($accessory);
|
||||
}
|
||||
@@ -331,7 +331,7 @@ class AccessoriesController extends Controller
|
||||
$accessory = Accessory::find($accessory_user->accessory_id);
|
||||
$this->authorize('checkin', $accessory);
|
||||
|
||||
$logaction = $accessory->logCheckin(User::find($accessory_user->assigned_to), $request->input('note'));
|
||||
$logaction = $accessory->logCheckin(User::find($accessory_user->user_id), $request->input('note'));
|
||||
|
||||
// Was the accessory updated?
|
||||
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
|
||||
|
||||
@@ -36,7 +36,7 @@ class AssetMaintenancesController extends Controller
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
$maintenances = AssetMaintenance::select('asset_maintenances.*')->with('asset', 'asset.model', 'asset.location', 'asset.defaultLoc', 'supplier', 'asset.company', 'admin');
|
||||
$maintenances = AssetMaintenance::select('asset_maintenances.*')->with('asset', 'asset.model', 'asset.location', 'supplier', 'asset.company', 'admin');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$maintenances = $maintenances->TextSearch($request->input('search'));
|
||||
@@ -55,9 +55,12 @@ class AssetMaintenancesController extends Controller
|
||||
}
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $maintenances->count()) ? $maintenances->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($maintenances) && ($request->get('offset') > $maintenances->count())) ? $maintenances->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
@@ -71,8 +74,7 @@ class AssetMaintenancesController extends Controller
|
||||
'asset_tag',
|
||||
'asset_name',
|
||||
'user_id',
|
||||
'supplier',
|
||||
'is_warranty',
|
||||
'supplier'
|
||||
];
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
||||
@@ -119,7 +121,7 @@ class AssetMaintenancesController extends Controller
|
||||
$assetMaintenance = new AssetMaintenance();
|
||||
$assetMaintenance->supplier_id = $request->input('supplier_id');
|
||||
$assetMaintenance->is_warranty = $request->input('is_warranty');
|
||||
$assetMaintenance->cost = $request->input('cost');
|
||||
$assetMaintenance->cost = Helper::ParseCurrency($request->input('cost'));
|
||||
$assetMaintenance->notes = e($request->input('notes'));
|
||||
$asset = Asset::find(e($request->input('asset_id')));
|
||||
|
||||
@@ -176,7 +178,7 @@ class AssetMaintenancesController extends Controller
|
||||
|
||||
$assetMaintenance->supplier_id = e($request->input('supplier_id'));
|
||||
$assetMaintenance->is_warranty = e($request->input('is_warranty'));
|
||||
$assetMaintenance->cost = $request->input('cost');
|
||||
$assetMaintenance->cost = Helper::ParseCurrency($request->input('cost'));
|
||||
$assetMaintenance->notes = e($request->input('notes'));
|
||||
|
||||
$asset = Asset::find(request('asset_id'));
|
||||
|
||||
@@ -38,7 +38,6 @@ class AssetModelsController extends Controller
|
||||
'image',
|
||||
'name',
|
||||
'model_number',
|
||||
'min_amt',
|
||||
'eol',
|
||||
'notes',
|
||||
'created_at',
|
||||
@@ -53,7 +52,6 @@ class AssetModelsController extends Controller
|
||||
'models.image',
|
||||
'models.name',
|
||||
'model_number',
|
||||
'min_amt',
|
||||
'eol',
|
||||
'requestable',
|
||||
'models.notes',
|
||||
@@ -65,7 +63,7 @@ class AssetModelsController extends Controller
|
||||
'models.deleted_at',
|
||||
'models.updated_at',
|
||||
])
|
||||
->with('category', 'depreciation', 'manufacturer')
|
||||
->with('category', 'depreciation', 'manufacturer', 'fieldset')
|
||||
->withCount('assets as assets_count');
|
||||
|
||||
if ($request->input('status')=='deleted') {
|
||||
@@ -80,9 +78,12 @@ class AssetModelsController extends Controller
|
||||
$assetmodels->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $assetmodels->count()) ? $assetmodels->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($assetmodels) && ($request->get('offset') > $assetmodels->count())) ? $assetmodels->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'models.created_at';
|
||||
|
||||
@@ -101,7 +101,6 @@ class AssetsController extends Controller
|
||||
'checkin_counter',
|
||||
'requests_counter',
|
||||
'byod',
|
||||
'asset_eol_date',
|
||||
];
|
||||
|
||||
$filter = [];
|
||||
@@ -110,12 +109,12 @@ class AssetsController extends Controller
|
||||
$filter = json_decode($request->input('filter'), true);
|
||||
}
|
||||
|
||||
$all_custom_fields = CustomField::where('type', Asset::class); //used as a 'cache' of custom fields throughout this page load
|
||||
$all_custom_fields = CustomField::all(); //used as a 'cache' of custom fields throughout this page load
|
||||
foreach ($all_custom_fields as $field) {
|
||||
$allowed_columns[] = $field->db_column_name();
|
||||
}
|
||||
|
||||
$assets = Asset::select('assets.*')
|
||||
$assets = Company::scopeCompanyables(Asset::select('assets.*'), 'company_id', 'assets')
|
||||
->with('location', 'assetstatus', 'company', 'defaultLoc','assignedTo',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset','supplier'); //it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
|
||||
|
||||
@@ -125,12 +124,11 @@ class AssetsController extends Controller
|
||||
$assets->InModelList($non_deprecable_models->toArray());
|
||||
}
|
||||
|
||||
|
||||
|
||||
// These are used by the API to query against specific ID numbers.
|
||||
// They are also used by the individual searches on detail pages like
|
||||
// locations, etc.
|
||||
|
||||
|
||||
// Search custom fields by column name
|
||||
foreach ($all_custom_fields as $field) {
|
||||
if ($request->filled($field->db_column_name())) {
|
||||
@@ -138,12 +136,76 @@ class AssetsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
if ((! is_null($filter)) && (count($filter)) > 0) {
|
||||
$assets->ByFilter($filter);
|
||||
} elseif ($request->filled('search')) {
|
||||
$assets->TextSearch($request->input('search'));
|
||||
|
||||
if ($request->filled('status_id')) {
|
||||
$assets->where('assets.status_id', '=', $request->input('status_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('asset_tag')) {
|
||||
$assets->where('assets.asset_tag', '=', $request->input('asset_tag'));
|
||||
}
|
||||
|
||||
if ($request->filled('serial')) {
|
||||
$assets->where('assets.serial', '=', $request->input('serial'));
|
||||
}
|
||||
|
||||
if ($request->input('requestable') == 'true') {
|
||||
$assets->where('assets.requestable', '=', '1');
|
||||
}
|
||||
|
||||
if ($request->filled('model_id')) {
|
||||
$assets->InModelList([$request->input('model_id')]);
|
||||
}
|
||||
|
||||
if ($request->filled('category_id')) {
|
||||
$assets->InCategory($request->input('category_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
$assets->where('assets.location_id', '=', $request->input('location_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('rtd_location_id')) {
|
||||
$assets->where('assets.rtd_location_id', '=', $request->input('rtd_location_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('supplier_id')) {
|
||||
$assets->where('assets.supplier_id', '=', $request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if (($request->filled('assigned_to')) && ($request->filled('assigned_type'))) {
|
||||
$assets->where('assets.assigned_to', '=', $request->input('assigned_to'))
|
||||
->where('assets.assigned_type', '=', $request->input('assigned_type'));
|
||||
}
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
$assets->where('assets.company_id', '=', $request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('manufacturer_id')) {
|
||||
$assets->ByManufacturer($request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('depreciation_id')) {
|
||||
$assets->ByDepreciationId($request->input('depreciation_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('byod')) {
|
||||
$assets->where('assets.byod', '=', $request->input('byod'));
|
||||
}
|
||||
|
||||
$request->filled('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
|
||||
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($assets) && ($request->get('offset') > $assets->count())) ? $assets->count() : $request->get('offset', 0);
|
||||
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
// This is used by the audit reporting routes
|
||||
if (Gate::allows('audit', Asset::class)) {
|
||||
switch ($audit) {
|
||||
@@ -157,6 +219,7 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
|
||||
// This is used by the sidenav, mostly
|
||||
|
||||
// We switched from using query scopes here because of a Laravel bug
|
||||
@@ -206,7 +269,7 @@ class AssetsController extends Controller
|
||||
break;
|
||||
case 'Deployed':
|
||||
// more sad, horrible workarounds for laravel bugs when doing full text searches
|
||||
$assets->whereNotNull('assets.assigned_to');
|
||||
$assets->where('assets.assigned_to', '>', '0');
|
||||
break;
|
||||
case 'byod':
|
||||
// This is kind of redundant, since we already check for byod=1 above, but this keeps the
|
||||
@@ -232,71 +295,12 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
// Leave these under the TextSearch scope, else the fuzziness will override the specific ID (status ID, etc) requested
|
||||
if ($request->filled('status_id')) {
|
||||
$assets->where('assets.status_id', '=', $request->input('status_id'));
|
||||
if ((! is_null($filter)) && (count($filter)) > 0) {
|
||||
$assets->ByFilter($filter);
|
||||
} elseif ($request->filled('search')) {
|
||||
$assets->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
if ($request->filled('asset_tag')) {
|
||||
$assets->where('assets.asset_tag', '=', $request->input('asset_tag'));
|
||||
}
|
||||
|
||||
if ($request->filled('serial')) {
|
||||
$assets->where('assets.serial', '=', $request->input('serial'));
|
||||
}
|
||||
|
||||
if ($request->input('requestable') == 'true') {
|
||||
$assets->where('assets.requestable', '=', '1');
|
||||
}
|
||||
|
||||
if ($request->filled('model_id')) {
|
||||
$assets->InModelList([$request->input('model_id')]);
|
||||
}
|
||||
|
||||
if ($request->filled('category_id')) {
|
||||
$assets->InCategory($request->input('category_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
$assets->where('assets.location_id', '=', $request->input('location_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('rtd_location_id')) {
|
||||
$assets->where('assets.rtd_location_id', '=', $request->input('rtd_location_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('supplier_id')) {
|
||||
$assets->where('assets.supplier_id', '=', $request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('asset_eol_date')) {
|
||||
$assets->where('assets.asset_eol_date', '=', $request->input('asset_eol_date'));
|
||||
}
|
||||
|
||||
if (($request->filled('assigned_to')) && ($request->filled('assigned_type'))) {
|
||||
$assets->where('assets.assigned_to', '=', $request->input('assigned_to'))
|
||||
->where('assets.assigned_type', '=', $request->input('assigned_type'));
|
||||
}
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
$assets->where('assets.company_id', '=', $request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('manufacturer_id')) {
|
||||
$assets->ByManufacturer($request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('depreciation_id')) {
|
||||
$assets->ByDepreciationId($request->input('depreciation_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('byod')) {
|
||||
$assets->where('assets.byod', '=', $request->input('byod'));
|
||||
}
|
||||
|
||||
if ($request->filled('order_number')) {
|
||||
$assets->where('assets.order_number', '=', $request->get('order_number'));
|
||||
}
|
||||
|
||||
// This is kinda gross, but we need to do this because the Bootstrap Tables
|
||||
// API passes custom field ordering as custom_fields.fieldname, and we have to strip
|
||||
@@ -307,8 +311,7 @@ class AssetsController extends Controller
|
||||
// in the allowed_columns array)
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'assets.created_at';
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
|
||||
switch ($sort_override) {
|
||||
case 'model':
|
||||
$assets->OrderModels($order);
|
||||
@@ -345,10 +348,6 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $assets->count()) ? $assets->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$total = $assets->count();
|
||||
$assets = $assets->skip($offset)->take($limit)->get();
|
||||
|
||||
@@ -461,7 +460,7 @@ class AssetsController extends Controller
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
$this->authorize('view', License::class);
|
||||
$asset = Asset::where('id', $id)->withTrashed()->firstorfail();
|
||||
$asset = Asset::where('id', $id)->withTrashed()->first();
|
||||
$licenses = $asset->licenses()->get();
|
||||
|
||||
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
|
||||
@@ -479,7 +478,7 @@ class AssetsController extends Controller
|
||||
public function selectlist(Request $request)
|
||||
{
|
||||
|
||||
$assets = Asset::select([
|
||||
$assets = Company::scopeCompanyables(Asset::select([
|
||||
'assets.id',
|
||||
'assets.name',
|
||||
'assets.asset_tag',
|
||||
@@ -487,7 +486,7 @@ class AssetsController extends Controller
|
||||
'assets.assigned_to',
|
||||
'assets.assigned_type',
|
||||
'assets.status_id',
|
||||
])->with('model', 'assetstatus', 'assignedTo')->NotArchived();
|
||||
])->with('model', 'assetstatus', 'assignedTo')->NotArchived(), 'company_id', 'assets');
|
||||
|
||||
if ($request->filled('assetStatusType') && $request->input('assetStatusType') === 'RTD') {
|
||||
$assets = $assets->RTD();
|
||||
@@ -545,16 +544,14 @@ class AssetsController extends Controller
|
||||
$asset->model_id = $request->get('model_id');
|
||||
$asset->order_number = $request->get('order_number');
|
||||
$asset->notes = $request->get('notes');
|
||||
$asset->asset_tag = $request->get('asset_tag', Asset::autoincrement_asset()); //yup, problem :/
|
||||
// NO IT IS NOT!!! This is never firing; we SHOW the asset_tag you're going to get, so it *will* be filled in!
|
||||
$asset->asset_tag = $request->get('asset_tag', Asset::autoincrement_asset());
|
||||
$asset->user_id = Auth::id();
|
||||
$asset->archived = '0';
|
||||
$asset->physical = '1';
|
||||
$asset->depreciate = '0';
|
||||
$asset->status_id = $request->get('status_id', 0);
|
||||
$asset->warranty_months = $request->get('warranty_months', null);
|
||||
$asset->purchase_cost = $request->get('purchase_cost');
|
||||
$asset->asset_eol_date = $request->get('asset_eol_date', $asset->present()->eol_date());
|
||||
$asset->purchase_cost = Helper::ParseCurrency($request->get('purchase_cost')); // this is the API's store method, so I don't know that I want to do this? Confusing. FIXME (or not?!)
|
||||
$asset->purchase_date = $request->get('purchase_date', null);
|
||||
$asset->assigned_to = $request->get('assigned_to', null);
|
||||
$asset->supplier_id = $request->get('supplier_id');
|
||||
@@ -562,7 +559,6 @@ class AssetsController extends Controller
|
||||
$asset->rtd_location_id = $request->get('rtd_location_id', null);
|
||||
$asset->location_id = $request->get('rtd_location_id', null);
|
||||
|
||||
|
||||
/**
|
||||
* this is here just legacy reasons. Api\AssetController
|
||||
* used image_source once to allow encoded image uploads.
|
||||
@@ -573,8 +569,41 @@ class AssetsController extends Controller
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
|
||||
$asset->customFill($request, Auth::user(), true);
|
||||
// Update custom fields in the database.
|
||||
// Validation for these fields is handled through the AssetRequest form request
|
||||
$model = AssetModel::find($request->get('model_id'));
|
||||
if (($model) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
|
||||
// Set the field value based on what was sent in the request
|
||||
$field_val = $request->input($field->db_column, null);
|
||||
|
||||
// If input value is null, use custom field's default value
|
||||
if ($field_val == null) {
|
||||
\Log::debug('Field value for '.$field->db_column.' is null');
|
||||
$field_val = $field->defaultValue($request->get('model_id'));
|
||||
\Log::debug('Use the default fieldset value of '.$field->defaultValue($request->get('model_id')));
|
||||
}
|
||||
|
||||
// if the field is set to encrypted, make sure we encrypt the value
|
||||
if ($field->field_encrypted == '1') {
|
||||
\Log::debug('This model field is encrypted in this fieldset.');
|
||||
|
||||
if (Gate::allows('admin')) {
|
||||
|
||||
// If input value is null, use custom field's default value
|
||||
if (($field_val == null) && ($request->has('model_id') != '')) {
|
||||
$field_val = \Crypt::encrypt($field->defaultValue($request->get('model_id')));
|
||||
} else {
|
||||
$field_val = \Crypt::encrypt($request->input($field->db_column));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$asset->{$field->db_column} = $field_val;
|
||||
}
|
||||
}
|
||||
|
||||
if ($asset->save()) {
|
||||
if ($request->get('assigned_user')) {
|
||||
@@ -634,7 +663,21 @@ class AssetsController extends Controller
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
|
||||
$asset->customFill($request,Auth::user());
|
||||
// Update custom fields
|
||||
if (($model = AssetModel::find($asset->model_id)) && (isset($model->fieldset))) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($request->has($field->db_column)) {
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('admin')) {
|
||||
$asset->{$field->db_column} = \Crypt::encrypt($request->input($field->db_column));
|
||||
}
|
||||
} else {
|
||||
$asset->{$field->db_column} = $request->input($field->db_column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if ($asset->save()) {
|
||||
if (($request->filled('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
|
||||
@@ -786,6 +829,7 @@ class AssetsController extends Controller
|
||||
|
||||
} elseif (request('checkout_to_type') == 'asset') {
|
||||
$target = Asset::where('id', '!=', $asset_id)->find(request('assigned_asset'));
|
||||
$asset->location_id = $target->rtd_location_id;
|
||||
// Override with the asset's location_id if it has one
|
||||
$asset->location_id = (($target) && (isset($target->location_id))) ? $target->location_id : '';
|
||||
$error_payload['target_id'] = $request->input('assigned_asset');
|
||||
@@ -857,7 +901,6 @@ class AssetsController extends Controller
|
||||
|
||||
$asset->expected_checkin = null;
|
||||
$asset->last_checkout = null;
|
||||
$asset->last_checkin = now();
|
||||
$asset->assigned_to = null;
|
||||
$asset->assignedTo()->disassociate($asset);
|
||||
$asset->accepted = null;
|
||||
@@ -877,14 +920,10 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
$checkin_at = $request->filled('checkin_at') ? $request->input('checkin_at').' '. date('H:i:s') : date('Y-m-d H:i:s');
|
||||
$originalValues = $asset->getRawOriginal();
|
||||
|
||||
if (($request->filled('checkin_at')) && ($request->get('checkin_at') != date('Y-m-d'))) {
|
||||
$originalValues['action_date'] = $checkin_at;
|
||||
}
|
||||
|
||||
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));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', ['asset'=> e($asset->asset_tag)], trans('admin/hardware/message.checkin.success')));
|
||||
}
|
||||
@@ -899,21 +938,18 @@ class AssetsController extends Controller
|
||||
* @since [v6.0]
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function checkinByTag(Request $request, $tag = null)
|
||||
public function checkinByTag(Request $request)
|
||||
{
|
||||
$this->authorize('checkin', Asset::class);
|
||||
if(null == $tag && null !== ($request->input('asset_tag'))) {
|
||||
$tag = $request->input('asset_tag');
|
||||
}
|
||||
$asset = Asset::where('asset_tag', $tag)->first();
|
||||
$asset = Asset::where('asset_tag', $request->input('asset_tag'))->first();
|
||||
|
||||
if ($asset) {
|
||||
return $this->checkin($request, $asset->id);
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', [
|
||||
'asset'=> e($tag)
|
||||
], 'Asset with tag '.e($tag).' not found'));
|
||||
'asset'=> e($request->input('asset_tag'))
|
||||
], 'Asset with tag '.e($request->input('asset_tag')).' not found'));
|
||||
}
|
||||
|
||||
|
||||
@@ -990,10 +1026,9 @@ class AssetsController extends Controller
|
||||
{
|
||||
$this->authorize('viewRequestable', Asset::class);
|
||||
|
||||
$assets = Asset::select('assets.*')
|
||||
$assets = Company::scopeCompanyables(Asset::select('assets.*'), 'company_id', 'assets')
|
||||
->with('location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
|
||||
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier')
|
||||
->requestableAssets();
|
||||
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier')->requestableAssets();
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
@@ -24,48 +24,10 @@ class CategoriesController extends Controller
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', Category::class);
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
'name',
|
||||
'category_type',
|
||||
'category_type',
|
||||
'use_default_eula',
|
||||
'eula_text',
|
||||
'require_acceptance',
|
||||
'checkin_email',
|
||||
'assets_count',
|
||||
'accessories_count',
|
||||
'consumables_count',
|
||||
'components_count',
|
||||
'licenses_count',
|
||||
'image',
|
||||
];
|
||||
$allowed_columns = ['id', 'name', 'category_type', 'category_type', 'use_default_eula', 'eula_text', 'require_acceptance', 'checkin_email', 'assets_count', 'accessories_count', 'consumables_count', 'components_count', 'licenses_count', 'image'];
|
||||
|
||||
$categories = Category::select([
|
||||
'id',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'name', 'category_type',
|
||||
'use_default_eula',
|
||||
'eula_text',
|
||||
'require_acceptance',
|
||||
'checkin_email',
|
||||
'image'
|
||||
])->withCount('accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count');
|
||||
|
||||
|
||||
/*
|
||||
* This checks to see if we should override the Admin Setting to show archived assets in list.
|
||||
* We don't currently use it within the Snipe-IT GUI, but will be useful for API integrations where they
|
||||
* may actually need to fetch assets that are archived.
|
||||
*
|
||||
* @see \App\Models\Category::showableAssets()
|
||||
*/
|
||||
if ($request->input('archived')=='true') {
|
||||
$categories = $categories->withCount('assets as assets_count');
|
||||
} else {
|
||||
$categories = $categories->withCount('showableAssets as assets_count');
|
||||
}
|
||||
$categories = Category::select(['id', 'created_at', 'updated_at', 'name', 'category_type', 'use_default_eula', 'eula_text', 'require_acceptance', 'checkin_email', 'image'])
|
||||
->withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$categories = $categories->TextSearch($request->input('search'));
|
||||
@@ -91,9 +53,14 @@ class CategoriesController extends Controller
|
||||
$categories->where('checkin_email', '=', $request->input('checkin_email'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $categories->count()) ? $categories->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($categories) && ($request->get('offset') > $categories->count())) ? $categories->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'assets_count';
|
||||
|
||||
@@ -27,9 +27,6 @@ class CompaniesController extends Controller
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
'name',
|
||||
'phone',
|
||||
'fax',
|
||||
'email',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'users_count',
|
||||
@@ -50,15 +47,13 @@ class CompaniesController extends Controller
|
||||
$companies->where('name', '=', $request->input('name'));
|
||||
}
|
||||
|
||||
if ($request->filled('email')) {
|
||||
$companies->where('email', '=', $request->input('email'));
|
||||
}
|
||||
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($companies) && ($request->get('offset') > $companies->count())) ? $companies->count() : $request->get('offset', 0);
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $companies->count()) ? $companies->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
@@ -173,7 +168,6 @@ class CompaniesController extends Controller
|
||||
$companies = Company::select([
|
||||
'companies.id',
|
||||
'companies.name',
|
||||
'companies.email',
|
||||
'companies.image',
|
||||
]);
|
||||
|
||||
|
||||
@@ -12,8 +12,6 @@ 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;
|
||||
|
||||
class ComponentsController extends Controller
|
||||
{
|
||||
@@ -45,8 +43,9 @@ class ComponentsController extends Controller
|
||||
'notes',
|
||||
];
|
||||
|
||||
$components = Component::select('components.*')
|
||||
->with('company', 'location', 'category', 'assets', 'supplier');
|
||||
|
||||
$components = Company::scopeCompanyables(Component::select('components.*')
|
||||
->with('company', 'location', 'category', 'assets'));
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$components = $components->TextSearch($request->input('search'));
|
||||
@@ -64,10 +63,6 @@ class ComponentsController extends Controller
|
||||
$components->where('category_id', '=', $request->input('category_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('supplier_id')) {
|
||||
$components->where('supplier_id', '=', $request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
$components->where('location_id', '=', $request->input('location_id'));
|
||||
}
|
||||
@@ -76,10 +71,14 @@ class ComponentsController extends Controller
|
||||
$components->where('notes','=',$request->input('notes'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $components->count()) ? $components->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($components) && ($request->get('offset') > $components->count())) ? $components->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort_override = $request->input('sort');
|
||||
$column_sort = in_array($sort_override, $allowed_columns) ? $sort_override : 'created_at';
|
||||
@@ -94,9 +93,6 @@ class ComponentsController extends Controller
|
||||
case 'company':
|
||||
$components = $components->OrderCompany($order);
|
||||
break;
|
||||
case 'supplier':
|
||||
$components = $components->OrderSupplier($order);
|
||||
break;
|
||||
default:
|
||||
$components = $components->orderBy($column_sort, $order);
|
||||
break;
|
||||
@@ -204,29 +200,12 @@ class ComponentsController extends Controller
|
||||
$this->authorize('view', \App\Models\Asset::class);
|
||||
|
||||
$component = Component::findOrFail($id);
|
||||
|
||||
$assets = $component->assets();
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$assets = $component->assets()
|
||||
->where(function ($query) use ($request) {
|
||||
$search_str = '%' . $request->input('search') . '%';
|
||||
$query->where('name', 'like', $search_str)
|
||||
->orWhereIn('model_id', function (Builder $query) use ($request) {
|
||||
$search_str = '%' . $request->input('search') . '%';
|
||||
$query->selectRaw('id')->from('models')->where('name', 'like', $search_str);
|
||||
})
|
||||
->orWhere('asset_tag', 'like', $search_str);
|
||||
})
|
||||
->get();
|
||||
$total = $assets->count();
|
||||
} else {
|
||||
$assets = $component->assets();
|
||||
|
||||
$total = $assets->count();
|
||||
$assets = $assets->skip($offset)->take($limit)->get();
|
||||
}
|
||||
$total = $assets->count();
|
||||
$assets = $assets->skip($offset)->take($limit)->get();
|
||||
|
||||
return (new ComponentsTransformer)->transformCheckedoutComponents($assets, $total);
|
||||
}
|
||||
@@ -246,30 +225,20 @@ class ComponentsController extends Controller
|
||||
public function checkout(Request $request, $componentId)
|
||||
{
|
||||
// Check if the component exists
|
||||
if (!$component = Component::find($componentId)) {
|
||||
if (is_null($component = Component::find($componentId))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.does_not_exist')));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $component);
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'assigned_to' => 'required|exists:assets,id',
|
||||
'assigned_qty' => "required|numeric|min:1|digits_between:1,".$component->numRemaining(),
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', $validator->errors()));
|
||||
|
||||
}
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($component->numRemaining() <= $request->get('assigned_qty')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.checkout.unavailable', ['remaining' => $component->numRemaining(), 'requested' => $request->get('assigned_qty')])));
|
||||
}
|
||||
|
||||
if ($component->numRemaining() >= $request->get('assigned_qty')) {
|
||||
|
||||
$asset = Asset::find($request->input('assigned_to'));
|
||||
if (!$asset = Asset::find($request->input('assigned_to'))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')));
|
||||
}
|
||||
|
||||
// Update the accessory data
|
||||
$component->assigned_to = $request->input('assigned_to');
|
||||
|
||||
$component->assets()->attach($component->id, [
|
||||
@@ -286,7 +255,7 @@ class ComponentsController extends Controller
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/components/message.checkout.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/components/message.checkout.unavailable', ['remaining' => $component->numRemaining(), 'requested' => $request->get('assigned_qty')])));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Not enough components remaining: '.$component->numRemaining().' remaining, '.$request->get('assigned_qty').' requested.'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\ComponentsTransformer;
|
||||
use App\Http\Transformers\ConsumablesTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Models\Company;
|
||||
@@ -45,8 +46,11 @@ class ConsumablesController extends Controller
|
||||
'notes',
|
||||
];
|
||||
|
||||
$consumables = Consumable::select('consumables.*')
|
||||
->with('company', 'location', 'category', 'users', 'manufacturer');
|
||||
|
||||
$consumables = Company::scopeCompanyables(
|
||||
Consumable::select('consumables.*')
|
||||
->with('company', 'location', 'category', 'users', 'manufacturer')
|
||||
);
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$consumables = $consumables->TextSearch(e($request->input('search')));
|
||||
@@ -72,10 +76,6 @@ class ConsumablesController extends Controller
|
||||
$consumables->where('manufacturer_id', '=', $request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('supplier_id')) {
|
||||
$consumables->where('supplier_id', '=', $request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('location_id')) {
|
||||
$consumables->where('location_id','=',$request->input('location_id'));
|
||||
}
|
||||
@@ -85,9 +85,12 @@ 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() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($consumables) && ($request->get('offset') > $consumables->count())) ? $consumables->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$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';
|
||||
@@ -109,9 +112,6 @@ class ConsumablesController extends Controller
|
||||
case 'company':
|
||||
$consumables = $consumables->OrderCompany($order);
|
||||
break;
|
||||
case 'supplier':
|
||||
$components = $consumables->OrderSupplier($order);
|
||||
break;
|
||||
default:
|
||||
$consumables = $consumables->orderBy($column_sort, $order);
|
||||
break;
|
||||
@@ -155,7 +155,7 @@ class ConsumablesController extends Controller
|
||||
public function show($id)
|
||||
{
|
||||
$this->authorize('view', Consumable::class);
|
||||
$consumable = Consumable::with('users')->findOrFail($id);
|
||||
$consumable = Consumable::findOrFail($id);
|
||||
|
||||
return (new ConsumablesTransformer)->transformConsumable($consumable);
|
||||
}
|
||||
@@ -210,37 +210,23 @@ class ConsumablesController extends Controller
|
||||
* @param int $consumableId
|
||||
* @return array
|
||||
*/
|
||||
public function getDataView($consumableId)
|
||||
public function checkedout($consumableId)
|
||||
{
|
||||
$consumable = Consumable::with(['consumableAssignments'=> function ($query) {
|
||||
$query->orderBy($query->getModel()->getTable().'.created_at', 'DESC');
|
||||
},
|
||||
'consumableAssignments.admin'=> function ($query) {
|
||||
},
|
||||
'consumableAssignments.user'=> function ($query) {
|
||||
},
|
||||
])->find($consumableId);
|
||||
|
||||
$consumable = Consumable::with('users')->findOrFail($consumableId);
|
||||
if (! Company::isCurrentUserHasAccess($consumable)) {
|
||||
return ['total' => 0, 'rows' => []];
|
||||
}
|
||||
$this->authorize('view', Consumable::class);
|
||||
$rows = [];
|
||||
|
||||
foreach ($consumable->consumableAssignments as $consumable_assignment) {
|
||||
$rows[] = [
|
||||
'avatar' => ($consumable_assignment->user) ? e($consumable_assignment->user->present()->gravatar) : '',
|
||||
'name' => ($consumable_assignment->user) ? $consumable_assignment->user->present()->nameUrl() : 'Deleted User',
|
||||
'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'),
|
||||
'note' => ($consumable_assignment->note) ? e($consumable_assignment->note) : null,
|
||||
'admin' => ($consumable_assignment->admin) ? $consumable_assignment->admin->present()->nameUrl() : null,
|
||||
];
|
||||
$offset = request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
$consumables_users = $consumable->users;
|
||||
$total = $consumables_users->count();
|
||||
|
||||
if ($total < $offset) {
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
$consumableCount = $consumable->users->count();
|
||||
$data = ['total' => $consumableCount, 'rows' => $rows];
|
||||
|
||||
return $data;
|
||||
return (new ConsumablesTransformer)->transformCheckedoutConsumables($consumable, $consumables_users, $total);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -254,39 +240,33 @@ class ConsumablesController extends Controller
|
||||
public function checkout(Request $request, $id)
|
||||
{
|
||||
// Check if the consumable exists
|
||||
if (!$consumable = Consumable::with('users')->find($id)) {
|
||||
if (is_null($consumable = Consumable::find($id))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/consumables/message.does_not_exist')));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $consumable);
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/consumables/message.checkout.unavailable')));
|
||||
\Log::debug('No enough remaining');
|
||||
}
|
||||
if ($consumable->qty > 0) {
|
||||
|
||||
// Check if the user exists - @TODO: this should probably be handled via validation, not here??
|
||||
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');
|
||||
}
|
||||
// Check if the user exists
|
||||
$assigned_to = $request->input('assigned_to');
|
||||
if (is_null($user = User::find($assigned_to))) {
|
||||
// Return error message
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'No user found'));
|
||||
}
|
||||
|
||||
// Update the consumable data
|
||||
$consumable->assigned_to = $request->input('assigned_to');
|
||||
// Update the consumable data
|
||||
$consumable->assigned_to = e($assigned_to);
|
||||
|
||||
$consumable->users()->attach($consumable->id,
|
||||
[
|
||||
'consumable_id' => $consumable->id,
|
||||
'user_id' => $user->id,
|
||||
'assigned_to' => $request->input('assigned_to'),
|
||||
'note' => $request->input('note'),
|
||||
]
|
||||
);
|
||||
$consumable->users()->attach($consumable->id, [
|
||||
'consumable_id' => $consumable->id,
|
||||
'user_id' => $user->id,
|
||||
'assigned_to' => $assigned_to,
|
||||
'note' => $request->input('note'),
|
||||
]);
|
||||
|
||||
// Log checkout event
|
||||
$logaction = $consumable->logCheckout($request->input('note'), $user);
|
||||
$logaction = $consumable->logCheckout(e($request->input('note')), $user);
|
||||
$data['log_id'] = $logaction->id;
|
||||
$data['eula'] = $consumable->getEula();
|
||||
$data['first_name'] = $user->first_name;
|
||||
@@ -296,7 +276,9 @@ class ConsumablesController extends Controller
|
||||
$data['require_acceptance'] = $consumable->requireAcceptance();
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/consumables/message.checkout.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'No consumables remaining'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -7,7 +7,6 @@ use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\CustomFieldsetsTransformer;
|
||||
use App\Http\Transformers\CustomFieldsTransformer;
|
||||
use App\Models\CustomFieldset;
|
||||
use App\Models\CustomField;
|
||||
use Illuminate\Http\Request;
|
||||
use Redirect;
|
||||
use View;
|
||||
@@ -35,7 +34,7 @@ class CustomFieldsetsController extends Controller
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('index', CustomField::class);
|
||||
$fieldsets = CustomFieldset::withCount('fields as fields_count')->get();
|
||||
$fieldsets = CustomFieldset::withCount('fields as fields_count', 'models as models_count')->get();
|
||||
|
||||
return (new CustomFieldsetsTransformer)->transformCustomFieldsets($fieldsets, $fieldsets->count());
|
||||
}
|
||||
@@ -95,18 +94,6 @@ class CustomFieldsetsController extends Controller
|
||||
$fieldset->fill($request->all());
|
||||
|
||||
if ($fieldset->save()) {
|
||||
// Sync fieldset with auto_add_to_fieldsets
|
||||
$fields = CustomField::select('id')->where('auto_add_to_fieldsets', '=', '1')->get();
|
||||
|
||||
if ($fields->count() > 0) {
|
||||
|
||||
foreach ($fields as $field) {
|
||||
$field_ids[] = $field->id;
|
||||
}
|
||||
|
||||
$fieldset->fields()->sync($field_ids);
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $fieldset, trans('admin/custom_fields/message.fieldset.create.success')));
|
||||
}
|
||||
|
||||
@@ -125,7 +112,7 @@ class CustomFieldsetsController extends Controller
|
||||
$this->authorize('delete', CustomField::class);
|
||||
$fieldset = CustomFieldset::findOrFail($id);
|
||||
|
||||
$modelsCount = $fieldset->customizables()->count();
|
||||
$modelsCount = $fieldset->models->count();
|
||||
$fieldsCount = $fieldset->fields->count();
|
||||
|
||||
if (($modelsCount > 0) || ($fieldsCount > 0)) {
|
||||
|
||||
@@ -30,8 +30,6 @@ class DepartmentsController extends Controller
|
||||
$departments = Company::scopeCompanyables(Department::select(
|
||||
'departments.id',
|
||||
'departments.name',
|
||||
'departments.phone',
|
||||
'departments.fax',
|
||||
'departments.location_id',
|
||||
'departments.company_id',
|
||||
'departments.manager_id',
|
||||
@@ -60,9 +58,12 @@ class DepartmentsController extends Controller
|
||||
$departments->where('location_id', '=', $request->input('location_id'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $departments->count()) ? $departments->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($departments) && ($request->get('offset') > $departments->count())) ? $departments->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
|
||||
@@ -28,9 +28,12 @@ class DepreciationsController extends Controller
|
||||
$depreciations = $depreciations->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $depreciations->count()) ? $depreciations->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($depreciations) && ($request->get('offset') > $depreciations->count())) ? $depreciations->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
|
||||
@@ -8,7 +8,6 @@ use App\Http\Transformers\GroupsTransformer;
|
||||
use App\Models\Group;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
|
||||
class GroupsController extends Controller
|
||||
{
|
||||
/**
|
||||
@@ -20,8 +19,6 @@ class GroupsController extends Controller
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('superadmin');
|
||||
|
||||
$this->authorize('view', Group::class);
|
||||
$allowed_columns = ['id', 'name', 'created_at', 'users_count'];
|
||||
|
||||
@@ -35,9 +32,12 @@ class GroupsController extends Controller
|
||||
$groups->where('name', '=', $request->input('name'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $groups->count()) ? $groups->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($groups) && ($request->get('offset') > $groups->count())) ? $groups->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
@@ -59,11 +59,9 @@ class GroupsController extends Controller
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('superadmin');
|
||||
$this->authorize('create', Group::class);
|
||||
$group = new Group;
|
||||
|
||||
$group->name = $request->input('name');
|
||||
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
|
||||
$group->fill($request->all());
|
||||
|
||||
if ($group->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.create.success')));
|
||||
@@ -82,7 +80,7 @@ class GroupsController extends Controller
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$this->authorize('superadmin');
|
||||
$this->authorize('view', Group::class);
|
||||
$group = Group::findOrFail($id);
|
||||
|
||||
return (new GroupsTransformer)->transformGroup($group);
|
||||
@@ -99,11 +97,9 @@ class GroupsController extends Controller
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$this->authorize('superadmin');
|
||||
$this->authorize('update', Group::class);
|
||||
$group = Group::findOrFail($id);
|
||||
|
||||
$group->name = $request->input('name');
|
||||
$group->permissions = $request->input('permissions'); // Todo - some JSON validation stuff here
|
||||
$group->fill($request->all());
|
||||
|
||||
if ($group->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $group, trans('admin/groups/message.update.success')));
|
||||
@@ -122,8 +118,9 @@ class GroupsController extends Controller
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$this->authorize('superadmin');
|
||||
$this->authorize('delete', Group::class);
|
||||
$group = Group::findOrFail($id);
|
||||
$this->authorize('delete', $group);
|
||||
$group->delete();
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/groups/message.delete.success')));
|
||||
|
||||
@@ -126,14 +126,7 @@ class ImportController extends Controller
|
||||
}
|
||||
$file_name = date('Y-m-d-his').'-'.$fixed_filename;
|
||||
$import->file_path = $file_name;
|
||||
$import->filesize = null;
|
||||
|
||||
if (!file_exists($path.'/'.$file_name)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.file_not_found')), 500);
|
||||
}
|
||||
|
||||
$import->filesize = filesize($path.'/'.$file_name);
|
||||
|
||||
$import->save();
|
||||
$results[] = $import;
|
||||
}
|
||||
@@ -160,7 +153,7 @@ class ImportController extends Controller
|
||||
// Run a backup immediately before processing
|
||||
if ($request->get('run-backup')) {
|
||||
\Log::debug('Backup manually requested via importer');
|
||||
Artisan::call('snipeit:backup', ['--filename' => 'pre-import-backup-'.date('Y-m-d-H:i:s')]);
|
||||
Artisan::call('backup:run');
|
||||
} else {
|
||||
\Log::debug('NO BACKUP requested via importer');
|
||||
}
|
||||
@@ -193,9 +186,6 @@ class ImportController extends Controller
|
||||
case 'user':
|
||||
$redirectTo = 'users.index';
|
||||
break;
|
||||
case 'location':
|
||||
$redirectTo = 'locations.index';
|
||||
break;
|
||||
}
|
||||
|
||||
if ($errors) { //Failure
|
||||
|
||||
@@ -1,71 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\LabelsTransformer;
|
||||
use App\Models\Labels\Label;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\ItemNotFoundException;
|
||||
use Auth;
|
||||
|
||||
class LabelsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns JSON listing of all labels.
|
||||
*
|
||||
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', Label::class);
|
||||
|
||||
$labels = Label::find();
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$search = $request->get('search');
|
||||
$labels = $labels->filter(function ($label, $index) use ($search) {
|
||||
return stripos($label->getName(), $search) !== false;
|
||||
});
|
||||
}
|
||||
|
||||
$total = $labels->count();
|
||||
|
||||
$offset = $request->get('offset', 0);
|
||||
$offset = ($offset > $total) ? $total : $offset;
|
||||
|
||||
$maxLimit = config('app.max_results');
|
||||
$limit = $request->get('limit', $maxLimit);
|
||||
$limit = ($limit > $maxLimit) ? $maxLimit : $limit;
|
||||
|
||||
$labels = $labels->skip($offset)->take($limit);
|
||||
|
||||
return (new LabelsTransformer)->transformLabels($labels, $total, $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns JSON with information about a label for detail view.
|
||||
*
|
||||
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
|
||||
* @param string $labelName
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function show(string $labelName)
|
||||
{
|
||||
$labelName = str_replace('/', '\\', $labelName);
|
||||
try {
|
||||
$label = Label::find($labelName);
|
||||
} catch(ItemNotFoundException $e) {
|
||||
return response()
|
||||
->json(
|
||||
Helper::formatStandardApiResponse('error', null, trans('admin/labels/message.does_not_exist')),
|
||||
404
|
||||
);
|
||||
}
|
||||
$this->authorize('view', $label);
|
||||
return (new LabelsTransformer)->transformLabel($label);
|
||||
}
|
||||
|
||||
}
|
||||
@@ -39,15 +39,8 @@ class LicenseSeatsController extends Controller
|
||||
}
|
||||
|
||||
$total = $seats->count();
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $seats->count()) ? $seats->count() : abs($request->input('offset'));
|
||||
|
||||
if ($offset >= $total ){
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
$limit = app('api_limit_value');
|
||||
$offset = (($seats) && (request('offset') >= $total)) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
$seats = $seats->skip($offset)->take($limit)->get();
|
||||
|
||||
|
||||
@@ -26,8 +26,8 @@ class LicensesController extends Controller
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', License::class);
|
||||
$licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'supplier','category')->withCount('freeSeats as free_seats_count'));
|
||||
|
||||
$licenses = License::with('company', 'manufacturer', 'supplier','category')->withCount('freeSeats as free_seats_count');
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
$licenses->where('company_id', '=', $request->input('company_id'));
|
||||
@@ -94,9 +94,12 @@ class LicensesController extends Controller
|
||||
$licenses->onlyTrashed();
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $licenses->count()) ? $licenses->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($licenses) && ($request->get('offset') > $licenses->count())) ? $licenses->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
|
||||
@@ -37,8 +37,6 @@ class LocationsController extends Controller
|
||||
'locations.city',
|
||||
'locations.state',
|
||||
'locations.zip',
|
||||
'locations.phone',
|
||||
'locations.fax',
|
||||
'locations.country',
|
||||
'locations.parent_id',
|
||||
'locations.manager_id',
|
||||
@@ -80,15 +78,14 @@ class LocationsController extends Controller
|
||||
$locations->where('locations.country', '=', $request->input('country'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $locations->count()) ? $locations->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
$offset = (($locations) && (request('offset') > $locations->count())) ? $locations->count() : request('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
|
||||
|
||||
|
||||
switch ($request->input('sort')) {
|
||||
case 'parent':
|
||||
$locations->OrderParent($order);
|
||||
@@ -253,12 +250,8 @@ class LocationsController extends Controller
|
||||
*/
|
||||
public function selectlist(Request $request)
|
||||
{
|
||||
// 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.
|
||||
// Otherwise, we do our normal check that they can view select lists.
|
||||
$request->headers->get('referer') === route('profile')
|
||||
? $this->authorize('self.edit_location')
|
||||
: $this->authorize('view.selectlists');
|
||||
|
||||
$this->authorize('view.selectlists');
|
||||
|
||||
$locations = Location::select([
|
||||
'locations.id',
|
||||
|
||||
@@ -23,10 +23,10 @@ class ManufacturersController extends Controller
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', Manufacturer::class);
|
||||
$allowed_columns = ['id', 'name', 'url', 'support_url', 'support_email', 'warranty_lookup_url', 'support_phone', 'created_at', 'updated_at', 'image', 'assets_count', 'consumables_count', 'components_count', 'licenses_count'];
|
||||
$allowed_columns = ['id', 'name', 'url', 'support_url', 'support_email', 'support_phone', 'created_at', 'updated_at', 'image', 'assets_count', 'consumables_count', 'components_count', 'licenses_count'];
|
||||
|
||||
$manufacturers = Manufacturer::select(
|
||||
['id', 'name', 'url', 'support_url', 'warranty_lookup_url', 'support_email', 'support_phone', 'created_at', 'updated_at', 'image', 'deleted_at']
|
||||
['id', 'name', 'url', 'support_url', 'support_email', 'support_phone', 'created_at', 'updated_at', 'image', 'deleted_at']
|
||||
)->withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('consumables as consumables_count')->withCount('accessories as accessories_count');
|
||||
|
||||
if ($request->input('deleted') == 'true') {
|
||||
@@ -49,10 +49,6 @@ class ManufacturersController extends Controller
|
||||
$manufacturers->where('support_url', '=', $request->input('support_url'));
|
||||
}
|
||||
|
||||
if ($request->filled('warranty_lookup_url')) {
|
||||
$manufacturers->where('warranty_lookup_url', '=', $request->input('warranty_lookup_url'));
|
||||
}
|
||||
|
||||
if ($request->filled('support_phone')) {
|
||||
$manufacturers->where('support_phone', '=', $request->input('support_phone'));
|
||||
}
|
||||
@@ -61,9 +57,12 @@ class ManufacturersController extends Controller
|
||||
$manufacturers->where('support_email', '=', $request->input('support_email'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $manufacturers->count()) ? $manufacturers->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($manufacturers) && ($request->get('offset') > $manufacturers->count())) ? $manufacturers->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
|
||||
@@ -29,10 +29,8 @@ class PredefinedKitsController extends Controller
|
||||
$kits = $kits->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $kits->count()) ? $kits->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$offset = $request->input('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
$order = $request->input('order') === 'desc' ? 'desc' : 'asc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'name';
|
||||
$kits->orderBy($sort, $order);
|
||||
|
||||
@@ -10,7 +10,7 @@ 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 Gate;
|
||||
use DB;
|
||||
|
||||
class ProfileController extends Controller
|
||||
|
||||
@@ -54,15 +54,11 @@ class ReportsController extends Controller
|
||||
'note',
|
||||
];
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $actionlogs->count()) ? $actionlogs->count() : abs($request->input('offset'));
|
||||
$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';
|
||||
$offset = request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
$total = $actionlogs->count();
|
||||
|
||||
$actionlogs = $actionlogs->orderBy($sort, $order)->skip($offset)->take($limit)->get();
|
||||
|
||||
return response()->json((new ActionlogsTransformer)->transformActionlogs($actionlogs, $total), 200, ['Content-Type' => 'application/json;charset=utf8'], JSON_UNESCAPED_UNICODE);
|
||||
|
||||
@@ -143,6 +143,47 @@ class SettingsController extends Controller
|
||||
|
||||
}
|
||||
|
||||
public function slacktest(SlackSettingsRequest $request)
|
||||
{
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'slack_endpoint' => 'url|required_with:slack_channel|starts_with:https://hooks.slack.com/|nullable',
|
||||
'slack_channel' => 'required_with:slack_endpoint|starts_with:#|nullable',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json(['message' => 'Validation failed', 'errors' => $validator->errors()], 422);
|
||||
}
|
||||
|
||||
// If validation passes, continue to the curl request
|
||||
$slack = new Client([
|
||||
'base_url' => e($request->input('slack_endpoint')),
|
||||
'defaults' => [
|
||||
'exceptions' => false,
|
||||
],
|
||||
]);
|
||||
|
||||
$payload = json_encode(
|
||||
[
|
||||
'channel' => e($request->input('slack_channel')),
|
||||
'text' => trans('general.slack_test_msg'),
|
||||
'username' => e($request->input('slack_botname')),
|
||||
'icon_emoji' => ':heart:',
|
||||
]);
|
||||
|
||||
try {
|
||||
$slack->post($request->input('slack_endpoint'), ['body' => $payload]);
|
||||
return response()->json(['message' => 'Success'], 200);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(['message' => 'Please check the channel name and webhook endpoint URL ('.e($request->input('slack_endpoint')).'). Slack responded with: '.$e->getMessage()], 400);
|
||||
}
|
||||
|
||||
//}
|
||||
return response()->json(['message' => 'Something went wrong :( '], 400);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Test the email configuration
|
||||
*
|
||||
@@ -271,7 +312,7 @@ class SettingsController extends Controller
|
||||
$headers = ['ContentType' => 'application/zip'];
|
||||
return Storage::download($path.'/'.$file, $file, $headers);
|
||||
} else {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('general.file_not_found')));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'File not found'));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ namespace App\Http\Controllers\Api;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\AssetsTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Http\Transformers\StatuslabelsTransformer;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Statuslabel;
|
||||
@@ -51,9 +50,12 @@ class StatuslabelsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $statuslabels->count()) ? $statuslabels->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($statuslabels) && ($request->get('offset') > $statuslabels->count())) ? $statuslabels->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
@@ -194,7 +196,6 @@ class StatuslabelsController extends Controller
|
||||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
$statuslabels = Statuslabel::withCount('assets')->get();
|
||||
$total = Array();
|
||||
|
||||
foreach ($statuslabels as $statuslabel) {
|
||||
|
||||
@@ -292,45 +293,4 @@ class StatuslabelsController extends Controller
|
||||
|
||||
return '0';
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a paginated collection for the select2 menus
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v6.1.1]
|
||||
* @see \App\Http\Transformers\SelectlistTransformer
|
||||
*/
|
||||
public function selectlist(Request $request)
|
||||
{
|
||||
|
||||
$this->authorize('view.selectlists');
|
||||
$statuslabels = Statuslabel::orderBy('default_label', 'desc')->orderBy('name', 'asc')->orderBy('deployable', 'desc');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$statuslabels = $statuslabels->where('name', 'LIKE', '%'.$request->get('search').'%');
|
||||
}
|
||||
|
||||
if ($request->filled('deployable')) {
|
||||
$statuslabels = $statuslabels->where('deployable', '=', '1');
|
||||
}
|
||||
|
||||
if ($request->filled('pending')) {
|
||||
$statuslabels = $statuslabels->where('pending', '=', '1');
|
||||
}
|
||||
|
||||
if ($request->filled('archived')) {
|
||||
$statuslabels = $statuslabels->where('archived', '=', '1');
|
||||
}
|
||||
|
||||
$statuslabels = $statuslabels->orderBy('name', 'ASC')->paginate(50);
|
||||
|
||||
// Loop through and set some custom properties for the transformer to use.
|
||||
// This lets us have more flexibility in special cases like assets, where
|
||||
// they may not have a ->name value but we want to display something anyway
|
||||
foreach ($statuslabels as $statuslabel) {
|
||||
$statuslabels->use_text = $statuslabel->name;
|
||||
}
|
||||
|
||||
return (new SelectlistTransformer)->transformSelectlist($statuslabels);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,30 +23,11 @@ class SuppliersController extends Controller
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', Supplier::class);
|
||||
$allowed_columns = ['
|
||||
id',
|
||||
'name',
|
||||
'address',
|
||||
'phone',
|
||||
'contact',
|
||||
'fax',
|
||||
'email',
|
||||
'image',
|
||||
'assets_count',
|
||||
'licenses_count',
|
||||
'accessories_count',
|
||||
'components_count',
|
||||
'consumables_count',
|
||||
'url',
|
||||
];
|
||||
$allowed_columns = ['id', 'name', 'address', 'phone', 'contact', 'fax', 'email', 'image', 'assets_count', 'licenses_count', 'accessories_count', 'url'];
|
||||
|
||||
$suppliers = Supplier::select(
|
||||
['id', 'name', 'address', 'address2', 'city', 'state', 'country', 'fax', 'phone', 'email', 'contact', 'created_at', 'updated_at', 'deleted_at', 'image', 'notes', 'url'])
|
||||
->withCount('assets as assets_count')
|
||||
->withCount('licenses as licenses_count')
|
||||
->withCount('accessories as accessories_count')
|
||||
->withCount('components as components_count')
|
||||
->withCount('consumables as consumables_count');
|
||||
['id', 'name', 'address', 'address2', 'city', 'state', 'country', 'fax', 'phone', 'email', 'contact', 'created_at', 'updated_at', 'deleted_at', 'image', 'notes']
|
||||
)->withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('accessories as accessories_count');
|
||||
|
||||
|
||||
if ($request->filled('search')) {
|
||||
@@ -93,9 +74,12 @@ class SuppliersController extends Controller
|
||||
$suppliers->where('notes', '=', $request->input('notes'));
|
||||
}
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $suppliers->count()) ? $suppliers->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($suppliers) && ($request->get('offset') > $suppliers->count())) ? $suppliers->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? $request->input('sort') : 'created_at';
|
||||
|
||||
@@ -13,7 +13,6 @@ use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Http\Transformers\UsersTransformer;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CurrentInventory;
|
||||
@@ -21,7 +20,6 @@ use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class UsersController extends Controller
|
||||
{
|
||||
@@ -37,7 +35,7 @@ class UsersController extends Controller
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
|
||||
$allowed_columns = [
|
||||
$users = User::select([
|
||||
'users.activated',
|
||||
'users.created_by',
|
||||
'users.address',
|
||||
@@ -71,18 +69,18 @@ class UsersController extends Controller
|
||||
'users.ldap_import',
|
||||
'users.start_date',
|
||||
'users.end_date',
|
||||
'users.vip',
|
||||
'users.autoassign_licenses',
|
||||
|
||||
];
|
||||
|
||||
foreach(CustomField::where('type', User::class)->get() as $field) {
|
||||
$allowed_columns[] = $field->db_column_name();
|
||||
}
|
||||
$users = User::select()->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy',)
|
||||
])->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');
|
||||
$users = Company::scopeCompanyables($users);
|
||||
|
||||
|
||||
if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
|
||||
$users = $users->onlyTrashed();
|
||||
} elseif (($request->filled('all')) && ($request->input('all') == 'true')) {
|
||||
$users = $users->withTrashed();
|
||||
}
|
||||
|
||||
if ($request->filled('activated')) {
|
||||
$users = $users->where('users.activated', '=', $request->input('activated'));
|
||||
}
|
||||
@@ -151,10 +149,6 @@ class UsersController extends Controller
|
||||
$users = $users->where('remote', '=', $request->input('remote'));
|
||||
}
|
||||
|
||||
if ($request->filled('vip')) {
|
||||
$users = $users->where('vip', '=', $request->input('vip'));
|
||||
}
|
||||
|
||||
if ($request->filled('two_factor_enrolled')) {
|
||||
$users = $users->where('two_factor_enrolled', '=', $request->input('two_factor_enrolled'));
|
||||
}
|
||||
@@ -187,19 +181,19 @@ class UsersController extends Controller
|
||||
$users->has('accessories', '=', $request->input('accessories_count'));
|
||||
}
|
||||
|
||||
if ($request->filled('autoassign_licenses')) {
|
||||
$users->where('autoassign_licenses', '=', $request->input('autoassign_licenses'));
|
||||
}
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$users = $users->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$offset = (($users) && (request('offset') > $users->count())) ? 0 : request('offset', 0);
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $users->count()) ? $users->count() : abs($request->input('offset'));
|
||||
$limit = app('api_limit_value');
|
||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||
// case we override with the actual count, so we should return 0 items.
|
||||
$offset = (($users) && ($request->get('offset') > $users->count())) ? $users->count() : $request->get('offset', 0);
|
||||
|
||||
// Check to make sure the limit is not higher than the max allowed
|
||||
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
|
||||
|
||||
|
||||
switch ($request->input('sort')) {
|
||||
@@ -218,14 +212,6 @@ class UsersController extends Controller
|
||||
case 'company':
|
||||
$users = $users->OrderCompany($order);
|
||||
break;
|
||||
case 'first_name':
|
||||
$users->orderBy('first_name', $order);
|
||||
$users->orderBy('last_name', $order);
|
||||
break;
|
||||
case 'last_name':
|
||||
$users->orderBy('last_name', $order);
|
||||
$users->orderBy('first_name', $order);
|
||||
break;
|
||||
default:
|
||||
$allowed_columns =
|
||||
[
|
||||
@@ -260,10 +246,8 @@ class UsersController extends Controller
|
||||
'two_factor_optin',
|
||||
'two_factor_enrolled',
|
||||
'remote',
|
||||
'vip',
|
||||
'start_date',
|
||||
'end_date',
|
||||
'autoassign_licenses',
|
||||
];
|
||||
|
||||
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name';
|
||||
@@ -271,14 +255,6 @@ class UsersController extends Controller
|
||||
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);
|
||||
|
||||
$total = $users->count();
|
||||
$users = $users->skip($offset)->take($limit)->get();
|
||||
|
||||
@@ -310,11 +286,9 @@ class UsersController extends Controller
|
||||
$users = Company::scopeCompanyables($users);
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$users = $users->where(function ($query) use ($request) {
|
||||
$query->SimpleNameSearch($request->get('search'))
|
||||
->orWhere('username', 'LIKE', '%'.$request->get('search').'%')
|
||||
->orWhere('employee_num', 'LIKE', '%'.$request->get('search').'%');
|
||||
});
|
||||
$users = $users->SimpleNameSearch($request->get('search'))
|
||||
->orWhere('username', 'LIKE', '%'.$request->get('search').'%')
|
||||
->orWhere('employee_num', 'LIKE', '%'.$request->get('search').'%');
|
||||
}
|
||||
|
||||
$users = $users->orderBy('last_name', 'asc')->orderBy('first_name', 'asc');
|
||||
@@ -369,13 +343,11 @@ class UsersController extends Controller
|
||||
$user->permissions = $permissions_array;
|
||||
}
|
||||
|
||||
$tmp_pass = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 40);
|
||||
$tmp_pass = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 20);
|
||||
$user->password = bcrypt($request->get('password', $tmp_pass));
|
||||
|
||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
|
||||
|
||||
$user->customFill($request,Auth::user());
|
||||
|
||||
|
||||
if ($user->save()) {
|
||||
if ($request->filled('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
@@ -466,9 +438,7 @@ class UsersController extends Controller
|
||||
|
||||
|
||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
|
||||
|
||||
$user->customFill($request,Auth::user());
|
||||
|
||||
|
||||
if ($user->save()) {
|
||||
|
||||
// Sync group memberships:
|
||||
@@ -479,13 +449,6 @@ class UsersController extends Controller
|
||||
|
||||
// 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()));
|
||||
}
|
||||
$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')) {
|
||||
|
||||
@@ -101,7 +101,7 @@ class AssetMaintenancesController extends Controller
|
||||
$assetMaintenance = new AssetMaintenance();
|
||||
$assetMaintenance->supplier_id = $request->input('supplier_id');
|
||||
$assetMaintenance->is_warranty = $request->input('is_warranty');
|
||||
$assetMaintenance->cost = $request->input('cost');
|
||||
$assetMaintenance->cost = Helper::ParseCurrency($request->input('cost'));
|
||||
$assetMaintenance->notes = $request->input('notes');
|
||||
$asset = Asset::find($request->input('asset_id'));
|
||||
|
||||
@@ -211,7 +211,7 @@ class AssetMaintenancesController extends Controller
|
||||
|
||||
$assetMaintenance->supplier_id = $request->input('supplier_id');
|
||||
$assetMaintenance->is_warranty = $request->input('is_warranty');
|
||||
$assetMaintenance->cost = $request->input('cost');
|
||||
$assetMaintenance->cost = Helper::ParseCurrency($request->input('cost'));
|
||||
$assetMaintenance->notes = $request->input('notes');
|
||||
|
||||
$asset = Asset::find(request('asset_id'));
|
||||
|
||||
@@ -5,7 +5,6 @@ namespace App\Http\Controllers;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\DefaultValuesForCustomFields;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\View;
|
||||
@@ -77,15 +76,14 @@ class AssetModelsController extends Controller
|
||||
$model->depreciation_id = $request->input('depreciation_id');
|
||||
$model->name = $request->input('name');
|
||||
$model->model_number = $request->input('model_number');
|
||||
$model->min_amt = $request->input('min_amt');
|
||||
$model->manufacturer_id = $request->input('manufacturer_id');
|
||||
$model->category_id = $request->input('category_id');
|
||||
$model->notes = $request->input('notes');
|
||||
$model->user_id = Auth::id();
|
||||
$model->requestable = Request::has('requestable');
|
||||
|
||||
if ($request->input('fieldset_id') != '') {
|
||||
$model->fieldset_id = e($request->input('fieldset_id'));
|
||||
if ($request->input('custom_fieldset') != '') {
|
||||
$model->fieldset_id = e($request->input('custom_fieldset'));
|
||||
}
|
||||
|
||||
$model = $request->handleImages($model);
|
||||
@@ -155,18 +153,17 @@ class AssetModelsController extends Controller
|
||||
$model->eol = $request->input('eol');
|
||||
$model->name = $request->input('name');
|
||||
$model->model_number = $request->input('model_number');
|
||||
$model->min_amt = $request->input('min_amt');
|
||||
$model->manufacturer_id = $request->input('manufacturer_id');
|
||||
$model->category_id = $request->input('category_id');
|
||||
$model->notes = $request->input('notes');
|
||||
$model->requestable = $request->input('requestable', '0');
|
||||
|
||||
DefaultValuesForCustomFields::forPivot($model, Asset::class)->delete();
|
||||
$this->removeCustomFieldsDefaultValues($model);
|
||||
|
||||
if ($request->input('fieldset_id') == '') {
|
||||
if ($request->input('custom_fieldset') == '') {
|
||||
$model->fieldset_id = null;
|
||||
} else {
|
||||
$model->fieldset_id = $request->input('fieldset_id');
|
||||
$model->fieldset_id = $request->input('custom_fieldset');
|
||||
|
||||
if ($this->shouldAddDefaultValues($request->input())) {
|
||||
if (!$this->assignCustomFieldsDefaultValues($model, $request->input('default_values'))){
|
||||
@@ -289,7 +286,6 @@ class AssetModelsController extends Controller
|
||||
return view('models/edit')
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('item', $model)
|
||||
->with('model_id', $model_to_clone->id)
|
||||
->with('clone_model', $model_to_clone);
|
||||
}
|
||||
|
||||
@@ -448,11 +444,11 @@ class AssetModelsController extends Controller
|
||||
{
|
||||
return ! empty($input['add_default_values'])
|
||||
&& ! empty($input['default_values'])
|
||||
&& ! empty($input['fieldset_id']);
|
||||
&& ! empty($input['custom_fieldset']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds default values to a model (as long as they are truthy) (does this mean I cannot set a default value of 0?)
|
||||
* Adds default values to a model (as long as they are truthy)
|
||||
*
|
||||
* @param AssetModel $model
|
||||
* @param array $defaultValues
|
||||
@@ -487,12 +483,22 @@ class AssetModelsController extends Controller
|
||||
}
|
||||
|
||||
foreach ($defaultValues as $customFieldId => $defaultValue) {
|
||||
if(is_array($defaultValue)) {
|
||||
$defaultValue = implode(', ', $defaultValue);
|
||||
if(is_array($defaultValue)){
|
||||
$model->defaultValues()->attach($customFieldId, ['default_value' => implode(', ', $defaultValue)]);
|
||||
}elseif ($defaultValue) {
|
||||
$model->defaultValues()->attach($customFieldId, ['default_value' => $defaultValue]);
|
||||
}
|
||||
DefaultValuesForCustomFields::updateOrCreate(['custom_field_id' => $customFieldId,'item_pivot_id' => $model->id], ['default_value' => $defaultValue]);
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes all default values
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
private function removeCustomFieldsDefaultValues(AssetModel $model)
|
||||
{
|
||||
$model->defaultValues()->detach();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -78,7 +78,7 @@ class AssetModelsFilesController extends Controller
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($modelId = null, $fileId = null)
|
||||
public function show($modelId = null, $fileId = null, $download = true)
|
||||
{
|
||||
$model = AssetModel::find($modelId);
|
||||
// the asset is valid
|
||||
@@ -99,13 +99,12 @@ class AssetModelsFilesController extends Controller
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
if ($download != 'true') {
|
||||
if ($contents = file_get_contents(Storage::url($file))) {
|
||||
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
return JsonResponse::create(['error' => 'Failed validation: '], 500);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
@@ -68,7 +68,6 @@ class AssetCheckinController extends Controller
|
||||
|
||||
$asset->expected_checkin = null;
|
||||
$asset->last_checkout = null;
|
||||
$asset->last_checkin = now();
|
||||
$asset->assigned_to = null;
|
||||
$asset->assignedTo()->disassociate($asset);
|
||||
$asset->assigned_type = null;
|
||||
@@ -95,25 +94,18 @@ class AssetCheckinController extends Controller
|
||||
\Log::debug('Manually override the location IDs');
|
||||
\Log::debug('Original Location ID: '.$asset->location_id);
|
||||
$asset->location_id = '';
|
||||
\Log::debug('New Location ID: '.$asset->location_id);
|
||||
\Log::debug('New RTD Location ID: '.$asset->location_id);
|
||||
}
|
||||
|
||||
$asset->location_id = $asset->rtd_location_id;
|
||||
|
||||
if ($request->filled('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){
|
||||
$asset->rtd_location_id = $request->get('location_id');
|
||||
}
|
||||
$asset->location_id = e($request->get('location_id'));
|
||||
}
|
||||
|
||||
$originalValues = $asset->getRawOriginal();
|
||||
|
||||
$checkin_at = date('Y-m-d H:i:s');
|
||||
if (($request->filled('checkin_at')) && ($request->get('checkin_at') != date('Y-m-d'))) {
|
||||
$originalValues['action_date'] = $checkin_at;
|
||||
$checkin_at = $request->get('checkin_at');
|
||||
}
|
||||
|
||||
@@ -136,7 +128,7 @@ class AssetCheckinController extends Controller
|
||||
|
||||
// Was the asset updated?
|
||||
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));
|
||||
|
||||
if ((isset($user)) && ($backto == 'user')) {
|
||||
return redirect()->route('users.show', $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
|
||||
|
||||
@@ -27,7 +27,7 @@ class AssetCheckoutController extends Controller
|
||||
public function create($assetId)
|
||||
{
|
||||
// Check if the asset exists
|
||||
if (is_null($asset = Asset::with('company')->find(e($assetId)))) {
|
||||
if (is_null($asset = Asset::find(e($assetId)))) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
|
||||
@@ -89,14 +89,6 @@ class AssetCheckoutController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
$settings = \App\Models\Setting::getSettings();
|
||||
|
||||
if ($settings->full_multiple_companies_support){
|
||||
if ($target->company_id != $asset->company_id){
|
||||
return redirect()->to("hardware/$assetId/checkout")->with('error', trans('general.error_user_company'));
|
||||
}
|
||||
}
|
||||
|
||||
if ($asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $request->get('name'))) {
|
||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.checkout.success'));
|
||||
}
|
||||
|
||||
@@ -79,7 +79,7 @@ class AssetFilesController extends Controller
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($assetId = null, $fileId = null)
|
||||
public function show($assetId = null, $fileId = null, $download = true)
|
||||
{
|
||||
$asset = Asset::find($assetId);
|
||||
// the asset is valid
|
||||
@@ -103,13 +103,12 @@ class AssetFilesController extends Controller
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
if ($download != 'true') {
|
||||
if ($contents = file_get_contents(Storage::url($file))) {
|
||||
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
|
||||
}
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
return JsonResponse::create(['error' => 'Failed validation: '], 500);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
@@ -12,13 +12,11 @@ use App\Models\CheckoutRequest;
|
||||
use App\Models\Company;
|
||||
use App\Models\Location;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\User;
|
||||
use App\View\Label;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Gate;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
@@ -142,9 +140,8 @@ class AssetsController extends Controller
|
||||
$asset->depreciate = '0';
|
||||
$asset->status_id = request('status_id');
|
||||
$asset->warranty_months = request('warranty_months', null);
|
||||
$asset->purchase_cost = request('purchase_cost');
|
||||
$asset->purchase_cost = Helper::ParseCurrency($request->get('purchase_cost'));
|
||||
$asset->purchase_date = request('purchase_date', null);
|
||||
$asset->asset_eol_date = request('asset_eol_date', $asset->present()->eol_date());
|
||||
$asset->assigned_to = request('assigned_to', null);
|
||||
$asset->supplier_id = request('supplier_id', null);
|
||||
$asset->requestable = request('requestable', 0);
|
||||
@@ -164,7 +161,29 @@ class AssetsController extends Controller
|
||||
$asset = $request->handleImages($asset);
|
||||
}
|
||||
|
||||
$asset->customFill($request, Auth::user()); // Update custom fields in the database.
|
||||
// Update custom fields in the database.
|
||||
// Validation for these fields is handled through the AssetRequest form request
|
||||
$model = AssetModel::find($request->get('model_id'));
|
||||
|
||||
if (($model) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('admin')) {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = \Crypt::encrypt(implode(', ', $request->input($field->db_column)));
|
||||
} else {
|
||||
$asset->{$field->db_column} = \Crypt::encrypt($request->input($field->db_column));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = implode(', ', $request->input($field->db_column));
|
||||
} else {
|
||||
$asset->{$field->db_column} = $request->input($field->db_column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the asset before saving
|
||||
if ($asset->isValid() && $asset->save()) {
|
||||
@@ -292,9 +311,7 @@ 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->asset_eol_date = request('asset_eol_date', null);
|
||||
|
||||
$asset->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost', null));
|
||||
$asset->purchase_date = $request->input('purchase_date', null);
|
||||
$asset->supplier_id = $request->input('supplier_id', null);
|
||||
$asset->expected_checkin = $request->input('expected_checkin', null);
|
||||
@@ -304,12 +321,6 @@ class AssetsController extends Controller
|
||||
$asset->rtd_location_id = $request->input('rtd_location_id', null);
|
||||
$asset->byod = $request->input('byod', 0);
|
||||
|
||||
$status = Statuslabel::find($asset->status_id);
|
||||
|
||||
if($status->archived){
|
||||
$asset->assigned_to = null;
|
||||
}
|
||||
|
||||
if ($asset->assigned_to == '') {
|
||||
$asset->location_id = $request->input('rtd_location_id', null);
|
||||
}
|
||||
@@ -432,12 +443,11 @@ class AssetsController extends Controller
|
||||
* @since [v3.0]
|
||||
* @return Redirect
|
||||
*/
|
||||
public function getAssetByTag(Request $request, $tag=null)
|
||||
public function getAssetByTag(Request $request)
|
||||
{
|
||||
$tag = $tag ? $tag : $request->get('assetTag');
|
||||
$topsearch = ($request->get('topsearch') == 'true');
|
||||
|
||||
if (! $asset = Asset::where('asset_tag', '=', $tag)->first()) {
|
||||
if (! $asset = Asset::where('asset_tag', '=', $request->get('assetTag'))->first()) {
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
$this->authorize('view', $asset);
|
||||
@@ -534,11 +544,9 @@ class AssetsController extends Controller
|
||||
$asset = Asset::find($assetId);
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
return (new Label())
|
||||
->with('assets', collect([ $asset ]))
|
||||
return view('hardware/labels')
|
||||
->with('assets', Asset::find($asset))
|
||||
->with('settings', Setting::getSettings())
|
||||
->with('template', request()->get('template'))
|
||||
->with('offset', request()->get('offset'))
|
||||
->with('bulkedit', false)
|
||||
->with('count', 0);
|
||||
}
|
||||
@@ -616,11 +624,7 @@ class AssetsController extends Controller
|
||||
$csv->setHeaderOffset(0);
|
||||
$header = $csv->getHeader();
|
||||
$isCheckinHeaderExplicit = in_array('checkin date', (array_map('strtolower', $header)));
|
||||
try {
|
||||
$results = $csv->getRecords();
|
||||
} catch (\Exception $e) {
|
||||
return back()->with('error', trans('general.error_in_import_file', ['error' => $e->getMessage()]));
|
||||
}
|
||||
$results = $csv->getRecords();
|
||||
$item = [];
|
||||
$status = [];
|
||||
$status['error'] = [];
|
||||
@@ -756,7 +760,7 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* Restore a deleted asset.
|
||||
* Retore a deleted asset.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
|
||||
@@ -8,13 +8,11 @@ use App\Http\Controllers\CheckInOutRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
use App\View\Label;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use App\Http\Requests\AssetCheckoutRequest;
|
||||
use App\Models\CustomField;
|
||||
|
||||
class BulkAssetsController extends Controller
|
||||
{
|
||||
@@ -31,8 +29,8 @@ class BulkAssetsController extends Controller
|
||||
*/
|
||||
public function edit(Request $request)
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
if (! $request->filled('ids')) {
|
||||
return redirect()->back()->with('error', trans('admin/hardware/message.update.no_assets_selected'));
|
||||
}
|
||||
@@ -42,59 +40,26 @@ class BulkAssetsController extends Controller
|
||||
session(['bulk_back_url' => $bulk_back_url]);
|
||||
|
||||
$asset_ids = array_values(array_unique($request->input('ids')));
|
||||
|
||||
//custom fields logic
|
||||
$asset_custom_field = Asset::with(['model.fieldset.fields', 'model'])->whereIn('id', $asset_ids)->whereHas('model', function ($query) {
|
||||
return $query->where('fieldset_id', '!=', null);
|
||||
})->get();
|
||||
|
||||
$models = $asset_custom_field->unique('model_id');
|
||||
$modelNames = [];
|
||||
foreach($models as $model) {
|
||||
$modelNames[] = $model->model->name;
|
||||
}
|
||||
|
||||
if ($request->filled('bulk_actions')) {
|
||||
switch ($request->input('bulk_actions')) {
|
||||
case 'labels':
|
||||
$this->authorize('view', Asset::class);
|
||||
$assets_found = Asset::find($asset_ids);
|
||||
|
||||
if ($assets_found->isEmpty()){
|
||||
return redirect()->back();
|
||||
}
|
||||
|
||||
return (new Label)
|
||||
->with('assets', $assets_found)
|
||||
return view('hardware/labels')
|
||||
->with('assets', Asset::find($asset_ids))
|
||||
->with('settings', Setting::getSettings())
|
||||
->with('bulkedit', true)
|
||||
->with('count', 0);
|
||||
|
||||
case 'delete':
|
||||
$this->authorize('delete', Asset::class);
|
||||
$assets = Asset::with('assignedTo', 'location')->find($asset_ids);
|
||||
$assets->each(function ($asset) {
|
||||
$this->authorize('delete', $asset);
|
||||
});
|
||||
|
||||
return view('hardware/bulk-delete')->with('assets', $assets);
|
||||
|
||||
case 'restore':
|
||||
$this->authorize('update', Asset::class);
|
||||
$assets = Asset::withTrashed()->find($asset_ids);
|
||||
$assets->each(function ($asset) {
|
||||
$this->authorize('delete', $asset);
|
||||
});
|
||||
|
||||
return view('hardware/bulk-restore')->with('assets', $assets);
|
||||
|
||||
case 'edit':
|
||||
$this->authorize('update', Asset::class);
|
||||
return view('hardware/bulk')
|
||||
->with('assets', $asset_ids)
|
||||
->with('statuslabel_list', Helper::statusLabelList())
|
||||
->with('models', $models->pluck(['model']))
|
||||
->with('modelNames', $modelNames);
|
||||
->with('statuslabel_list', Helper::statusLabelList());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -112,7 +77,6 @@ class BulkAssetsController extends Controller
|
||||
public function update(Request $request)
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
$error_bag = [];
|
||||
|
||||
// Get the back url from the session and then destroy the session
|
||||
$bulk_back_url = route('hardware.index');
|
||||
@@ -121,21 +85,12 @@ class BulkAssetsController extends Controller
|
||||
}
|
||||
|
||||
|
||||
$custom_field_columns = CustomField::all()->pluck('db_column')->toArray();
|
||||
|
||||
if(Session::exists('ids')) {
|
||||
$assets = Session::get('ids');
|
||||
} elseif (! $request->filled('ids') || count($request->input('ids')) <= 0) {
|
||||
if (! $request->filled('ids') || count($request->input('ids')) <= 0) {
|
||||
return redirect($bulk_back_url)->with('error', trans('admin/hardware/message.update.no_assets_selected'));
|
||||
}
|
||||
|
||||
|
||||
$assets = array_keys($request->input('ids'));
|
||||
|
||||
if ($request->anyFilled($custom_field_columns)) {
|
||||
$custom_fields_present = true;
|
||||
} else {
|
||||
$custom_fields_present = false;
|
||||
}
|
||||
|
||||
if (($request->filled('purchase_date'))
|
||||
|| ($request->filled('expected_checkin'))
|
||||
|| ($request->filled('purchase_cost'))
|
||||
@@ -147,12 +102,8 @@ class BulkAssetsController extends Controller
|
||||
|| ($request->filled('company_id'))
|
||||
|| ($request->filled('status_id'))
|
||||
|| ($request->filled('model_id'))
|
||||
|| ($request->filled('next_audit_date'))
|
||||
|| ($request->filled('null_purchase_date'))
|
||||
|| ($request->filled('null_expected_checkin_date'))
|
||||
|| ($request->filled('null_next_audit_date'))
|
||||
|| ($request->anyFilled($custom_field_columns))
|
||||
|
||||
) {
|
||||
foreach ($assets as $assetId) {
|
||||
|
||||
@@ -165,11 +116,7 @@ class BulkAssetsController extends Controller
|
||||
->conditionallyAddItem('requestable')
|
||||
->conditionallyAddItem('status_id')
|
||||
->conditionallyAddItem('supplier_id')
|
||||
->conditionallyAddItem('warranty_months')
|
||||
->conditionallyAddItem('next_audit_date');
|
||||
foreach ($custom_field_columns as $key => $custom_field_column) {
|
||||
$this->conditionallyAddItem($custom_field_column);
|
||||
}
|
||||
->conditionallyAddItem('warranty_months');
|
||||
|
||||
if ($request->input('null_purchase_date')=='1') {
|
||||
$this->update_array['purchase_date'] = null;
|
||||
@@ -179,12 +126,8 @@ class BulkAssetsController extends Controller
|
||||
$this->update_array['expected_checkin'] = null;
|
||||
}
|
||||
|
||||
if ($request->input('null_next_audit_date')=='1') {
|
||||
$this->update_array['next_audit_date'] = null;
|
||||
}
|
||||
|
||||
if ($request->filled('purchase_cost')) {
|
||||
$this->update_array['purchase_cost'] = $request->input('purchase_cost');
|
||||
$this->update_array['purchase_cost'] = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
}
|
||||
|
||||
if ($request->filled('company_id')) {
|
||||
@@ -202,11 +145,11 @@ class BulkAssetsController extends Controller
|
||||
}
|
||||
|
||||
$changed = [];
|
||||
$assetCollection = Asset::where('id' ,$assetId)->get();
|
||||
$asset = Asset::where('id' ,$assetId)->get();
|
||||
|
||||
foreach ($this->update_array as $key => $value) {
|
||||
if ($this->update_array[$key] != $assetCollection->toArray()[0][$key]) {
|
||||
$changed[$key]['old'] = $assetCollection->toArray()[0][$key];
|
||||
if ($this->update_array[$key] != $asset->toArray()[0][$key]) {
|
||||
$changed[$key]['old'] = $asset->toArray()[0][$key];
|
||||
$changed[$key]['new'] = $this->update_array[$key];
|
||||
}
|
||||
}
|
||||
@@ -218,47 +161,17 @@ class BulkAssetsController extends Controller
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->log_meta = json_encode($changed);
|
||||
$logAction->logaction('update');
|
||||
|
||||
if($custom_fields_present) {
|
||||
$asset = Asset::find($assetId);
|
||||
$assetCustomFields = $asset->model()->first()->fieldset;
|
||||
if($assetCustomFields && $assetCustomFields->fields) {
|
||||
foreach ($assetCustomFields->fields as $field) {
|
||||
if (array_key_exists($field->db_column, $this->update_array)) {
|
||||
$asset->{$field->db_column} = $this->update_array[$field->db_column];
|
||||
$saved = $asset->save();
|
||||
if(!$saved) {
|
||||
$error_bag[] = $asset->getErrors();
|
||||
}
|
||||
continue;
|
||||
} else {
|
||||
$array = $this->update_array;
|
||||
array_except($array, $field->db_column);
|
||||
$asset->save($array);
|
||||
}
|
||||
if (!$asset->save()) {
|
||||
$error_bag[] = $asset->getErrors();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
Asset::find($assetId)->update($this->update_array);
|
||||
}
|
||||
}
|
||||
if(!empty($error_bag)) {
|
||||
$errors = [];
|
||||
//find the customfield name from the name of the messagebag items
|
||||
foreach ($error_bag as $key => $bag) {
|
||||
foreach($bag->keys() as $key => $value) {
|
||||
CustomField::where('db_column', $value)->get()->map(function($item) use (&$errors) {
|
||||
$errors[] = $item->name;
|
||||
});
|
||||
}
|
||||
}
|
||||
return redirect($bulk_back_url)->with('bulk_errors', array_unique($errors));
|
||||
}
|
||||
|
||||
DB::table('assets')
|
||||
->where('id', $assetId)
|
||||
->update($this->update_array);
|
||||
} // endforeach
|
||||
|
||||
return redirect($bulk_back_url)->with('success', trans('admin/hardware/message.update.success'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
// no values given, nothing to update
|
||||
return redirect($bulk_back_url)->with('warning', trans('admin/hardware/message.update.nothing_updated'));
|
||||
}
|
||||
@@ -375,8 +288,7 @@ class BulkAssetsController extends Controller
|
||||
foreach ($asset_ids as $asset_id) {
|
||||
$asset = Asset::findOrFail($asset_id);
|
||||
$this->authorize('checkout', $asset);
|
||||
|
||||
$error = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), $asset->name, null);
|
||||
$error = $asset->checkOut($target, $admin, $checkout_at, $expected_checkin, e($request->get('note')), null);
|
||||
|
||||
if ($target->location_id != '') {
|
||||
$asset->location_id = $target->location_id;
|
||||
@@ -399,19 +311,5 @@ class BulkAssetsController extends Controller
|
||||
} catch (ModelNotFoundException $e) {
|
||||
return redirect()->route('hardware.bulkcheckout.show')->with('error', $e->getErrors());
|
||||
}
|
||||
|
||||
}
|
||||
public function restore(Request $request) {
|
||||
$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'));
|
||||
} else {
|
||||
foreach ($assetIds as $key => $assetId) {
|
||||
$asset = Asset::withTrashed()->find($assetId);
|
||||
$asset->restore();
|
||||
}
|
||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.restore.success'));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -92,7 +92,7 @@ class BulkAssetModelsController extends Controller
|
||||
AssetModel::whereIn('id', $models_raw_array)->update($update_array);
|
||||
|
||||
return redirect()->route('models.index')
|
||||
->with('success', trans_choice('admin/models/message.bulkedit.success', count($models_raw_array), ['model_count' => count($models_raw_array)]));
|
||||
->with('success', trans('admin/models/message.bulkedit.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('models.index')
|
||||
|
||||
@@ -60,9 +60,6 @@ final class CompaniesController extends Controller
|
||||
|
||||
$company = new Company;
|
||||
$company->name = $request->input('name');
|
||||
$company->phone = $request->input('phone');
|
||||
$company->fax = $request->input('fax');
|
||||
$company->email = $request->input('email');
|
||||
|
||||
$company = $request->handleImages($company);
|
||||
|
||||
@@ -114,9 +111,6 @@ final class CompaniesController extends Controller
|
||||
$this->authorize('update', $company);
|
||||
|
||||
$company->name = $request->input('name');
|
||||
$company->phone = $request->input('phone');
|
||||
$company->fax = $request->input('fax');
|
||||
$company->email = $request->input('email');
|
||||
|
||||
$company = $request->handleImages($company);
|
||||
|
||||
@@ -125,7 +119,8 @@ final class CompaniesController extends Controller
|
||||
->with('success', trans('admin/companies/message.update.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($company->getErrors());
|
||||
return redirect()->route('companies.edit', ['company' => $companyId])
|
||||
->with('error', trans('admin/companies/message.update.error'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -33,11 +33,6 @@ class ComponentCheckoutController extends Controller
|
||||
}
|
||||
$this->authorize('checkout', $component);
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($component->numRemaining() <= 0){
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
return view('components/checkout', compact('component'));
|
||||
}
|
||||
|
||||
@@ -55,7 +50,7 @@ class ComponentCheckoutController extends Controller
|
||||
public function store(Request $request, $componentId)
|
||||
{
|
||||
// Check if the component exists
|
||||
if (!$component = Component::find($componentId)) {
|
||||
if (is_null($component = Component::find($componentId))) {
|
||||
// Redirect to the component management page with error
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found'));
|
||||
}
|
||||
@@ -63,15 +58,9 @@ class ComponentCheckoutController extends Controller
|
||||
$this->authorize('checkout', $component);
|
||||
|
||||
$max_to_checkout = $component->numRemaining();
|
||||
|
||||
// Make sure there are at least the requested number of components available to checkout
|
||||
if ($max_to_checkout < $request->get('assigned_qty')) {
|
||||
return redirect()->back()->withInput()->with('error', trans('admin/components/message.checkout.unavailable', ['remaining' => $max_to_checkout, 'requested' => $request->get('assigned_qty')]));
|
||||
}
|
||||
|
||||
$validator = Validator::make($request->all(), [
|
||||
'asset_id' => 'required|exists:assets,id',
|
||||
'assigned_qty' => "required|numeric|min:1|digits_between:1,$max_to_checkout",
|
||||
'asset_id' => 'required',
|
||||
'assigned_qty' => "required|numeric|between:1,$max_to_checkout",
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
@@ -80,17 +69,24 @@ class ComponentCheckoutController extends Controller
|
||||
->withInput();
|
||||
}
|
||||
|
||||
$admin_user = Auth::user();
|
||||
$asset_id = e($request->input('asset_id'));
|
||||
|
||||
// Check if the user exists
|
||||
$asset = Asset::find($request->input('asset_id'));
|
||||
if (is_null($asset = Asset::find($asset_id))) {
|
||||
// Redirect to the component management page with error
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.asset_does_not_exist'));
|
||||
}
|
||||
|
||||
// Update the component data
|
||||
$component->asset_id = $request->input('asset_id');
|
||||
$component->asset_id = $asset_id;
|
||||
|
||||
$component->assets()->attach($component->id, [
|
||||
'component_id' => $component->id,
|
||||
'user_id' => Auth::user(),
|
||||
'user_id' => $admin_user->id,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'assigned_qty' => $request->input('assigned_qty'),
|
||||
'asset_id' => $request->input('asset_id'),
|
||||
'asset_id' => $asset_id,
|
||||
'note' => $request->input('note'),
|
||||
]);
|
||||
|
||||
|
||||
@@ -71,14 +71,13 @@ class ComponentsController extends Controller
|
||||
$component = new Component();
|
||||
$component->name = $request->input('name');
|
||||
$component->category_id = $request->input('category_id');
|
||||
$component->supplier_id = $request->input('supplier_id');
|
||||
$component->location_id = $request->input('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$component->order_number = $request->input('order_number', null);
|
||||
$component->min_amt = $request->input('min_amt', null);
|
||||
$component->serial = $request->input('serial', null);
|
||||
$component->purchase_date = $request->input('purchase_date', null);
|
||||
$component->purchase_cost = $request->input('purchase_cost', null);
|
||||
$component->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost', null));
|
||||
$component->qty = $request->input('qty');
|
||||
$component->user_id = Auth::id();
|
||||
$component->notes = $request->input('notes');
|
||||
@@ -146,14 +145,13 @@ class ComponentsController extends Controller
|
||||
// Update the component data
|
||||
$component->name = $request->input('name');
|
||||
$component->category_id = $request->input('category_id');
|
||||
$component->supplier_id = $request->input('supplier_id');
|
||||
$component->location_id = $request->input('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$component->order_number = $request->input('order_number');
|
||||
$component->min_amt = $request->input('min_amt');
|
||||
$component->serial = $request->input('serial');
|
||||
$component->purchase_date = $request->input('purchase_date');
|
||||
$component->purchase_cost = request('purchase_cost');
|
||||
$component->purchase_cost = Helper::ParseCurrency(request('purchase_cost'));
|
||||
$component->qty = $request->input('qty');
|
||||
$component->notes = $request->input('notes');
|
||||
|
||||
|
||||
@@ -132,7 +132,7 @@ class ComponentsFilesController extends Controller
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($componentId = null, $fileId = null)
|
||||
public function show($componentId = null, $fileId = null, $download = true)
|
||||
{
|
||||
\Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||
$component = Component::find($componentId);
|
||||
@@ -157,17 +157,21 @@ class ComponentsFilesController extends Controller
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
} else {
|
||||
if ($download != 'true') {
|
||||
\Log::debug('display the file');
|
||||
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
|
||||
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
|
||||
}
|
||||
|
||||
return JsonResponse::create(['error' => 'Failed validation: '], 500);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -24,16 +24,9 @@ class ConsumableCheckoutController extends Controller
|
||||
*/
|
||||
public function create($consumableId)
|
||||
{
|
||||
|
||||
if (is_null($consumable = Consumable::with('users')->find($consumableId))) {
|
||||
if (is_null($consumable = Consumable::find($consumableId))) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0){
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $consumable);
|
||||
|
||||
return view('consumables/checkout', compact('consumable'));
|
||||
@@ -51,18 +44,12 @@ class ConsumableCheckoutController extends Controller
|
||||
*/
|
||||
public function store(Request $request, $consumableId)
|
||||
{
|
||||
if (is_null($consumable = Consumable::with('users')->find($consumableId))) {
|
||||
if (is_null($consumable = Consumable::find($consumableId))) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $consumable);
|
||||
|
||||
// Make sure there is at least one available to checkout
|
||||
if ($consumable->numRemaining() <= 0) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.checkout.unavailable'));
|
||||
}
|
||||
|
||||
|
||||
$admin_user = Auth::user();
|
||||
$assigned_to = e($request->input('assigned_to'));
|
||||
|
||||
|
||||
@@ -68,7 +68,6 @@ class ConsumablesController extends Controller
|
||||
$consumable = new Consumable();
|
||||
$consumable->name = $request->input('name');
|
||||
$consumable->category_id = $request->input('category_id');
|
||||
$consumable->supplier_id = $request->input('supplier_id');
|
||||
$consumable->location_id = $request->input('location_id');
|
||||
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$consumable->order_number = $request->input('order_number');
|
||||
@@ -77,7 +76,7 @@ class ConsumablesController extends Controller
|
||||
$consumable->model_number = $request->input('model_number');
|
||||
$consumable->item_no = $request->input('item_no');
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = $request->input('purchase_cost');
|
||||
$consumable->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
$consumable->qty = $request->input('qty');
|
||||
$consumable->user_id = Auth::id();
|
||||
$consumable->notes = $request->input('notes');
|
||||
@@ -145,7 +144,6 @@ class ConsumablesController extends Controller
|
||||
|
||||
$consumable->name = $request->input('name');
|
||||
$consumable->category_id = $request->input('category_id');
|
||||
$consumable->supplier_id = $request->input('supplier_id');
|
||||
$consumable->location_id = $request->input('location_id');
|
||||
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$consumable->order_number = $request->input('order_number');
|
||||
@@ -154,7 +152,7 @@ class ConsumablesController extends Controller
|
||||
$consumable->model_number = $request->input('model_number');
|
||||
$consumable->item_no = $request->input('item_no');
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = $request->input('purchase_cost');
|
||||
$consumable->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
$consumable->qty = Helper::ParseFloat($request->input('qty'));
|
||||
$consumable->notes = $request->input('notes');
|
||||
|
||||
|
||||
@@ -131,7 +131,7 @@ class ConsumablesFilesController extends Controller
|
||||
* @return \Symfony\Consumable\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($consumableId = null, $fileId = null)
|
||||
public function show($consumableId = null, $fileId = null, $download = true)
|
||||
{
|
||||
$consumable = Consumable::find($consumableId);
|
||||
|
||||
@@ -155,19 +155,22 @@ class ConsumablesFilesController extends Controller
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
|
||||
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
|
||||
// won't work, as they're not accessible via the web
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
} else {
|
||||
if ($download != 'true') {
|
||||
\Log::debug('display the file');
|
||||
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
|
||||
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
|
||||
}
|
||||
|
||||
return JsonResponse::create(['error' => 'Failed validation: '], 500);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -9,11 +9,11 @@
|
||||
*
|
||||
* **THIS DOCUMENTATION DOES NOT COVER INSTALLATION.** If you're here and you're not a
|
||||
* developer, you're probably in the wrong place. Please see the
|
||||
* [Installation documentation](https://snipe-it.readme.io) for
|
||||
* [Installation documentation](http://docs.snipeitapp.com) for
|
||||
* information on how to install Snipe-IT.
|
||||
*
|
||||
* To learn how to set up a development environment and get started developing for Snipe-IT,
|
||||
* please see the [contributing documentation](https://snipe-it.readme.io/docs/contributing-overview).
|
||||
* please see the [contributing documentation](http://docs.snipeitapp.com/contributing.html).
|
||||
*
|
||||
* Only the Snipe-IT specific controllers, models, helpers, service providers,
|
||||
* etc have been included in this documentation (excluding vendors, Laravel core, etc)
|
||||
|
||||
@@ -6,12 +6,9 @@ use App\Helpers\Helper;
|
||||
use App\Http\Requests\CustomFieldRequest;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Redirect;
|
||||
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Custom Asset Fields for
|
||||
* the Snipe-IT Asset Management application.
|
||||
@@ -23,7 +20,6 @@ use Redirect;
|
||||
*/
|
||||
class CustomFieldsController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns a view with a listing of custom fields.
|
||||
*
|
||||
@@ -32,16 +28,12 @@ class CustomFieldsController extends Controller
|
||||
* @return \Illuminate\Support\Facades\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index(Request $request)
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('view', CustomField::class);
|
||||
if ( $request->input('tab') == 1 ) {
|
||||
// Users section, make sure to auto-create the first fieldset if so
|
||||
CustomFieldset::firstOrCreate(['type' => Helper::$itemtypes_having_custom_fields[1]], ['name' => 'default']);
|
||||
}
|
||||
|
||||
$fieldsets = CustomFieldset::with('fields')->where("type", Helper::$itemtypes_having_custom_fields[$request->get('tab',0)])->get(); //cannot eager-load 'customizable' because it's not a relation
|
||||
$fields = CustomField::with('fieldset')->where("type", Helper::$itemtypes_having_custom_fields[$request->get('tab',0)])->get();
|
||||
$fieldsets = CustomFieldset::with('fields', 'models')->get();
|
||||
$fields = CustomField::with('fieldset')->get();
|
||||
|
||||
return view('custom_fields.index')->with('custom_fieldsets', $fieldsets)->with('custom_fields', $fields);
|
||||
}
|
||||
@@ -53,7 +45,7 @@ class CustomFieldsController extends Controller
|
||||
* @see CustomFieldsController::storeField()
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v5.1.5]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show()
|
||||
@@ -71,17 +63,14 @@ class CustomFieldsController extends Controller
|
||||
* @return \Illuminate\Support\Facades\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create(Request $request)
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', CustomField::class);
|
||||
$fieldsets = CustomFieldset::where('type', Helper::$itemtypes_having_custom_fields[$request->get('tab')])->get();
|
||||
|
||||
return view('custom_fields.fields.edit', [
|
||||
'predefinedFormats' => Helper::predefined_formats(),
|
||||
'customFormat' => '',
|
||||
'fieldsets' => $fieldsets,
|
||||
'field' => new CustomField(),
|
||||
]);
|
||||
'customFormat' => '',
|
||||
])->with('field', new CustomField());
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -90,7 +79,7 @@ class CustomFieldsController extends Controller
|
||||
* @see CustomFieldsController::createField()
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(CustomFieldRequest $request)
|
||||
@@ -115,12 +104,8 @@ class CustomFieldsController extends Controller
|
||||
"show_in_email" => $show_in_email,
|
||||
"is_unique" => $request->get("is_unique", 0),
|
||||
"display_in_user_view" => $display_in_user_view,
|
||||
"auto_add_to_fieldsets" => $request->get("auto_add_to_fieldsets", 0),
|
||||
"show_in_listview" => $request->get("show_in_listview", 0),
|
||||
"user_id" => Auth::id(),
|
||||
"user_id" => Auth::id()
|
||||
]);
|
||||
// not mass-assignable; must be manual
|
||||
$field->type = Helper::$itemtypes_having_custom_fields[$request->get('tab')];
|
||||
|
||||
|
||||
if ($request->filled('custom_format')) {
|
||||
@@ -130,23 +115,10 @@ class CustomFieldsController extends Controller
|
||||
}
|
||||
|
||||
if ($field->save()) {
|
||||
|
||||
// Sync fields with fieldsets
|
||||
$fieldset_array = $request->input('associate_fieldsets');
|
||||
if ($request->get('tab') == 1 ) {
|
||||
$fieldset_array = [CustomFieldset::firstOrCreate(['type' => User::class],['name' => 'default'])->id => true];
|
||||
}
|
||||
if (($request->has('associate_fieldsets') || $request->get('tab') == 1) && (is_array($fieldset_array))) {
|
||||
$field->fieldset()->sync(array_keys($fieldset_array));
|
||||
} else {
|
||||
$field->fieldset()->sync([]);
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('fields.index',['tab' => $request->get('tab',0)])->with('success', trans('admin/custom_fields/message.field.create.success'));
|
||||
return redirect()->route('fields.index')->with('success', trans('admin/custom_fields/message.field.create.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('selected_fieldsets', $request->input('associate_fieldsets'))->withInput()
|
||||
return redirect()->back()->withInput()
|
||||
->with('error', trans('admin/custom_fields/message.field.create.error'));
|
||||
}
|
||||
|
||||
@@ -156,7 +128,7 @@ class CustomFieldsController extends Controller
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function deleteFieldFromFieldset($field_id, $fieldset_id)
|
||||
@@ -175,7 +147,8 @@ class CustomFieldsController extends Controller
|
||||
->with('success', trans('admin/custom_fields/message.field.delete.success'));
|
||||
} else {
|
||||
return redirect()->back()->withErrors(['message' => "Field is in use and cannot be deleted."]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return redirect()->back()->withErrors(['message' => "Error deleting field from fieldset"]);
|
||||
@@ -188,7 +161,7 @@ class CustomFieldsController extends Controller
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($field_id)
|
||||
@@ -196,17 +169,12 @@ class CustomFieldsController extends Controller
|
||||
if ($field = CustomField::find($field_id)) {
|
||||
$this->authorize('delete', $field);
|
||||
|
||||
if ($field->type == User::class) {
|
||||
$field->fieldset()->detach(); // remove from 'default' group (and others, if they exist in the future!)
|
||||
}
|
||||
if (($field->fieldset) && ($field->fieldset->count() > 0)) {
|
||||
return redirect()->back()->withErrors(['message' => 'Field is in-use']);
|
||||
}
|
||||
$type = $field->type;
|
||||
$field->delete();
|
||||
return redirect()->route('fields.index',['tab' => array_search($type, Helper::$itemtypes_having_custom_fields)])
|
||||
|
||||
->with('success', trans('admin/custom_fields/message.field.delete.success'));
|
||||
return redirect()->route("fields.index")
|
||||
->with("success", trans('admin/custom_fields/message.field.delete.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withErrors(['message' => 'Field does not exist']);
|
||||
@@ -222,12 +190,12 @@ class CustomFieldsController extends Controller
|
||||
* @return \Illuminate\Support\Facades\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit(Request $request, $id)
|
||||
public function edit($id)
|
||||
{
|
||||
if ($field = CustomField::find($id)) {
|
||||
|
||||
$this->authorize('update', $field);
|
||||
$fieldsets = CustomFieldset::get();
|
||||
|
||||
$customFormat = '';
|
||||
if ((stripos($field->format, 'regex') === 0) && ($field->format !== CustomField::PREDEFINED_FORMATS['MAC'])) {
|
||||
$customFormat = $field->format;
|
||||
@@ -236,7 +204,6 @@ class CustomFieldsController extends Controller
|
||||
return view('custom_fields.fields.edit', [
|
||||
'field' => $field,
|
||||
'customFormat' => $customFormat,
|
||||
'fieldsets' => $fieldsets,
|
||||
'predefinedFormats' => Helper::predefined_formats(),
|
||||
]);
|
||||
}
|
||||
@@ -255,7 +222,7 @@ class CustomFieldsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $id
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(CustomFieldRequest $request, $id)
|
||||
@@ -282,8 +249,6 @@ class CustomFieldsController extends Controller
|
||||
$field->show_in_email = $show_in_email;
|
||||
$field->is_unique = $request->get("is_unique", 0);
|
||||
$field->display_in_user_view = $display_in_user_view;
|
||||
$field->auto_add_to_fieldsets = $request->get("auto_add_to_fieldsets", 0);
|
||||
$field->show_in_listview = $request->get("show_in_listview", 0);
|
||||
|
||||
if ($request->get('format') == 'CUSTOM REGEX') {
|
||||
$field->format = e($request->get('custom_format'));
|
||||
@@ -291,22 +256,12 @@ class CustomFieldsController extends Controller
|
||||
$field->format = e($request->get('format'));
|
||||
}
|
||||
|
||||
if ($field->element == 'checkbox' || $field->element == 'radio'){
|
||||
if($field->element == 'checkbox' || $field->element == 'radio'){
|
||||
$field->format = 'ANY';
|
||||
}
|
||||
|
||||
if ($field->save()) {
|
||||
|
||||
|
||||
// Sync fields with fieldsets
|
||||
$fieldset_array = $request->input('associate_fieldsets');
|
||||
if ($request->has('associate_fieldsets') && (is_array($fieldset_array))) {
|
||||
$field->fieldset()->sync(array_keys($fieldset_array));
|
||||
} else {
|
||||
$field->fieldset()->sync([]);
|
||||
}
|
||||
|
||||
return redirect()->route('fields.index',['tab' => $request->get('tab',0)])->with('success', trans('admin/custom_fields/message.field.update.success'));
|
||||
return redirect()->route('fields.index')->with('success', trans('admin/custom_fields/message.field.update.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.update.error'));
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
@@ -39,7 +38,7 @@ class CustomFieldsetsController extends Controller
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function show( $id)
|
||||
public function show($id)
|
||||
{
|
||||
$cfset = CustomFieldset::with('fields')
|
||||
->where('id', '=', $id)->orderBy('id', 'ASC')->first();
|
||||
@@ -47,7 +46,7 @@ class CustomFieldsetsController extends Controller
|
||||
$this->authorize('view', $cfset);
|
||||
|
||||
if ($cfset) {
|
||||
$custom_fields_list = ['' => 'Add New Field to Fieldset'] + CustomField::where('type', $cfset->type)->pluck('name', 'id')->toArray();
|
||||
$custom_fields_list = ['' => 'Add New Field to Fieldset'] + CustomField::pluck('name', 'id')->toArray();
|
||||
|
||||
$maxid = 0;
|
||||
foreach ($cfset->fields as $field) {
|
||||
@@ -94,29 +93,16 @@ class CustomFieldsetsController extends Controller
|
||||
{
|
||||
$this->authorize('create', CustomField::class);
|
||||
|
||||
$fieldset = new CustomFieldset([
|
||||
'name' => $request->get('name'),
|
||||
$cfset = new CustomFieldset([
|
||||
'name' => e($request->get('name')),
|
||||
'user_id' => Auth::user()->id,
|
||||
'type' => Helper::$itemtypes_having_custom_fields[$request->get('tab')]
|
||||
// 'sub' =>
|
||||
]);
|
||||
|
||||
$validator = Validator::make($request->all(), $fieldset->rules);
|
||||
|
||||
$validator = Validator::make($request->all(), $cfset->rules);
|
||||
if ($validator->passes()) {
|
||||
$fieldset->save();
|
||||
$cfset->save();
|
||||
|
||||
// Sync fieldset with auto_add_to_fieldsets
|
||||
$fields = CustomField::select('id')->where('auto_add_to_fieldsets', '=', '1')->get();
|
||||
if ($fields->count() > 0) {
|
||||
foreach ($fields as $field) {
|
||||
$field_ids[] = $field->id;
|
||||
}
|
||||
|
||||
$fieldset->fields()->sync($field_ids);
|
||||
}
|
||||
|
||||
return redirect()->route('fieldsets.show', [$fieldset->id])
|
||||
return redirect()->route('fieldsets.show', [$cfset->id])
|
||||
->with('success', trans('admin/custom_fields/message.fieldset.create.success'));
|
||||
}
|
||||
|
||||
|
||||
@@ -170,8 +170,6 @@ class DepartmentsController extends Controller
|
||||
$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);
|
||||
$department->phone = $request->input('phone');
|
||||
$department->fax = $request->input('fax');
|
||||
|
||||
$department = $request->handleImages($department);
|
||||
|
||||
|
||||
@@ -1,74 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Laravel\Socialite\Facades\Socialite;
|
||||
use Laravel\Socialite\Two\InvalidStateException;
|
||||
use App\Models\Setting;
|
||||
|
||||
|
||||
class GoogleAuthController extends Controller
|
||||
{
|
||||
/**
|
||||
* We need this constructor so that we override the socialite expected config variables,
|
||||
* since we want to allow this to be changed via database fields
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
$setting = Setting::getSettings();
|
||||
config(['services.google.redirect' => config('app.url').'/google/callback']);
|
||||
config(['services.google.client_id' => $setting->google_client_id]);
|
||||
config(['services.google.client_secret' => $setting->google_client_secret]);
|
||||
}
|
||||
|
||||
public function redirectToGoogle()
|
||||
{
|
||||
return Socialite::driver('google')->redirect();
|
||||
}
|
||||
|
||||
public function handleGoogleCallback()
|
||||
{
|
||||
try {
|
||||
$socialUser = Socialite::driver('google')->user();
|
||||
\Log::debug('Google user found in Google Workspace');
|
||||
} catch (InvalidStateException $exception) {
|
||||
\Log::debug('Google user NOT found in Google Workspace');
|
||||
return redirect()->route('login')
|
||||
->withErrors(
|
||||
[
|
||||
'username' => [
|
||||
trans('auth/general.google_login_failed')
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
$user = User::where('username', $socialUser->getEmail())->first();
|
||||
|
||||
|
||||
if ($user) {
|
||||
\Log::debug('Google user '.$socialUser->getEmail().' found in Snipe-IT');
|
||||
$user->update([
|
||||
'avatar' => $socialUser->avatar,
|
||||
]);
|
||||
|
||||
Auth::login($user, true);
|
||||
return redirect()->route('home');
|
||||
}
|
||||
|
||||
\Log::debug('Google user '.$socialUser->getEmail().' NOT found in Snipe-IT');
|
||||
return redirect()->route('login')
|
||||
->withErrors(
|
||||
[
|
||||
'username' => [
|
||||
trans('auth/general.google_login_failed'),
|
||||
],
|
||||
]
|
||||
);
|
||||
}
|
||||
}
|
||||
@@ -92,7 +92,7 @@ class GroupsController extends Controller
|
||||
return view('groups.edit', compact('group', 'permissions', 'selected_array', 'groupPermissions'));
|
||||
}
|
||||
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', ['id' => $id]));
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -107,7 +107,7 @@ class GroupsController extends Controller
|
||||
public function update(Request $request, $id = null)
|
||||
{
|
||||
if (! $group = Group::find($id)) {
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', ['id' => $id]));
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
|
||||
}
|
||||
$group->name = $request->input('name');
|
||||
$group->permissions = json_encode($request->input('permission'));
|
||||
@@ -133,13 +133,14 @@ class GroupsController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function destroy($id)
|
||||
public function destroy($id = null)
|
||||
{
|
||||
if (! config('app.lock_passwords')) {
|
||||
if (! $group = Group::find($id)) {
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', ['id' => $id]));
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
|
||||
}
|
||||
$group->delete();
|
||||
// Redirect to the group management page
|
||||
return redirect()->route('groups.index')->with('success', trans('admin/groups/message.success.delete'));
|
||||
}
|
||||
|
||||
@@ -163,6 +164,6 @@ class GroupsController extends Controller
|
||||
return view('groups/view', compact('group'));
|
||||
}
|
||||
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', ['id' => $id]));
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
|
||||
}
|
||||
}
|
||||
|
||||
22
app/Http/Controllers/ImportsController.php
Normal file
22
app/Http/Controllers/ImportsController.php
Normal file
@@ -0,0 +1,22 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Transformers\ImportsTransformer;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Import;
|
||||
|
||||
class ImportsController extends Controller
|
||||
{
|
||||
/**
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('import');
|
||||
$imports = (new ImportsTransformer)->transformImports(Import::latest()->get());
|
||||
|
||||
return view('importer/import')->with('imports', $imports);
|
||||
}
|
||||
}
|
||||
@@ -1,77 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Category;
|
||||
use App\Models\Company;
|
||||
use App\Models\Labels\Label;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\Setting;
|
||||
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
|
||||
*
|
||||
* @author Grant Le Roux <grant.leroux+snipe-it@gmail.com>
|
||||
* @param string $labelName
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show(string $labelName)
|
||||
{
|
||||
$labelName = str_replace('/', '\\', $labelName);
|
||||
$template = Label::find($labelName);
|
||||
|
||||
$exampleAsset = new Asset();
|
||||
|
||||
$exampleAsset->id = 999999;
|
||||
$exampleAsset->name = 'JEN-867-5309';
|
||||
$exampleAsset->asset_tag = 'TCA-00001';
|
||||
$exampleAsset->serial = 'SN9876543210';
|
||||
|
||||
$exampleAsset->company = new Company();
|
||||
$exampleAsset->company->id = 999999;
|
||||
$exampleAsset->company->name = 'Test Company Limited';
|
||||
$exampleAsset->company->image = 'company-image-test.png';
|
||||
|
||||
$exampleAsset->assignedto = new User();
|
||||
$exampleAsset->assignedto->id = 999999;
|
||||
$exampleAsset->assignedto->first_name = 'Test';
|
||||
$exampleAsset->assignedto->last_name = 'Person';
|
||||
$exampleAsset->assignedto->username = 'Test.Person';
|
||||
$exampleAsset->assignedto->employee_num = '0123456789';
|
||||
|
||||
$exampleAsset->model = new AssetModel();
|
||||
$exampleAsset->model->id = 999999;
|
||||
$exampleAsset->model->name = 'Test Model';
|
||||
$exampleAsset->model->model_number = 'MDL5678';
|
||||
$exampleAsset->model->manufacturer = new Manufacturer();
|
||||
$exampleAsset->model->manufacturer->id = 999999;
|
||||
$exampleAsset->model->manufacturer->name = 'Test Manufacturing Inc.';
|
||||
$exampleAsset->model->category = new Category();
|
||||
$exampleAsset->model->category->id = 999999;
|
||||
$exampleAsset->model->category->name = 'Test Category';
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
if (request()->has('settings')) {
|
||||
$overrides = request()->get('settings');
|
||||
foreach ($overrides as $key => $value) {
|
||||
$settings->$key = $value;
|
||||
}
|
||||
}
|
||||
|
||||
return (new LabelView())
|
||||
->with('assets', collect([$exampleAsset]))
|
||||
->with('settings', $settings)
|
||||
->with('template', $template)
|
||||
->with('bulkedit', false)
|
||||
->with('count', 0);
|
||||
|
||||
return redirect()->route('home')->with('error', trans('admin/labels/message.does_not_exist'));
|
||||
}
|
||||
}
|
||||
@@ -59,12 +59,6 @@ class LicenseCheckinController extends Controller
|
||||
}
|
||||
|
||||
$license = License::find($licenseSeat->license_id);
|
||||
|
||||
// LicenseSeat is not assigned, it can't be checked in
|
||||
if (is_null($licenseSeat->assigned_to) && is_null($licenseSeat->asset_id)) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkin.error'));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
if (! $license->reassignable) {
|
||||
@@ -112,54 +106,4 @@ class LicenseCheckinController extends Controller
|
||||
// Redirect to the license page with error
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.checkin.error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk checkin all license seats
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LicenseCheckinController::create() method that provides the form view
|
||||
* @since [v6.1.1]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
|
||||
public function bulkCheckin(Request $request, $licenseId) {
|
||||
|
||||
$license = License::findOrFail($licenseId);
|
||||
$this->authorize('checkin', $license);
|
||||
|
||||
$licenseSeatsByUser = LicenseSeat::where('license_id', '=', $licenseId)
|
||||
->whereNotNull('assigned_to')
|
||||
->with('user')
|
||||
->get();
|
||||
|
||||
foreach ($licenseSeatsByUser as $user_seat) {
|
||||
$user_seat->assigned_to = null;
|
||||
|
||||
if ($user_seat->save()) {
|
||||
\Log::debug('Checking in '.$license->name.' from user '.$user_seat->username);
|
||||
$user_seat->logCheckin($user_seat->user, trans('admin/licenses/general.bulk.checkin_all.log_msg'));
|
||||
}
|
||||
}
|
||||
|
||||
$licenseSeatsByAsset = LicenseSeat::where('license_id', '=', $licenseId)
|
||||
->whereNotNull('asset_id')
|
||||
->with('asset')
|
||||
->get();
|
||||
|
||||
$count = 0;
|
||||
foreach ($licenseSeatsByAsset as $asset_seat) {
|
||||
$asset_seat->asset_id = null;
|
||||
|
||||
if ($asset_seat->save()) {
|
||||
\Log::debug('Checking in '.$license->name.' from asset '.$asset_seat->asset_tag);
|
||||
$asset_seat->logCheckin($asset_seat->asset, trans('admin/licenses/general.bulk.checkin_all.log_msg'));
|
||||
$count++;
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', trans_choice('admin/licenses/general.bulk.checkin_all.success', 2, ['count' => $count] ));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -30,17 +30,15 @@ class LicenseCheckoutController extends Controller
|
||||
// Check that the license is valid
|
||||
if ($license = License::find($licenseId)) {
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
// If the license is valid, check that there is an available seat
|
||||
if ($license->avail_seats_count < 1) {
|
||||
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
|
||||
}
|
||||
return view('licenses/checkout', compact('license'));
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
return view('licenses/checkout', compact('license'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -128,70 +126,4 @@ class LicenseCheckoutController extends Controller
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Bulk checkin all license seats
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LicenseCheckinController::create() method that provides the form view
|
||||
* @since [v6.1.1]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
|
||||
public function bulkCheckout($licenseId) {
|
||||
|
||||
\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');
|
||||
|
||||
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. ');
|
||||
}
|
||||
|
||||
// If the license is valid, check that there is an available seat
|
||||
if ($license->availCount()->count() < 1) {
|
||||
return redirect()->back()->with('error', trans('admin/licenses/general.bulk.checkout_all.error_no_seats'));
|
||||
}
|
||||
|
||||
|
||||
$assigned_count = 0;
|
||||
|
||||
foreach ($users as $user) {
|
||||
|
||||
// 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... ');
|
||||
continue;
|
||||
}
|
||||
|
||||
$licenseSeat = $license->freeSeat();
|
||||
|
||||
// Update the seat with checkout info
|
||||
$licenseSeat->assigned_to = $user->id;
|
||||
|
||||
if ($licenseSeat->save()) {
|
||||
$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);
|
||||
}
|
||||
|
||||
if ($avail_count == 0) {
|
||||
return redirect()->back()->with('warning', trans('admin/licenses/general.bulk.checkout_all.warn_not_enough_seats', ['count' => $assigned_count]));
|
||||
}
|
||||
}
|
||||
|
||||
if ($assigned_count == 0) {
|
||||
return redirect()->back()->with('warning', trans('admin/licenses/general.bulk.checkout_all.warn_no_avail_users', ['count' => $assigned_count]));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', trans_choice('admin/licenses/general.bulk.checkout_all.success', 2, ['count' => $assigned_count] ));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -91,30 +91,29 @@ class LicenseFilesController extends Controller
|
||||
*/
|
||||
public function destroy($licenseId = null, $fileId = null)
|
||||
{
|
||||
if ($license = License::find($licenseId)) {
|
||||
$license = License::find($licenseId);
|
||||
|
||||
// the asset is valid
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('update', $license);
|
||||
$log = Actionlog::find($fileId);
|
||||
|
||||
if ($log = Actionlog::find($fileId)) {
|
||||
|
||||
// Remove the file if one exists
|
||||
if (Storage::exists('licenses/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('licenses/'.$log->filename);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
// Remove the file if one exists
|
||||
if (Storage::exists('licenses/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('licenses/'.$log->filename);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('general.log_does_not_exist'));
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
@@ -130,6 +129,7 @@ class LicenseFilesController extends Controller
|
||||
*/
|
||||
public function show($licenseId = null, $fileId = null, $download = true)
|
||||
{
|
||||
\Log::info('Private filesystem is: '.config('filesystems.default'));
|
||||
$license = License::find($licenseId);
|
||||
|
||||
// the license is valid
|
||||
@@ -152,19 +152,21 @@ class LicenseFilesController extends Controller
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
|
||||
// won't work, as they're not accessible via the web
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
} else {
|
||||
if ($download != 'true') {
|
||||
\Log::debug('display the file');
|
||||
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
|
||||
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
|
||||
}
|
||||
|
||||
return JsonResponse::create(['error' => 'Failed validation: '], 500);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,8 +6,6 @@ use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Company;
|
||||
use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -88,7 +86,7 @@ class LicensesController extends Controller
|
||||
$license->name = $request->input('name');
|
||||
$license->notes = $request->input('notes');
|
||||
$license->order_number = $request->input('order_number');
|
||||
$license->purchase_cost = $request->input('purchase_cost');
|
||||
$license->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
$license->purchase_date = $request->input('purchase_date');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
@@ -166,7 +164,7 @@ class LicensesController extends Controller
|
||||
$license->name = $request->input('name');
|
||||
$license->notes = $request->input('notes');
|
||||
$license->order_number = $request->input('order_number');
|
||||
$license->purchase_cost = $request->input('purchase_cost');
|
||||
$license->purchase_cost = Helper::ParseCurrency($request->input('purchase_cost'));
|
||||
$license->purchase_date = $request->input('purchase_date');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->reassignable = $request->input('reassignable', 0);
|
||||
@@ -207,7 +205,7 @@ class LicensesController extends Controller
|
||||
if ($license->assigned_seats_count == 0) {
|
||||
// Delete the license and the associated license seats
|
||||
DB::table('license_seats')
|
||||
->where('license_id', $license->id)
|
||||
->where('id', $license->id)
|
||||
->update(['assigned_to' => null, 'asset_id' => null]);
|
||||
|
||||
$licenseSeats = $license->licenseseats();
|
||||
@@ -235,40 +233,16 @@ class LicensesController extends Controller
|
||||
{
|
||||
$license = License::with('assignedusers')->find($licenseId);
|
||||
|
||||
if (!$license) {
|
||||
return redirect()->route('licenses.index')
|
||||
->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
if ($license) {
|
||||
$this->authorize('view', $license);
|
||||
|
||||
return view('licenses/view', compact('license'));
|
||||
}
|
||||
|
||||
$users_count = User::where('autoassign_licenses', '1')->count();
|
||||
$total_seats_count = $license->totalSeatsByLicenseID();
|
||||
$available_seats_count = $license->availCount()->count();
|
||||
$checkedout_seats_count = ($total_seats_count - $available_seats_count);
|
||||
|
||||
\Log::debug('Total: '.$total_seats_count);
|
||||
\Log::debug('Users: '.$users_count);
|
||||
\Log::debug('Available: '.$available_seats_count);
|
||||
\Log::debug('Checkedout: '.$checkedout_seats_count);
|
||||
|
||||
|
||||
$this->authorize('view', $license);
|
||||
return view('licenses.view', compact('license'))
|
||||
->with('users_count', $users_count)
|
||||
->with('total_seats_count', $total_seats_count)
|
||||
->with('available_seats_count', $available_seats_count)
|
||||
->with('checkedout_seats_count', $checkedout_seats_count);
|
||||
|
||||
return redirect()->route('licenses.index')
|
||||
->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view with prepopulated data for clone
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function getClone($licenseId = null)
|
||||
{
|
||||
if (is_null($license_to_clone = License::find($licenseId))) {
|
||||
|
||||
@@ -79,8 +79,6 @@ class LocationsController extends Controller
|
||||
$location->ldap_ou = $request->input('ldap_ou');
|
||||
$location->manager_id = $request->input('manager_id');
|
||||
$location->user_id = Auth::id();
|
||||
$location->phone = request('phone');
|
||||
$location->fax = request('fax');
|
||||
|
||||
$location = $request->handleImages($location);
|
||||
|
||||
@@ -141,8 +139,6 @@ class LocationsController extends Controller
|
||||
$location->state = $request->input('state');
|
||||
$location->country = $request->input('country');
|
||||
$location->zip = $request->input('zip');
|
||||
$location->phone = request('phone');
|
||||
$location->fax = request('fax');
|
||||
$location->ldap_ou = $request->input('ldap_ou');
|
||||
$location->manager_id = $request->input('manager_id');
|
||||
|
||||
@@ -231,36 +227,6 @@ class LocationsController extends Controller
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view that presents a form to clone a location.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $locationId
|
||||
* @since [v6.0.14]
|
||||
* @return View
|
||||
*/
|
||||
public function getClone($locationId = null)
|
||||
{
|
||||
$this->authorize('create', Location::class);
|
||||
|
||||
// Check if the asset exists
|
||||
if (is_null($location_to_clone = Location::find($locationId))) {
|
||||
// Redirect to the asset management page
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/locations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$location = clone $location_to_clone;
|
||||
|
||||
// unset these values
|
||||
$location->id = null;
|
||||
$location->image = null;
|
||||
|
||||
return view('locations/edit')
|
||||
->with('item', $location);
|
||||
}
|
||||
|
||||
|
||||
public function print_all_assigned($id)
|
||||
{
|
||||
if ($location = Location::where('id', $id)->first()) {
|
||||
|
||||
@@ -68,7 +68,6 @@ class ManufacturersController extends Controller
|
||||
$manufacturer->user_id = Auth::id();
|
||||
$manufacturer->url = $request->input('url');
|
||||
$manufacturer->support_url = $request->input('support_url');
|
||||
$manufacturer->warranty_lookup_url = $request->input('warranty_lookup_url');
|
||||
$manufacturer->support_phone = $request->input('support_phone');
|
||||
$manufacturer->support_email = $request->input('support_email');
|
||||
$manufacturer = $request->handleImages($manufacturer);
|
||||
@@ -124,11 +123,10 @@ class ManufacturersController extends Controller
|
||||
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.does_not_exist'));
|
||||
}
|
||||
|
||||
// Save the data
|
||||
// Save the data
|
||||
$manufacturer->name = $request->input('name');
|
||||
$manufacturer->url = $request->input('url');
|
||||
$manufacturer->support_url = $request->input('support_url');
|
||||
$manufacturer->warranty_lookup_url = $request->input('warranty_lookup_url');
|
||||
$manufacturer->support_phone = $request->input('support_phone');
|
||||
$manufacturer->support_email = $request->input('support_email');
|
||||
|
||||
|
||||
@@ -17,7 +17,7 @@ class ModalController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net]
|
||||
* @return View
|
||||
*/
|
||||
public function show ($type, $itemId = null) {
|
||||
function show ($type, $itemId = null) {
|
||||
|
||||
// These values should correspond to a file in resources/views/modals/
|
||||
$allowed_types = [
|
||||
|
||||
@@ -8,7 +8,7 @@ use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CurrentInventory;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Gate;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
@@ -51,8 +51,9 @@ class ReportsController extends Controller
|
||||
public function getAccessoryReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
$accessories = Accessory::orderBy('created_at', 'DESC')->with('company')->get();
|
||||
|
||||
return view('reports/accessories');
|
||||
return view('reports/accessories', compact('accessories'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -284,7 +285,7 @@ class ReportsController extends Controller
|
||||
|
||||
$row = [
|
||||
$actionlog->created_at,
|
||||
($actionlog->admin) ? e($actionlog->admin->getFullNameAttribute()) : '',
|
||||
($actionlog->user) ? e($actionlog->user->getFullNameAttribute()) : '',
|
||||
$actionlog->present()->actionType(),
|
||||
e($actionlog->itemType()),
|
||||
($actionlog->itemType() == 'user') ? $actionlog->filename : $item_name,
|
||||
@@ -501,6 +502,7 @@ class ReportsController extends Controller
|
||||
$header[] = trans('general.zip');
|
||||
}
|
||||
|
||||
|
||||
if ($request->filled('assigned_to')) {
|
||||
$header[] = trans('admin/hardware/table.checkoutto');
|
||||
$header[] = trans('general.type');
|
||||
@@ -531,24 +533,19 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('warranty')) {
|
||||
$header[] = trans('admin/hardware/form.warranty');
|
||||
$header[] = trans('admin/hardware/form.warranty_expires');
|
||||
$header[] = 'Warranty';
|
||||
$header[] = 'Warranty Expires';
|
||||
}
|
||||
|
||||
if ($request->filled('depreciation')) {
|
||||
$header[] = trans('admin/hardware/table.book_value');
|
||||
$header[] = trans('admin/hardware/table.diff');
|
||||
$header[] = trans('admin/hardware/form.fully_depreciated');
|
||||
$header[] = 'Value';
|
||||
$header[] = 'Diff';
|
||||
$header[] = 'Fully Depreciated';
|
||||
}
|
||||
|
||||
if ($request->filled('checkout_date')) {
|
||||
$header[] = trans('admin/hardware/table.checkout_date');
|
||||
}
|
||||
|
||||
if ($request->filled('checkin_date')) {
|
||||
$header[] = trans('admin/hardware/table.last_checkin_date');
|
||||
}
|
||||
|
||||
if ($request->filled('expected_checkin')) {
|
||||
$header[] = trans('admin/hardware/form.expected_checkin');
|
||||
}
|
||||
@@ -594,28 +591,28 @@ class ReportsController extends Controller
|
||||
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
|
||||
\Log::debug('Added headers: '.$executionTime);
|
||||
|
||||
$assets = Asset::select('assets.*')->with(
|
||||
$assets = \App\Models\Company::scopeCompanyables(Asset::select('assets.*'))->with(
|
||||
'location', 'assetstatus', 'company', 'defaultLoc', 'assignedTo',
|
||||
'model.category', 'model.manufacturer', 'supplier');
|
||||
|
||||
if ($request->filled('by_location_id')) {
|
||||
$assets->whereIn('assets.location_id', $request->input('by_location_id'));
|
||||
$assets->where('assets.location_id', $request->input('by_location_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('by_rtd_location_id')) {
|
||||
$assets->whereIn('assets.rtd_location_id', $request->input('by_rtd_location_id'));
|
||||
$assets->where('assets.rtd_location_id', $request->input('by_rtd_location_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('by_supplier_id')) {
|
||||
$assets->whereIn('assets.supplier_id', $request->input('by_supplier_id'));
|
||||
$assets->where('assets.supplier_id', $request->input('by_supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('by_company_id')) {
|
||||
$assets->whereIn('assets.company_id', $request->input('by_company_id'));
|
||||
$assets->where('assets.company_id', $request->input('by_company_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('by_model_id')) {
|
||||
$assets->whereIn('assets.model_id', $request->input('by_model_id'));
|
||||
$assets->where('assets.model_id', $request->input('by_model_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('by_category_id')) {
|
||||
@@ -635,7 +632,7 @@ class ReportsController extends Controller
|
||||
}
|
||||
|
||||
if ($request->filled('by_status_id')) {
|
||||
$assets->whereIn('assets.status_id', $request->input('by_status_id'));
|
||||
$assets->where('assets.status_id', $request->input('by_status_id'));
|
||||
}
|
||||
|
||||
if (($request->filled('purchase_start')) && ($request->filled('purchase_end'))) {
|
||||
@@ -643,24 +640,7 @@ 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();
|
||||
|
||||
$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'))->endOfDay();
|
||||
|
||||
$assets->whereBetween('assets.last_checkout', [$checkout_start, $checkout_end]);
|
||||
}
|
||||
|
||||
if (($request->filled('checkin_date_start'))) {
|
||||
$assets->whereBetween('last_checkin', [
|
||||
Carbon::parse($request->input('checkin_date_start'))->startOfDay(),
|
||||
// use today's date is `checkin_date_end` is not provided
|
||||
Carbon::parse($request->input('checkin_date_end', now()))->endOfDay(),
|
||||
]);
|
||||
$assets->whereBetween('assets.created_at', [$request->input('created_start'), $request->input('created_end')]);
|
||||
}
|
||||
|
||||
if (($request->filled('expected_checkin_start')) && ($request->filled('expected_checkin_end'))) {
|
||||
@@ -668,10 +648,7 @@ 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();
|
||||
|
||||
$assets->whereBetween('assets.last_audit_date', [$last_audit_start, $last_audit_end]);
|
||||
$assets->whereBetween('assets.last_audit_date', [$request->input('last_audit_start'), $request->input('last_audit_end')]);
|
||||
}
|
||||
|
||||
if (($request->filled('next_audit_start')) && ($request->filled('next_audit_end'))) {
|
||||
@@ -687,7 +664,6 @@ class ReportsController extends Controller
|
||||
$assets->onlyTrashed();
|
||||
}
|
||||
|
||||
\Log::debug($assets->toSql());
|
||||
$assets->orderBy('assets.id', 'ASC')->chunk(20, function ($assets) use ($handle, $customfields, $request) {
|
||||
|
||||
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
|
||||
@@ -847,12 +823,6 @@ class ReportsController extends Controller
|
||||
$row[] = ($asset->last_checkout) ? $asset->last_checkout : '';
|
||||
}
|
||||
|
||||
if ($request->filled('checkin_date')) {
|
||||
$row[] = ($asset->last_checkin)
|
||||
? Carbon::parse($asset->last_checkin)->format('Y-m-d')
|
||||
: '';
|
||||
}
|
||||
|
||||
if ($request->filled('expected_checkin')) {
|
||||
$row[] = ($asset->expected_checkin) ? $asset->expected_checkin : '';
|
||||
}
|
||||
@@ -929,8 +899,12 @@ class ReportsController extends Controller
|
||||
public function getAssetMaintenancesReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
// Grab all the improvements
|
||||
$assetMaintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company')
|
||||
->orderBy('created_at', 'DESC')
|
||||
->get();
|
||||
|
||||
return view('reports.asset_maintenances');
|
||||
return view('reports/asset_maintenances', compact('assetMaintenances'));
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -1021,12 +995,7 @@ class ReportsController extends Controller
|
||||
|
||||
$assetsForReport = $acceptances
|
||||
->filter(function ($acceptance) {
|
||||
$acceptance_checkoutable_flag = false;
|
||||
if ($acceptance->checkoutable){
|
||||
$acceptance_checkoutable_flag = $acceptance->checkoutable->checkedOutToUser();
|
||||
}
|
||||
|
||||
return $acceptance->checkoutable_type == 'App\Models\Asset' && $acceptance_checkoutable_flag;
|
||||
return $acceptance->checkoutable_type == 'App\Models\Asset';
|
||||
})
|
||||
->map(function($acceptance) {
|
||||
return ['assetItem' => $acceptance->checkoutable, 'acceptance' => $acceptance];
|
||||
@@ -1056,11 +1025,7 @@ class ReportsController extends Controller
|
||||
if (is_null($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()){
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||
}
|
||||
$logItem = $logItem_res[0];
|
||||
$logItem = $assetItem->checkouts()->where('created_at', '=', $acceptance->created_at)->get()[0];
|
||||
}
|
||||
|
||||
if(!$assetItem->assignedTo->locale){
|
||||
@@ -1155,6 +1120,8 @@ class ReportsController extends Controller
|
||||
$row[] = str_replace(',', '', e($item['assetItem']->asset_tag));
|
||||
$row[] = str_replace(',', '', e(($item['acceptance']->assignedTo) ? $item['acceptance']->assignedTo->present()->name() : trans('admin/reports/general.deleted_user')));
|
||||
$rows[] = implode(',', $row);
|
||||
} else {
|
||||
// Log the error maybe?
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -65,27 +65,18 @@ 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://";
|
||||
}
|
||||
$protocol = array_key_exists('HTTPS', $_SERVER) && ('on' == $_SERVER['HTTPS']) ? 'https://' : '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;
|
||||
}
|
||||
$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['url_valid'] = (url('/').'/setup' === $pageURL);
|
||||
|
||||
$start_settings['url_config'] = url('/');
|
||||
$start_settings['real_url'] = $pageURL;
|
||||
$start_settings['php_version_min'] = true;
|
||||
|
||||
@@ -120,17 +111,17 @@ class SettingsController extends Controller
|
||||
$start_settings['prod'] = true;
|
||||
}
|
||||
|
||||
$start_settings['owner'] = '';
|
||||
|
||||
if (function_exists('posix_getpwuid')) { // Probably Linux
|
||||
$owner = posix_getpwuid(fileowner($_SERVER['SCRIPT_FILENAME']));
|
||||
// This *should* be an array, but we've seen this return a bool in some chrooted environments
|
||||
if (is_array($owner)) {
|
||||
$start_settings['owner'] = $owner['name'];
|
||||
}
|
||||
$start_settings['owner'] = $owner['name'];
|
||||
} else { // Windows
|
||||
// TODO: Is there a way of knowing if a windows user has elevated permissions
|
||||
// This just gets the user name, which likely isn't 'root'
|
||||
// $start_settings['owner'] = getenv('USERNAME');
|
||||
$start_settings['owner'] = '';
|
||||
}
|
||||
|
||||
if (($start_settings['owner'] === 'root') || ($start_settings['owner'] === '0')) {
|
||||
if (('root' === $start_settings['owner']) || ('0' === $start_settings['owner'])) {
|
||||
$start_settings['owner_is_admin'] = true;
|
||||
} else {
|
||||
$start_settings['owner_is_admin'] = false;
|
||||
@@ -349,6 +340,7 @@ class SettingsController extends Controller
|
||||
$setting->email_format = $request->input('email_format');
|
||||
$setting->username_format = $request->input('username_format');
|
||||
$setting->require_accept_signature = $request->input('require_accept_signature');
|
||||
$setting->display_username = $request->input('display_username', 0);
|
||||
$setting->show_assigned_assets = $request->input('show_assigned_assets', '0');
|
||||
if (! config('app.lock_passwords')) {
|
||||
$setting->login_note = $request->input('login_note');
|
||||
@@ -590,7 +582,6 @@ class SettingsController extends Controller
|
||||
$setting->date_display_format = $request->input('date_display_format');
|
||||
$setting->time_display_format = $request->input('time_display_format');
|
||||
$setting->digit_separator = $request->input('digit_separator');
|
||||
$setting->name_display_format = $request->input('name_display_format');
|
||||
|
||||
if ($setting->save()) {
|
||||
return redirect()->route('settings.index')
|
||||
@@ -689,6 +680,33 @@ class SettingsController extends Controller
|
||||
return view('settings.slack', compact('setting'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a form to allow a super admin to update settings.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*
|
||||
* @since [v1.0]
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function postSlack(SlackSettingsRequest $request)
|
||||
{
|
||||
if (is_null($setting = Setting::getSettings())) {
|
||||
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
|
||||
}
|
||||
|
||||
$setting->slack_endpoint = $request->input('slack_endpoint');
|
||||
$setting->slack_channel = $request->input('slack_channel');
|
||||
$setting->slack_botname = $request->input('slack_botname');
|
||||
|
||||
if ($setting->save()) {
|
||||
return redirect()->route('settings.index')
|
||||
->with('success', trans('admin/settings/message.update.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($setting->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a form to allow a super admin to update settings.
|
||||
*
|
||||
@@ -790,7 +808,7 @@ class SettingsController extends Controller
|
||||
*/
|
||||
public function getPhpInfo()
|
||||
{
|
||||
if (config('app.debug') === true) {
|
||||
if (true === config('app.debug')) {
|
||||
return view('settings.phpinfo');
|
||||
}
|
||||
|
||||
@@ -828,14 +846,6 @@ class SettingsController extends Controller
|
||||
if (is_null($setting = Setting::getSettings())) {
|
||||
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
|
||||
}
|
||||
$setting->label2_enable = $request->input('label2_enable');
|
||||
$setting->label2_template = $request->input('label2_template');
|
||||
$setting->label2_title = $request->input('label2_title');
|
||||
$setting->label2_asset_logo = $request->input('label2_asset_logo');
|
||||
$setting->label2_1d_type = $request->input('label2_1d_type');
|
||||
$setting->label2_2d_type = $request->input('label2_2d_type');
|
||||
$setting->label2_2d_target = $request->input('label2_2d_target');
|
||||
$setting->label2_fields = $request->input('label2_fields');
|
||||
$setting->labels_per_page = $request->input('labels_per_page');
|
||||
$setting->labels_width = $request->input('labels_width');
|
||||
$setting->labels_height = $request->input('labels_height');
|
||||
@@ -884,7 +894,7 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
if ($setting->save()) {
|
||||
return redirect()->route('settings.labels.index')
|
||||
return redirect()->route('settings.index')
|
||||
->with('success', trans('admin/settings/message.update.success'));
|
||||
}
|
||||
|
||||
@@ -970,7 +980,6 @@ class SettingsController extends Controller
|
||||
$setting->ldap_phone_field = $request->input('ldap_phone');
|
||||
$setting->ldap_jobtitle = $request->input('ldap_jobtitle');
|
||||
$setting->ldap_country = $request->input('ldap_country');
|
||||
$setting->ldap_location = $request->input('ldap_location');
|
||||
$setting->ldap_dept = $request->input('ldap_dept');
|
||||
$setting->ldap_client_tls_cert = $request->input('ldap_client_tls_cert');
|
||||
$setting->ldap_client_tls_key = $request->input('ldap_client_tls_key');
|
||||
@@ -1048,48 +1057,6 @@ class SettingsController extends Controller
|
||||
return $pdf_branding;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show Google login settings form
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v6.1.1]
|
||||
* @return View
|
||||
*/
|
||||
public function getGoogleLoginSettings()
|
||||
{
|
||||
$setting = Setting::getSettings();
|
||||
return view('settings.google', compact('setting'));
|
||||
}
|
||||
|
||||
/**
|
||||
* ShSaveow Google login settings form
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v6.1.1]
|
||||
* @return View
|
||||
*/
|
||||
public function postGoogleLoginSettings(Request $request)
|
||||
{
|
||||
if (!config('app.lock_passwords')) {
|
||||
$setting = Setting::getSettings();
|
||||
|
||||
$setting->google_login = $request->input('google_login', 0);
|
||||
$setting->google_client_id = $request->input('google_client_id');
|
||||
$setting->google_client_secret = $request->input('google_client_secret');
|
||||
|
||||
if ($setting->save()) {
|
||||
return redirect()->route('settings.index')
|
||||
->with('success', trans('admin/settings/message.update.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($setting->getErrors());
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Show the listing of backups.
|
||||
*
|
||||
@@ -1145,7 +1112,7 @@ class SettingsController extends Controller
|
||||
public function postBackups()
|
||||
{
|
||||
if (! config('app.lock_passwords')) {
|
||||
Artisan::call('snipeit:backup', ['--filename' => 'manual-backup-'.date('Y-m-d-H-i-s')]);
|
||||
Artisan::call('backup:run');
|
||||
$output = Artisan::output();
|
||||
|
||||
// Backup completed
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Events\UserMerged;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Accessory;
|
||||
@@ -14,7 +13,6 @@ use App\Models\LicenseSeat;
|
||||
use App\Models\ConsumableAssignment;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -23,7 +21,7 @@ use Illuminate\Support\Facades\Password;
|
||||
class BulkUsersController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns a view that confirms the user's a bulk action will be applied to.
|
||||
* Returns a view that confirms the user's a bulk delete will be applied to.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.7]
|
||||
@@ -37,32 +35,16 @@ class BulkUsersController extends Controller
|
||||
|
||||
// Make sure there were users selected
|
||||
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
|
||||
|
||||
// Get the list of affected users
|
||||
$user_raw_array = request('ids');
|
||||
$users = User::whereIn('id', $user_raw_array)
|
||||
->with('groups', 'assets', 'licenses', 'accessories')->get();
|
||||
|
||||
// bulk edit, display the bulk edit form
|
||||
if ($request->input('bulk_actions') == 'edit') {
|
||||
return view('users/bulk-edit', compact('users'))
|
||||
->with('groups', Group::pluck('name', 'id'));
|
||||
|
||||
// bulk delete, display the bulk delete confirmation form
|
||||
} elseif ($request->input('bulk_actions') == 'delete') {
|
||||
return view('users/confirm-bulk-delete')->with('users', $users)->with('statuslabel_list', Helper::statusLabelList());
|
||||
|
||||
// merge, confirm they have at least 2 users selected and display the merge screen
|
||||
} elseif ($request->input('bulk_actions') == 'merge') {
|
||||
|
||||
if (($request->filled('ids')) && (count($request->input('ids')) > 1)) {
|
||||
return view('users/confirm-merge')->with('users', $users);
|
||||
// Not enough users selected, send them back
|
||||
} else {
|
||||
return redirect()->back()->with('error', trans('general.not_enough_users_selected', ['count' => 2]));
|
||||
}
|
||||
|
||||
// bulk password reset, just do the thing
|
||||
} elseif ($request->input('bulk_actions') == 'bulkpasswordreset') {
|
||||
foreach ($users as $user) {
|
||||
if (($user->activated == '1') && ($user->email != '')) {
|
||||
@@ -77,7 +59,7 @@ class BulkUsersController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', trans('general.no_users_selected'));
|
||||
return redirect()->back()->with('error', 'No users selected');
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -94,7 +76,7 @@ class BulkUsersController extends Controller
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
if ((! $request->filled('ids')) || $request->input('ids') <= 0) {
|
||||
return redirect()->back()->with('error', trans('general.no_users_selected'));
|
||||
return redirect()->back()->with('error', 'No users selected');
|
||||
}
|
||||
$user_raw_array = $request->input('ids');
|
||||
|
||||
@@ -113,8 +95,7 @@ class BulkUsersController extends Controller
|
||||
->conditionallyAddItem('locale')
|
||||
->conditionallyAddItem('remote')
|
||||
->conditionallyAddItem('ldap_import')
|
||||
->conditionallyAddItem('activated')
|
||||
->conditionallyAddItem('autoassign_licenses');
|
||||
->conditionallyAddItem('activated');
|
||||
|
||||
|
||||
// If the manager_id is one of the users being updated, generate a warning.
|
||||
@@ -124,11 +105,6 @@ class BulkUsersController extends Controller
|
||||
'warning' => trans('admin/users/message.bulk_manager_warn'),
|
||||
];
|
||||
}
|
||||
|
||||
if ($request->input('null_location_id')=='1') {
|
||||
$this->update_array['location_id'] = null;
|
||||
}
|
||||
|
||||
if (! $manager_conflict) {
|
||||
$this->conditionallyAddItem('manager_id');
|
||||
}
|
||||
@@ -187,11 +163,11 @@ class BulkUsersController extends Controller
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
if ((! $request->filled('ids')) || (count($request->input('ids')) == 0)) {
|
||||
return redirect()->back()->with('error', trans('general.no_users_selected'));
|
||||
return redirect()->back()->with('error', 'No users selected');
|
||||
}
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('users.index')->with('error', trans('general.feature_disabled'));
|
||||
return redirect()->route('users.index')->with('error', 'Bulk delete is not enabled in this installation');
|
||||
}
|
||||
|
||||
$user_raw_array = request('ids');
|
||||
@@ -273,80 +249,4 @@ class BulkUsersController extends Controller
|
||||
$logAction->logaction('checkin from');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Save bulk-edited users
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function merge(Request $request)
|
||||
{
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('users.index')->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
$user_ids_to_merge = $request->input('ids_to_merge');
|
||||
$user_ids_to_merge = array_diff($user_ids_to_merge, array($request->input('merge_into_id')));
|
||||
|
||||
if ((!$request->filled('merge_into_id')) || (count($user_ids_to_merge) < 1)) {
|
||||
return redirect()->back()->with('error', trans('general.no_users_selected'));
|
||||
}
|
||||
|
||||
// Get the users
|
||||
$merge_into_user = User::find($request->input('merge_into_id'));
|
||||
$users_to_merge = User::whereIn('id', $user_ids_to_merge)->with('assets', 'licenses', 'consumables','accessories')->get();
|
||||
$admin = User::find(Auth::user()->id);
|
||||
|
||||
// Walk users
|
||||
foreach ($users_to_merge as $user_to_merge) {
|
||||
|
||||
foreach ($user_to_merge->assets as $asset) {
|
||||
\Log::debug('Updating asset: '.$asset->asset_tag . ' to '.$merge_into_user->id);
|
||||
$asset->assigned_to = $request->input('merge_into_id');
|
||||
$asset->save();
|
||||
}
|
||||
|
||||
foreach ($user_to_merge->licenses as $license) {
|
||||
\Log::debug('Updating license pivot: '.$license->id . ' to '.$merge_into_user->id);
|
||||
$user_to_merge->licenses()->updateExistingPivot($license->id, ['assigned_to' => $merge_into_user->id]);
|
||||
}
|
||||
|
||||
foreach ($user_to_merge->consumables as $consumable) {
|
||||
\Log::debug('Updating consumable pivot: '.$consumable->id . ' to '.$merge_into_user->id);
|
||||
$user_to_merge->consumables()->updateExistingPivot($consumable->id, ['assigned_to' => $merge_into_user->id]);
|
||||
}
|
||||
|
||||
foreach ($user_to_merge->accessories as $accessory) {
|
||||
$user_to_merge->accessories()->updateExistingPivot($accessory->id, ['assigned_to' => $merge_into_user->id]);
|
||||
}
|
||||
|
||||
foreach ($user_to_merge->userlog as $log) {
|
||||
$log->target_id = $user_to_merge->id;
|
||||
$log->save();
|
||||
}
|
||||
|
||||
User::where('manager_id', '=', $user_to_merge->id)->update(['manager_id' => $merge_into_user->id]);
|
||||
|
||||
foreach ($user_to_merge->managedLocations as $managedLocation) {
|
||||
$managedLocation->manager_id = $merge_into_user->id;
|
||||
$managedLocation->save();
|
||||
}
|
||||
|
||||
$user_to_merge->delete();
|
||||
//$user_to_merge->save();
|
||||
|
||||
event(new UserMerged($user_to_merge, $merge_into_user, $admin));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('success', trans('general.merge_success', ['count' => $users_to_merge->count(), 'into_username' => $merge_into_user->username]));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,7 +2,6 @@
|
||||
|
||||
namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
@@ -140,25 +139,18 @@ class UserFilesController extends Controller
|
||||
|
||||
// the license is valid
|
||||
if (isset($user->id)) {
|
||||
|
||||
$this->authorize('view', $user);
|
||||
|
||||
$log = Actionlog::find($fileId);
|
||||
$file = $log->get_src('users');
|
||||
|
||||
// Display the file inline
|
||||
if (request('inline') == 'true') {
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
return Storage::download('private_uploads/users/'.$log->filename, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return Storage::download('private_uploads/users/'.$log->filename);
|
||||
|
||||
return Response::download($file); //FIXME this doesn't use the new StorageHelper yet, but it's complicated...
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/users/message.user_not_found', ['id' => $userId]);
|
||||
|
||||
// Redirect to the user management page if the user doesn't exist
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', ['id' => $userId]));
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('users.index')->with('error', $error);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -74,6 +74,7 @@ class UsersController extends Controller
|
||||
$permissions = $this->filterDisplayable($permissions);
|
||||
|
||||
$user = new User;
|
||||
$user->activated = 1;
|
||||
|
||||
return view('users/edit', compact('groups', 'userGroups', 'permissions', 'userPermissions'))
|
||||
->with('user', $user);
|
||||
@@ -120,7 +121,6 @@ class UsersController extends Controller
|
||||
$user->created_by = Auth::user()->id;
|
||||
$user->start_date = $request->input('start_date', null);
|
||||
$user->end_date = $request->input('end_date', null);
|
||||
$user->autoassign_licenses = $request->input('autoassign_licenses', 0);
|
||||
|
||||
// Strip out the superuser permission if the user isn't a superadmin
|
||||
$permissions_array = $request->input('permission');
|
||||
@@ -133,9 +133,6 @@ class UsersController extends Controller
|
||||
// we have to invoke the
|
||||
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
|
||||
\Log::info("About to call customFill, in the 'store' controller!!!");
|
||||
$user->customFill($request, Auth::user());
|
||||
|
||||
if ($user->save()) {
|
||||
if ($request->filled('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
@@ -213,6 +210,7 @@ class UsersController extends Controller
|
||||
*/
|
||||
public function update(SaveUserRequest $request, $id = null)
|
||||
{
|
||||
|
||||
// We need to reverse the UI specific logic for our
|
||||
// permissions here before we update the user.
|
||||
$permissions = $request->input('permissions', []);
|
||||
@@ -270,15 +268,12 @@ class UsersController extends Controller
|
||||
$user->city = $request->input('city', null);
|
||||
$user->state = $request->input('state', null);
|
||||
$user->country = $request->input('country', null);
|
||||
// if a user is editing themselves we should always keep activated true
|
||||
$user->activated = $request->input('activated', $request->user()->is($user) ? 1 : 0);
|
||||
$user->activated = $request->input('activated', 0);
|
||||
$user->zip = $request->input('zip', null);
|
||||
$user->remote = $request->input('remote', 0);
|
||||
$user->vip = $request->input('vip', 0);
|
||||
$user->website = $request->input('website', null);
|
||||
$user->start_date = $request->input('start_date', null);
|
||||
$user->end_date = $request->input('end_date', null);
|
||||
$user->autoassign_licenses = $request->input('autoassign_licenses', 0);
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
@@ -303,8 +298,6 @@ class UsersController extends Controller
|
||||
// Handle uploaded avatar
|
||||
app(ImageUploadRequest::class)->handleImages($user, 600, 'avatar', 'avatars', 'avatar');
|
||||
|
||||
\Log::debug("calling custom fill from the UPDATE method!");
|
||||
$user->customFill($request, Auth::user());
|
||||
//\Log::debug(print_r($user, true));
|
||||
|
||||
// Was the user updated?
|
||||
@@ -675,4 +668,4 @@ class UsersController extends Controller
|
||||
|
||||
return redirect()->back()->with('error', 'User is not activated, is LDAP synced, or does not have an email address ');
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,7 +82,7 @@ class ViewAssetsController extends Controller
|
||||
return view('account/requestable-assets', compact('assets', 'models'));
|
||||
}
|
||||
|
||||
public function getRequestItem(Request $request, $itemType, $itemId = null, $cancel_by_admin = false, $requestingUser = null)
|
||||
public function getRequestItem(Request $request, $itemType, $itemId = null)
|
||||
{
|
||||
$item = null;
|
||||
$fullItemType = 'App\\Models\\'.studly_case($itemType);
|
||||
@@ -119,16 +119,16 @@ class ViewAssetsController extends Controller
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
if (($item_request = $item->isRequestedBy($user)) || $cancel_by_admin) {
|
||||
$item->cancelRequest($requestingUser);
|
||||
$data['item_quantity'] = ($item_request) ? $item_request->qty : 1;
|
||||
if ($item_request = $item->isRequestedBy($user)) {
|
||||
$item->cancelRequest();
|
||||
$data['item_quantity'] = $item_request->qty;
|
||||
$logaction->logaction('request_canceled');
|
||||
|
||||
if (($settings->alert_email != '') && ($settings->alerts_enabled == '1') && (! config('app.lock_passwords'))) {
|
||||
$settings->notify(new RequestAssetCancelation($data));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success')->with('success', trans('admin/hardware/message.requests.canceled'));
|
||||
return redirect()->route('requestable-assets')->with('success')->with('success', trans('admin/hardware/message.requests.canceled'));
|
||||
} else {
|
||||
$item->request();
|
||||
if (($settings->alert_email != '') && ($settings->alerts_enabled == '1') && (! config('app.lock_passwords'))) {
|
||||
|
||||
@@ -18,12 +18,13 @@ class Kernel extends HttpKernel
|
||||
\Illuminate\Foundation\Http\Middleware\PreventRequestsDuringMaintenance::class,
|
||||
\Illuminate\Session\Middleware\StartSession::class,
|
||||
\Illuminate\View\Middleware\ShareErrorsFromSession::class,
|
||||
\Fideloper\Proxy\TrustProxies::class,
|
||||
\App\Http\Middleware\CheckForSetup::class,
|
||||
\App\Http\Middleware\CheckForDebug::class,
|
||||
\Illuminate\Foundation\Http\Middleware\ConvertEmptyStringsToNull::class,
|
||||
\App\Http\Middleware\SecurityHeaders::class,
|
||||
\App\Http\Middleware\PreventBackHistory::class,
|
||||
\Illuminate\Http\Middleware\HandleCors::class,
|
||||
\Fruitcake\Cors\HandleCors::class,
|
||||
|
||||
];
|
||||
|
||||
|
||||
@@ -1,67 +0,0 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
class CategoryEditForm extends Component
|
||||
{
|
||||
public $defaultEulaText;
|
||||
|
||||
public $eulaText;
|
||||
|
||||
public $originalSendCheckInEmailValue;
|
||||
|
||||
public $requireAcceptance;
|
||||
|
||||
public $sendCheckInEmail;
|
||||
|
||||
public $useDefaultEula;
|
||||
|
||||
public function mount()
|
||||
{
|
||||
$this->originalSendCheckInEmailValue = $this->sendCheckInEmail;
|
||||
|
||||
if ($this->eulaText || $this->useDefaultEula) {
|
||||
$this->sendCheckInEmail = 1;
|
||||
}
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.category-edit-form');
|
||||
}
|
||||
|
||||
public function updated($property, $value)
|
||||
{
|
||||
if (! in_array($property, ['eulaText', 'useDefaultEula'])) {
|
||||
return;
|
||||
}
|
||||
|
||||
$this->sendCheckInEmail = $this->eulaText || $this->useDefaultEula ? 1 : $this->originalSendCheckInEmailValue;
|
||||
}
|
||||
|
||||
public function getShouldDisplayEmailMessageProperty(): bool
|
||||
{
|
||||
return $this->eulaText || $this->useDefaultEula;
|
||||
}
|
||||
|
||||
public function getEmailMessageProperty(): string
|
||||
{
|
||||
if ($this->useDefaultEula) {
|
||||
return trans('admin/categories/general.email_will_be_sent_due_to_global_eula');
|
||||
}
|
||||
|
||||
return trans('admin/categories/general.email_will_be_sent_due_to_category_eula');
|
||||
}
|
||||
|
||||
public function getEulaTextDisabledProperty()
|
||||
{
|
||||
return (bool)$this->useDefaultEula;
|
||||
}
|
||||
|
||||
public function getSendCheckInEmailDisabledProperty()
|
||||
{
|
||||
return $this->eulaText || $this->useDefaultEula;
|
||||
}
|
||||
}
|
||||
@@ -2,8 +2,6 @@
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\DefaultValuesForCustomFields;
|
||||
use Livewire\Component;
|
||||
|
||||
use App\Models\CustomFieldset;
|
||||
@@ -32,7 +30,7 @@ class CustomFieldSetDefaultValuesForModel extends Component
|
||||
$this->fields = CustomFieldset::find($this->fieldset_id)->fields;
|
||||
}
|
||||
|
||||
$this->add_default_values = (DefaultValuesForCustomFields::forPivot($this->model, Asset::class)->count() > 0);
|
||||
$this->add_default_values = ($this->model->defaultValues->count() > 0);
|
||||
}
|
||||
|
||||
public function updatedFieldsetId()
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user