mirror of
https://github.com/snipe/snipe-it.git
synced 2025-03-05 12:40:39 -08:00
Merge branch 'develop' into dev-master-integration
# Conflicts: # .gitignore # .travis.yml # app/Console/Commands/LdapSync.php # app/Console/Commands/SendExpectedCheckinAlerts.php # app/Console/Commands/SendExpirationAlerts.php # app/Console/Commands/SendInventoryAlerts.php # app/Console/Kernel.php # app/Http/Controllers/Api/AssetsController.php # app/Http/Controllers/Api/ManufacturersController.php # app/Http/Controllers/Api/StatuslabelsController.php # app/Http/Controllers/Api/UsersController.php # app/Http/Controllers/AssetMaintenancesController.php # app/Http/Controllers/Assets/AssetsController.php # app/Http/Controllers/Auth/ForgotPasswordController.php # app/Http/Controllers/Auth/LoginController.php # app/Http/Controllers/Auth/ResetPasswordController.php # app/Http/Controllers/ReportsController.php # app/Http/Controllers/SettingsController.php # app/Http/Controllers/UsersController.php # app/Http/Transformers/AssetMaintenancesTransformer.php # app/Importer/Importer.php # app/Importer/ItemImporter.php # app/Importer/UserImporter.php # app/Importer/import_mappings.md # app/Models/Ldap.php # app/Models/License.php # app/Models/Location.php # app/Models/Recipients/AlertRecipient.php # app/Models/User.php # app/Providers/AppServiceProvider.php # composer.json # composer.lock # config/trustedproxy.php # config/version.php # public/js/build/all.js # public/js/build/vue.js # public/js/build/vue.js.map # public/js/dist/all.js # public/mix-manifest.json # resources/assets/js/components/importer/importer-file.vue # resources/lang/ar/admin/settings/general.php # resources/lang/bg/admin/settings/general.php # resources/lang/en-ID/admin/settings/general.php # resources/lang/en-ID/passwords.php # resources/lang/en/passwords.php # resources/lang/es-CO/passwords.php # resources/lang/es-ES/passwords.php # resources/lang/es-MX/passwords.php # resources/lang/es-VE/passwords.php # resources/lang/fi/admin/settings/general.php # resources/lang/id/admin/settings/general.php # resources/lang/id/passwords.php # resources/lang/ja/passwords.php # resources/lang/nl/passwords.php # resources/lang/pl/admin/settings/general.php # resources/lang/pl/passwords.php # resources/lang/pt-BR/admin/settings/general.php # resources/lang/pt-BR/passwords.php # resources/lang/ru/admin/settings/general.php # resources/lang/ru/admin/statuslabels/table.php # resources/lang/ru/passwords.php # resources/lang/sr-CS/general.php # resources/lang/sr-CS/mail.php # resources/lang/sv-SE/admin/settings/general.php # resources/lang/tr/admin/settings/general.php # resources/lang/tr/passwords.php # resources/lang/vi/admin/models/message.php # resources/lang/vi/admin/users/general.php # resources/lang/zh-CN/admin/settings/general.php # resources/views/importer/import.blade.php # resources/views/partials/bootstrap-table.blade.php # resources/views/partials/forms/edit/image-upload.blade.php # resources/views/users/edit.blade.php # resources/views/users/view.blade.php # tests/unit/ImporterTest.php
This commit is contained in:
commit
533649f24e
|
@ -1650,6 +1650,168 @@
|
|||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jwhulette",
|
||||
"name": "Wes Hulette",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/4930051?v=4",
|
||||
"profile": "http://macfoo.wordpress.com/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "patrict",
|
||||
"name": "patrict",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/8134591?v=4",
|
||||
"profile": "https://github.com/patrict",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "VELIKII-DIVAN",
|
||||
"name": "Dmitriy Minaev",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/2611616?v=4",
|
||||
"profile": "https://github.com/VELIKII-DIVAN",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "liquidhorse",
|
||||
"name": "liquidhorse",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/5132245?v=4",
|
||||
"profile": "https://github.com/liquidhorse",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Seldaek",
|
||||
"name": "Jordi Boggiano",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/183678?v=4",
|
||||
"profile": "https://seld.be/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "inietov",
|
||||
"name": "Ivan Nieto",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/653557?v=4",
|
||||
"profile": "https://github.com/inietov",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "benrubson",
|
||||
"name": "Ben RUBSON",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/6764151?v=4",
|
||||
"profile": "https://github.com/benrubson",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "NMathar",
|
||||
"name": "NMathar",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/8554558?v=4",
|
||||
"profile": "https://github.com/NMathar",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "smb",
|
||||
"name": "Steffen",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/139566?v=4",
|
||||
"profile": "https://github.com/smb",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Sxderp",
|
||||
"name": "Sxderp",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/6609453?v=4",
|
||||
"profile": "https://github.com/Sxderp",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "fanta8897",
|
||||
"name": "fanta8897",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/4807843?v=4",
|
||||
"profile": "https://github.com/fanta8897",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "andreybolonin",
|
||||
"name": "Andrey Bolonin",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/2576509?v=4",
|
||||
"profile": "https://andreybolonin.com/phpconsulting/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "shinayoshi",
|
||||
"name": "shinayoshi",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/2173307?v=4",
|
||||
"profile": "http://www.shinayoshi.net/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "reuser",
|
||||
"name": "Hubert",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/2130159?v=4",
|
||||
"profile": "https://github.com/reuser",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "KeenRivals",
|
||||
"name": "KeenRivals",
|
||||
"avatar_url": "https://avatars0.githubusercontent.com/u/6865789?v=4",
|
||||
"profile": "https://brashear.me",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "omyno",
|
||||
"name": "omyno",
|
||||
"avatar_url": "https://avatars3.githubusercontent.com/u/2902513?v=4",
|
||||
"profile": "https://github.com/omyno",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "jackka",
|
||||
"name": "Evgeny",
|
||||
"avatar_url": "https://avatars1.githubusercontent.com/u/6271335?v=4",
|
||||
"profile": "https://github.com/jackka",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "colin-campbell",
|
||||
"name": "Colin Campbell",
|
||||
"avatar_url": "https://avatars2.githubusercontent.com/u/1169963?v=4",
|
||||
"profile": "https://digitalist.se",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
|
|
@ -1,5 +1,13 @@
|
|||
.git
|
||||
.github
|
||||
.gitattributes
|
||||
.gitignore
|
||||
.dockerignore
|
||||
app/storage/logs/*
|
||||
app/storage/views/*
|
||||
vendor/*
|
||||
storage/framework/cache/*
|
||||
node_modules
|
||||
.vagrant
|
||||
.idea
|
||||
|
||||
|
|
13
.env.example
13
.env.example
|
@ -43,6 +43,8 @@ MAIL_FROM_ADDR=you@example.com
|
|||
MAIL_FROM_NAME='Snipe-IT'
|
||||
MAIL_REPLYTO_ADDR=you@example.com
|
||||
MAIL_REPLYTO_NAME='Snipe-IT'
|
||||
MAIL_AUTO_EMBED=true
|
||||
MAIL_AUTO_EMBED_METHOD=base64
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: IMAGE LIBRARY
|
||||
|
@ -59,6 +61,7 @@ ENCRYPT=false
|
|||
COOKIE_NAME=snipeit_session
|
||||
COOKIE_DOMAIN=null
|
||||
SECURE_COOKIES=false
|
||||
SESSION_PATH=null
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SECURITY HEADER SETTINGS
|
||||
|
@ -90,10 +93,12 @@ MEMCACHED_PORT=null
|
|||
# --------------------------------------------
|
||||
# OPTIONAL: AWS S3 SETTINGS
|
||||
# --------------------------------------------
|
||||
AWS_SECRET=null
|
||||
AWS_KEY=null
|
||||
AWS_REGION=null
|
||||
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: LOGIN THROTTLING
|
||||
|
@ -106,7 +111,7 @@ LOGIN_LOCKOUT_DURATION=60
|
|||
# --------------------------------------------
|
||||
APP_LOG=single
|
||||
APP_LOG_MAX_FILES=10
|
||||
APP_LOCKED=false
|
||||
APP_LOG_LEVEL=debug
|
||||
FILESYSTEM_DISK=local
|
||||
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
|
||||
ALLOW_IFRAMING=false
|
||||
|
|
|
@ -40,10 +40,12 @@ IMAGE_LIB=gd
|
|||
# --------------------------------------------
|
||||
# OPTIONAL: AWS S3 SETTINGS
|
||||
# --------------------------------------------
|
||||
AWS_SECRET=null
|
||||
AWS_KEY=null
|
||||
AWS_REGION=null
|
||||
AWS_SECRET_ACCESS_KEY=null
|
||||
AWS_ACCESS_KEY_ID=null
|
||||
AWS_DEFAULT_REGION=null
|
||||
AWS_BUCKET=null
|
||||
AWS_BUCKET_ROOT=null
|
||||
AWS_URL=null
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
|
|
|
@ -40,10 +40,12 @@ IMAGE_LIB=gd
|
|||
# --------------------------------------------
|
||||
# OPTIONAL: AWS S3 SETTINGS
|
||||
# --------------------------------------------
|
||||
AWS_SECRET=null
|
||||
AWS_KEY=null
|
||||
AWS_REGION=null
|
||||
AWS_SECRET_ACCESS_KEY=null
|
||||
AWS_ACCESS_KEY_ID=null
|
||||
AWS_DEFAULT_REGION=null
|
||||
AWS_BUCKET=null
|
||||
AWS_BUCKET_ROOT=null
|
||||
AWS_URL=null
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
|
|
33
.github/config.yml
vendored
Normal file
33
.github/config.yml
vendored
Normal file
|
@ -0,0 +1,33 @@
|
|||
# Configuration for new-issue-welcome - https://github.com/behaviorbot/new-issue-welcome
|
||||
|
||||
# Comment to be posted to on first time issues
|
||||
newIssueWelcomeComment: |
|
||||
👋 Thanks for opening your first issue here! If you're reporting a 🐞 bug, please make sure you include steps to reproduce it. We get a lot of issues on this repo, so please be patient and we will get back to you as soon as we can.
|
||||
|
||||
# Configuration for new-pr-welcome - https://github.com/behaviorbot/new-pr-welcome
|
||||
|
||||
# Comment to be posted to on PRs from first time contributors in your repository
|
||||
newPRWelcomeComment: |
|
||||
💖 Thanks for this pull request! 💖
|
||||
|
||||
We use [semantic commit messages](https://snipe-it.readme.io/docs/contributing-overview#section-pull-request-guidelines) to streamline the release process and easily generate changelogs between versions. Before your pull request can be merged, you should **update your pull request title** to start with a semantic prefix if it doesn't have one already.
|
||||
|
||||
Examples of commit messages with semantic prefixes:
|
||||
|
||||
- `Fixed #<issue number>: don't overwrite prevent_default if default wasn't prevented`
|
||||
- `Added #<issue number>: add checkout functionality to assets`
|
||||
- `Improved Asset Checkout: use new notification method for checkout`
|
||||
|
||||
Things that will help get your PR across the finish line:
|
||||
|
||||
- Document any user-facing changes you've made.
|
||||
- Include tests when adding/changing behavior.
|
||||
- Include screenshots and animated GIFs whenever possible.
|
||||
|
||||
We get a lot of pull requests on this repo, so please be patient and we will get back to you as soon as we can.
|
||||
|
||||
# Configuration for first-pr-merge - https://github.com/behaviorbot/first-pr-merge
|
||||
|
||||
# Comment to be posted to on pull requests merged by a first time user
|
||||
firstPRMergeComment: >
|
||||
Congrats on merging your first pull request! 🎉🎉🎉
|
6
.gitignore
vendored
6
.gitignore
vendored
|
@ -50,4 +50,10 @@ tests/_support/_generated/*
|
|||
/storage/oauth-public.key
|
||||
|
||||
*.cache
|
||||
|
||||
.vagrant
|
||||
|
||||
\.php_cs\.dist
|
||||
|
||||
phpmd\.xml
|
||||
/public/storage
|
||||
|
|
11
.travis.yml
11
.travis.yml
|
@ -14,15 +14,11 @@ services:
|
|||
|
||||
# list any PHP version you want to test against
|
||||
php:
|
||||
- 5.6
|
||||
- 7.0
|
||||
- 7.1
|
||||
- 7.1.3
|
||||
- 7.1.4
|
||||
- 7.2
|
||||
- 7.3
|
||||
- 7.3.0
|
||||
|
||||
matrix:
|
||||
allow_failures:
|
||||
- php: 7.3
|
||||
|
||||
# execute any number of scripts before the test run, custom env's are available as variables
|
||||
before_script:
|
||||
|
@ -33,6 +29,7 @@ before_script:
|
|||
- mysql -e 'CREATE USER "travis'@'localhost";'
|
||||
- mysql -e 'GRANT ALL PRIVILEGES ON * . * TO "travis'@'localhost";'
|
||||
- mysql -e 'FLUSH PRIVILEGES;'
|
||||
- cp .env.testing-ci .env
|
||||
- composer self-update
|
||||
- composer install -n --prefer-source
|
||||
- chmod -R 777 storage
|
||||
|
|
65
Dockerfile
65
Dockerfile
|
@ -1,35 +1,58 @@
|
|||
FROM ubuntu:xenial
|
||||
MAINTAINER Brady Wetherington <uberbrady@gmail.com>
|
||||
FROM ubuntu:bionic
|
||||
LABEL maintainer Brady Wetherington <uberbrady@gmail.com>
|
||||
|
||||
RUN apt-get update && apt-get install -y \
|
||||
RUN export DEBIAN_FRONTEND=noninteractive; \
|
||||
export DEBCONF_NONINTERACTIVE_SEEN=true; \
|
||||
echo 'tzdata tzdata/Areas select Etc' | debconf-set-selections; \
|
||||
echo 'tzdata tzdata/Zones/Etc select UTC' | debconf-set-selections; \
|
||||
apt-get update -qqy \
|
||||
&& apt-get install -qqy --no-install-recommends \
|
||||
apt-utils \
|
||||
apache2 \
|
||||
apache2-bin \
|
||||
libapache2-mod-php7.0 \
|
||||
php7.0-curl \
|
||||
php7.0-ldap \
|
||||
php7.0-mysql \
|
||||
php7.0-mcrypt \
|
||||
php7.0-gd \
|
||||
php7.0-xml \
|
||||
php7.0-mbstring \
|
||||
php7.0-zip \
|
||||
php7.0-bcmath \
|
||||
libapache2-mod-php7.2 \
|
||||
php7.2-curl \
|
||||
php7.2-ldap \
|
||||
php7.2-mysql \
|
||||
php7.2-gd \
|
||||
php7.2-xml \
|
||||
php7.2-mbstring \
|
||||
php7.2-zip \
|
||||
php7.2-bcmath \
|
||||
patch \
|
||||
curl \
|
||||
wget \
|
||||
vim \
|
||||
git \
|
||||
cron \
|
||||
mysql-client \
|
||||
cron \
|
||||
gcc \
|
||||
make \
|
||||
autoconf \
|
||||
libc-dev \
|
||||
pkg-config \
|
||||
libmcrypt-dev \
|
||||
php7.2-dev \
|
||||
ca-certificates \
|
||||
unzip \
|
||||
&& apt-get clean \
|
||||
&& rm -rf /var/lib/apt/lists/* /tmp/* /var/tmp/*
|
||||
|
||||
|
||||
RUN curl -L -O https://github.com/pear/pearweb_phars/raw/master/go-pear.phar
|
||||
RUN php go-pear.phar
|
||||
|
||||
RUN pecl install mcrypt-1.0.2
|
||||
|
||||
RUN bash -c "echo extension=/usr/lib/php/20170718/mcrypt.so > /etc/php/7.2/mods-available/mcrypt.ini"
|
||||
|
||||
RUN phpenmod mcrypt
|
||||
RUN phpenmod gd
|
||||
RUN phpenmod bcmath
|
||||
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.0/apache2/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.0/cli/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.2/apache2/php.ini
|
||||
RUN sed -i 's/variables_order = .*/variables_order = "EGPCS"/' /etc/php/7.2/cli/php.ini
|
||||
|
||||
RUN useradd -m --uid 1000 --gid 50 docker
|
||||
|
||||
|
@ -40,11 +63,11 @@ COPY docker/000-default.conf /etc/apache2/sites-enabled/000-default.conf
|
|||
|
||||
#SSL
|
||||
RUN mkdir -p /var/lib/snipeit/ssl
|
||||
COPY docker/001-default-ssl.conf /etc/apache2/sites-enabled/001-default-ssl.conf
|
||||
#COPY docker/001-default-ssl.conf /etc/apache2/sites-available/001-default-ssl.conf
|
||||
#COPY docker/001-default-ssl.conf /etc/apache2/sites-enabled/001-default-ssl.conf
|
||||
COPY docker/001-default-ssl.conf /etc/apache2/sites-available/001-default-ssl.conf
|
||||
|
||||
RUN a2enmod ssl
|
||||
#RUN a2ensite 001-default-ssl.conf
|
||||
RUN a2ensite 001-default-ssl.conf
|
||||
|
||||
COPY . /var/www/html
|
||||
|
||||
|
@ -67,18 +90,18 @@ RUN \
|
|||
rm -r "/var/www/html/storage/private_uploads" && ln -fs "/var/lib/snipeit/data/private_uploads" "/var/www/html/storage/private_uploads" \
|
||||
&& rm -rf "/var/www/html/public/uploads" && ln -fs "/var/lib/snipeit/data/uploads" "/var/www/html/public/uploads" \
|
||||
&& rm -r "/var/www/html/storage/app/backups" && ln -fs "/var/lib/snipeit/dumps" "/var/www/html/storage/app/backups" \
|
||||
&& mkdir "/var/lib/snipeit/keys" && ln -fs "/var/lib/snipeit/keys/oauth-private.key" "/var/www/html/storage/oauth-private.key" \
|
||||
&& mkdir -p "/var/lib/snipeit/keys" && ln -fs "/var/lib/snipeit/keys/oauth-private.key" "/var/www/html/storage/oauth-private.key" \
|
||||
&& ln -fs "/var/lib/snipeit/keys/oauth-public.key" "/var/www/html/storage/oauth-public.key" \
|
||||
&& chown docker "/var/lib/snipeit/keys/"
|
||||
|
||||
############## DEPENDENCIES via COMPOSER ###################
|
||||
|
||||
#global install of composer
|
||||
RUN cd /tmp;curl -sS https://getcomposer.org/installer | php;mv /tmp/composer.phar /usr/local/bin/composer
|
||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||
|
||||
# Get dependencies
|
||||
USER docker
|
||||
RUN cd /var/www/html;composer install && rm -rf /home/docker/.composer/cache
|
||||
RUN composer install --no-dev --working-dir=/var/www/html
|
||||
USER root
|
||||
|
||||
############### APPLICATION INSTALL/INIT #################
|
||||
|
|
80
Dockerfile.alpine
Normal file
80
Dockerfile.alpine
Normal file
|
@ -0,0 +1,80 @@
|
|||
FROM alpine:3.8
|
||||
# Apache + PHP
|
||||
RUN apk add --update --no-cache \
|
||||
apache2 \
|
||||
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 \
|
||||
curl \
|
||||
wget \
|
||||
vim \
|
||||
git \
|
||||
mysql-client \
|
||||
tini
|
||||
|
||||
# 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/php7/php.ini
|
||||
COPY docker/000-default-2.4.conf /etc/apache2/conf.d/default.conf
|
||||
|
||||
# Enable mod_rewrite
|
||||
RUN sed -i '/LoadModule rewrite_module/s/^#//g' /etc/apache2/httpd.conf
|
||||
|
||||
COPY . /var/www/html
|
||||
|
||||
WORKDIR /var/www/html
|
||||
|
||||
COPY docker/docker.env /var/www/html/.env
|
||||
|
||||
RUN chown -R apache:apache /var/www/html
|
||||
|
||||
RUN \
|
||||
rm -r "/var/www/html/storage/private_uploads" \
|
||||
&& mkdir -p "/var/lib/snipeit/data/private_uploads" && ln -fs "/var/lib/snipeit/data/private_uploads" "/var/www/html/storage/private_uploads" \
|
||||
&& rm -rf "/var/www/html/public/uploads" \
|
||||
&& mkdir -p "/var/lib/snipeit/data/uploads" && ln -fs "/var/lib/snipeit/data/uploads" "/var/www/html/public/uploads" \
|
||||
&& mkdir -p "/var/lib/snipeit/dumps" && rm -r "/var/www/html/storage/app/backups" && ln -fs "/var/lib/snipeit/dumps" "/var/www/html/storage/app/backups" \
|
||||
&& mkdir -p "/var/lib/snipeit/keys" && ln -fs "/var/lib/snipeit/keys/oauth-private.key" "/var/www/html/storage/oauth-private.key" \
|
||||
&& ln -fs "/var/lib/snipeit/keys/oauth-public.key" "/var/www/html/storage/oauth-public.key" \
|
||||
&& chown -R apache "/var/lib/snipeit"
|
||||
|
||||
# Install composer
|
||||
COPY --from=composer:latest /usr/bin/composer /usr/bin/composer
|
||||
RUN mkdir -p /var/www/.composer && chown apache /var/www/.composer
|
||||
|
||||
# Install dependencies
|
||||
USER apache
|
||||
RUN COMPOSER_CACHE_DIR=/dev/null composer install --no-dev --working-dir=/var/www/html
|
||||
|
||||
USER root
|
||||
|
||||
VOLUME ["/var/lib/snipeit"]
|
||||
|
||||
# Entrypoints
|
||||
COPY docker/entrypoint_alpine.sh /entrypoint.sh
|
||||
RUN chmod +x /entrypoint.sh
|
||||
|
||||
ENTRYPOINT ["/sbin/tini", "--"]
|
||||
|
||||
CMD ["/entrypoint.sh"]
|
||||
|
||||
EXPOSE 80
|
36
README.md
36
README.md
|
@ -1,5 +1,5 @@
|
|||
[](https://travis-ci.org/snipe/snipe-it) [](https://crowdin.com/project/snipe-it) [](https://gitter.im/snipe/snipe-it?utm_source=badge&utm_medium=badge&utm_campaign=pr-badge&utm_content=badge) [](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://www.codetriage.com/snipe/snipe-it)
|
||||
[](#contributors) [](https://www.codetriage.com/snipe/snipe-it)
|
||||
|
||||
|
||||
## Snipe-IT - Open Source Asset Management System
|
||||
|
@ -64,6 +64,21 @@ As these were created by third-parties, Snipe-IT cannot provide support for thes
|
|||
|
||||
-----
|
||||
|
||||
### Contributing
|
||||
|
||||
Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing-overview).
|
||||
|
||||
|
||||
Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
|
||||
|
||||
-----
|
||||
|
||||
### Security
|
||||
|
||||
To report a security vulnerability, please email security@snipeitapp.com instead of using the issue tracker.
|
||||
|
||||
-----
|
||||
|
||||
### Contributors
|
||||
|
||||
Thanks goes to all of these wonderful people ([emoji key](https://github.com/kentcdodds/all-contributors#emoji-key)) who have helped Snipe-IT get this far:
|
||||
|
@ -95,22 +110,11 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
|||
| [<img src="https://avatars2.githubusercontent.com/u/982885?v=4" width="110px;"/><br /><sub>Martin Stub</sub>](http://martinstub.dk)<br />[🌍](#translation-stubben "Translation") | [<img src="https://avatars2.githubusercontent.com/u/28959963?v=4" width="110px;"/><br /><sub>Meyer Flavio</sub>](https://github.com/meyerf99)<br />[🌍](#translation-meyerf99 "Translation") | [<img src="https://avatars3.githubusercontent.com/u/796443?v=4" width="110px;"/><br /><sub>Micael Rodrigues</sub>](https://github.com/MicaelRodrigues)<br />[🌍](#translation-MicaelRodrigues "Translation") | [<img src="https://avatars0.githubusercontent.com/u/10481331?v=4" width="110px;"/><br /><sub>Mikael Rasmussen</sub>](http://rubixy.com/)<br />[🌍](#translation-mikaelssen "Translation") | [<img src="https://avatars1.githubusercontent.com/u/1544552?v=4" width="110px;"/><br /><sub>IxFail</sub>](https://github.com/IxFail)<br />[🌍](#translation-IxFail "Translation") | [<img src="https://avatars3.githubusercontent.com/u/18483118?v=4" width="110px;"/><br /><sub>Mohammed Fota</sub>](http://www.mohammedfota.com)<br />[🌍](#translation-MohammedFota "Translation") | [<img src="https://avatars0.githubusercontent.com/u/227080?v=4" width="110px;"/><br /><sub>Moayad Alserihi</sub>](https://github.com/omego)<br />[🌍](#translation-omego "Translation") |
|
||||
| [<img src="https://avatars0.githubusercontent.com/u/1680266?v=4" width="110px;"/><br /><sub>saymd</sub>](https://github.com/saymd)<br />[🌍](#translation-saymd "Translation") | [<img src="https://avatars0.githubusercontent.com/u/1826808?v=4" width="110px;"/><br /><sub>Patrik Larsson</sub>](https://nordsken.se)<br />[🌍](#translation-pooot "Translation") | [<img src="https://avatars1.githubusercontent.com/u/20584746?v=4" width="110px;"/><br /><sub>drcryo</sub>](https://github.com/drcryo)<br />[🌍](#translation-drcryo "Translation") | [<img src="https://avatars1.githubusercontent.com/u/19408004?v=4" width="110px;"/><br /><sub>pawel1615</sub>](https://github.com/pawel1615)<br />[🌍](#translation-pawel1615 "Translation") | [<img src="https://avatars2.githubusercontent.com/u/23340468?v=4" width="110px;"/><br /><sub>bodrovics</sub>](https://github.com/bodrovics)<br />[🌍](#translation-bodrovics "Translation") | [<img src="https://avatars0.githubusercontent.com/u/3257654?v=4" width="110px;"/><br /><sub>priatna</sub>](https://github.com/priatna)<br />[🌍](#translation-priatna "Translation") | [<img src="https://avatars1.githubusercontent.com/u/5358374?v=4" width="110px;"/><br /><sub>Fan Jiang</sub>](https://amayume.net)<br />[🌍](#translation-ProfFan "Translation") |
|
||||
| [<img src="https://avatars1.githubusercontent.com/u/22555451?v=4" width="110px;"/><br /><sub>ragnarcx</sub>](https://github.com/ragnarcx)<br />[🌍](#translation-ragnarcx "Translation") | [<img src="https://avatars2.githubusercontent.com/u/18654582?v=4" width="110px;"/><br /><sub>Rein van Haaren</sub>](http://www.reinvanhaaren.nl/)<br />[🌍](#translation-reinvanhaaren "Translation") | [<img src="https://avatars1.githubusercontent.com/u/386672?v=4" width="110px;"/><br /><sub>Teguh Dwicaksana</sub>](http://dheche.songolimo.net)<br />[🌍](#translation-dheche "Translation") | [<img src="https://avatars2.githubusercontent.com/u/2572552?v=4" width="110px;"/><br /><sub>fraccie</sub>](https://github.com/FRaccie)<br />[🌍](#translation-FRaccie "Translation") | [<img src="https://avatars0.githubusercontent.com/u/35182720?v=4" width="110px;"/><br /><sub>vinzruzell</sub>](https://github.com/vinzruzell)<br />[🌍](#translation-vinzruzell "Translation") | [<img src="https://avatars1.githubusercontent.com/u/7883603?v=4" width="110px;"/><br /><sub>Kevin Austin</sub>](http://kevinaustin.com)<br />[🌍](#translation-vipsystem "Translation") | [<img src="https://avatars3.githubusercontent.com/u/3861828?v=4" width="110px;"/><br /><sub>Wira Sandy</sub>](http://azuraweb.xyz)<br />[🌍](#translation-wira-sandy "Translation") |
|
||||
| [<img src="https://avatars2.githubusercontent.com/u/8663789?v=4" width="110px;"/><br /><sub>Илья</sub>](https://github.com/GrayHoax)<br />[🌍](#translation-GrayHoax "Translation") | [<img src="https://avatars3.githubusercontent.com/u/30119111?v=4" width="110px;"/><br /><sub>GodUseVPN</sub>](https://github.com/godusevpn)<br />[🌍](#translation-godusevpn "Translation") | [<img src="https://avatars1.githubusercontent.com/u/745576?v=4" width="110px;"/><br /><sub>周周</sub>](https://github.com/EngrZhou)<br />[🌍](#translation-EngrZhou "Translation") | [<img src="https://avatars3.githubusercontent.com/u/1631095?v=4" width="110px;"/><br /><sub>Sam</sub>](https://github.com/takuy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [<img src="https://avatars1.githubusercontent.com/u/264022?v=4" width="110px;"/><br /><sub>Azerothian</sub>](https://www.illisian.com.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") |
|
||||
| [<img src="https://avatars2.githubusercontent.com/u/8663789?v=4" width="110px;"/><br /><sub>Илья</sub>](https://github.com/GrayHoax)<br />[🌍](#translation-GrayHoax "Translation") | [<img src="https://avatars3.githubusercontent.com/u/30119111?v=4" width="110px;"/><br /><sub>GodUseVPN</sub>](https://github.com/godusevpn)<br />[🌍](#translation-godusevpn "Translation") | [<img src="https://avatars1.githubusercontent.com/u/745576?v=4" width="110px;"/><br /><sub>周周</sub>](https://github.com/EngrZhou)<br />[🌍](#translation-EngrZhou "Translation") | [<img src="https://avatars3.githubusercontent.com/u/1631095?v=4" width="110px;"/><br /><sub>Sam</sub>](https://github.com/takuy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=takuy "Code") | [<img src="https://avatars1.githubusercontent.com/u/264022?v=4" width="110px;"/><br /><sub>Azerothian</sub>](https://www.illisian.com.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Azerothian "Code") | [<img src="https://avatars1.githubusercontent.com/u/4930051?v=4" width="110px;"/><br /><sub>Wes Hulette</sub>](http://macfoo.wordpress.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jwhulette "Code") | [<img src="https://avatars0.githubusercontent.com/u/8134591?v=4" width="110px;"/><br /><sub>patrict</sub>](https://github.com/patrict)<br />[💻](https://github.com/snipe/snipe-it/commits?author=patrict "Code") |
|
||||
| [<img src="https://avatars3.githubusercontent.com/u/2611616?v=4" width="110px;"/><br /><sub>Dmitriy Minaev</sub>](https://github.com/VELIKII-DIVAN)<br />[💻](https://github.com/snipe/snipe-it/commits?author=VELIKII-DIVAN "Code") | [<img src="https://avatars0.githubusercontent.com/u/5132245?v=4" width="110px;"/><br /><sub>liquidhorse</sub>](https://github.com/liquidhorse)<br />[💻](https://github.com/snipe/snipe-it/commits?author=liquidhorse "Code") | [<img src="https://avatars1.githubusercontent.com/u/183678?v=4" width="110px;"/><br /><sub>Jordi Boggiano</sub>](https://seld.be/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Seldaek "Code") | [<img src="https://avatars0.githubusercontent.com/u/653557?v=4" width="110px;"/><br /><sub>Ivan Nieto</sub>](https://github.com/inietov)<br />[💻](https://github.com/snipe/snipe-it/commits?author=inietov "Code") | [<img src="https://avatars2.githubusercontent.com/u/6764151?v=4" width="110px;"/><br /><sub>Ben RUBSON</sub>](https://github.com/benrubson)<br />[💻](https://github.com/snipe/snipe-it/commits?author=benrubson "Code") | [<img src="https://avatars2.githubusercontent.com/u/8554558?v=4" width="110px;"/><br /><sub>NMathar</sub>](https://github.com/NMathar)<br />[💻](https://github.com/snipe/snipe-it/commits?author=NMathar "Code") | [<img src="https://avatars1.githubusercontent.com/u/139566?v=4" width="110px;"/><br /><sub>Steffen</sub>](https://github.com/smb)<br />[💻](https://github.com/snipe/snipe-it/commits?author=smb "Code") |
|
||||
| [<img src="https://avatars0.githubusercontent.com/u/6609453?v=4" width="110px;"/><br /><sub>Sxderp</sub>](https://github.com/Sxderp)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Sxderp "Code") | [<img src="https://avatars1.githubusercontent.com/u/4807843?v=4" width="110px;"/><br /><sub>fanta8897</sub>](https://github.com/fanta8897)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fanta8897 "Code") | [<img src="https://avatars2.githubusercontent.com/u/2576509?v=4" width="110px;"/><br /><sub>Andrey Bolonin</sub>](https://andreybolonin.com/phpconsulting/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=andreybolonin "Code") | [<img src="https://avatars3.githubusercontent.com/u/2173307?v=4" width="110px;"/><br /><sub>shinayoshi</sub>](http://www.shinayoshi.net/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=shinayoshi "Code") | [<img src="https://avatars3.githubusercontent.com/u/2130159?v=4" width="110px;"/><br /><sub>Hubert</sub>](https://github.com/reuser)<br />[💻](https://github.com/snipe/snipe-it/commits?author=reuser "Code") | [<img src="https://avatars0.githubusercontent.com/u/6865789?v=4" width="110px;"/><br /><sub>KeenRivals</sub>](https://brashear.me)<br />[💻](https://github.com/snipe/snipe-it/commits?author=KeenRivals "Code") | [<img src="https://avatars3.githubusercontent.com/u/2902513?v=4" width="110px;"/><br /><sub>omyno</sub>](https://github.com/omyno)<br />[💻](https://github.com/snipe/snipe-it/commits?author=omyno "Code") |
|
||||
| [<img src="https://avatars1.githubusercontent.com/u/6271335?v=4" width="110px;"/><br /><sub>Evgeny</sub>](https://github.com/jackka)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jackka "Code") | [<img src="https://avatars2.githubusercontent.com/u/1169963?v=4" width="110px;"/><br /><sub>Colin Campbell</sub>](https://digitalist.se)<br />[💻](https://github.com/snipe/snipe-it/commits?author=colin-campbell "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
-----
|
||||
|
||||
### Contributing
|
||||
|
||||
Please see the documentation on [contributing and developing for Snipe-IT](https://snipe-it.readme.io/docs/contributing-overview).
|
||||
|
||||
|
||||
Please note that this project is released with a [Contributor Code of Conduct](CODE_OF_CONDUCT.md). By participating in this project you agree to abide by its terms.
|
||||
|
||||
-----
|
||||
|
||||
### Security
|
||||
|
||||
To report a security vulnerability, please email security@snipeitapp.com instead of using the issue tracker.
|
||||
|
|
18
Vagrantfile
vendored
18
Vagrantfile
vendored
|
@ -81,4 +81,22 @@ Vagrant.configure("2") do |config|
|
|||
fedora26.vm.provision :shell, :inline => "wget #{SNIPEIT_SH_URL}"
|
||||
fedora26.vm.provision :shell, :inline => "chmod 755 snipeit.sh"
|
||||
end
|
||||
|
||||
config.vm.define "freebsd" do |freebsd|
|
||||
freebsd.vm.box = "freebsd/FreeBSD-11.2-RELEASE"
|
||||
freebsd.vm.hostname = 'freebsd12'
|
||||
freebsd.vm.network "forwarded_port", guest: 80, host: 8080
|
||||
freebsd.vm.network "forwarded_port", guest:3306, host:3306 # mysql
|
||||
freebsd.vm.network "private_network", type: "dhcp"
|
||||
freebsd.ssh.shell = "sh"
|
||||
freebsd.vm.base_mac = "080027D14C66"
|
||||
freebsd.vm.synced_folder ".", "/vagrant", :nfs => true, id: "vagrant-root",
|
||||
:mount_options => ['rw', 'vers=3', 'tcp', 'actimeo=2']
|
||||
freebsd.vm.provision "shell", inline: <<-SHELL
|
||||
pkg install -y python27;
|
||||
SHELL
|
||||
freebsd.vm.provision "ansible" do |ansible|
|
||||
ansible.playbook = "ansible/freebsd/vagrant_playbook.yml"
|
||||
end
|
||||
end
|
||||
end
|
||||
|
|
260
ansible/freebsd/vagrant_playbook.yml
Normal file
260
ansible/freebsd/vagrant_playbook.yml
Normal file
|
@ -0,0 +1,260 @@
|
|||
---
|
||||
- name: Set up local server
|
||||
hosts: all
|
||||
remote_user: vagrant
|
||||
become_user: root
|
||||
become_method: sudo
|
||||
vars:
|
||||
- ansible_python_interpreter: /usr/local/bin/python2.7
|
||||
gather_facts: no
|
||||
|
||||
# Tasks
|
||||
tasks:
|
||||
|
||||
#
|
||||
# Update the PKG database
|
||||
#
|
||||
- name: Upgrade PKG database
|
||||
raw: sudo pkg upgrade -y
|
||||
|
||||
#
|
||||
# Mount the shared folders
|
||||
#
|
||||
- name: Update Vagrant Shared Folders
|
||||
command: "{{ item }}"
|
||||
with_items:
|
||||
- sysrc rpc_lockd_enable=YES
|
||||
- sysrc rpc_statd_enable=YES
|
||||
become: true
|
||||
|
||||
#
|
||||
# Install required utilities
|
||||
#
|
||||
- name: Install Utilities
|
||||
pkgng:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
with_items:
|
||||
- openssl
|
||||
- node
|
||||
- npm
|
||||
- git
|
||||
- nano
|
||||
- wget
|
||||
- bash
|
||||
become: true
|
||||
|
||||
#
|
||||
# Install php and php dependancies
|
||||
#
|
||||
- name: Install PHP dependancies
|
||||
pkgng:
|
||||
name: "{{ item }}"
|
||||
state: present
|
||||
with_items:
|
||||
- php72
|
||||
- php72-zip
|
||||
- php72-zlib
|
||||
- php72-extensions
|
||||
- php72-mbstring
|
||||
- php72-openssl
|
||||
# - php72-mysqli
|
||||
- php72-curl
|
||||
- php72-soap
|
||||
- php72-pdo_mysql
|
||||
# - php72-pdo_pgsql
|
||||
- php72-ldap
|
||||
- php72-curl
|
||||
- php72-fileinfo
|
||||
- php72-bcmath
|
||||
- php72-gd
|
||||
become: true
|
||||
|
||||
#
|
||||
# Create a php.ini file
|
||||
#
|
||||
- name: PHP INI check
|
||||
stat:
|
||||
path: /usr/local/etc/php.ini
|
||||
register: php_ini_exits
|
||||
|
||||
- name: Create PHP ini
|
||||
command: cp /usr/local/etc/php.ini-development /usr/local/etc/php.ini
|
||||
become: true
|
||||
when: not php_ini_exits.stat.exists
|
||||
|
||||
- name: Enable PHP-FPM auto-start
|
||||
command: sysrc php_fpm_enable=YES
|
||||
become: true
|
||||
|
||||
- name: Start PHP-FPM service
|
||||
service:
|
||||
name: php-fpm
|
||||
state: started
|
||||
become: true
|
||||
|
||||
#
|
||||
# Install the lastest version of composer
|
||||
#
|
||||
- name: Composer check
|
||||
stat:
|
||||
path: /usr/local/bin/composer
|
||||
register: composer_exits
|
||||
|
||||
- name: Install Composer
|
||||
shell: |
|
||||
EXPECTED_SIGNATURE=$(wget -q -O - https://composer.github.io/installer.sig)
|
||||
php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
|
||||
ACTUAL_SIGNATURE=$(php -r "echo hash_file('SHA384', 'composer-setup.php');")
|
||||
|
||||
if [ "$EXPECTED_SIGNATURE" != "$ACTUAL_SIGNATURE" ]
|
||||
then
|
||||
>&2 echo 'ERROR: Invalid installer signature'
|
||||
rm composer-setup.php
|
||||
exit 1
|
||||
fi
|
||||
|
||||
php composer-setup.php --quiet
|
||||
RESULT=$?
|
||||
rm composer-setup.php
|
||||
mv composer.phar /usr/local/bin/composer
|
||||
exit $RESULT
|
||||
when: not composer_exits.stat.exists
|
||||
become: true
|
||||
|
||||
#
|
||||
# Install MySQL Server
|
||||
|
||||
- name: Install MySQL 5.7
|
||||
pkgng:
|
||||
name: mysql57-server
|
||||
state: present
|
||||
become: true
|
||||
register: sql_server
|
||||
|
||||
- name: Start MySQL server
|
||||
service:
|
||||
name: mysql-server
|
||||
state: started
|
||||
become: true
|
||||
|
||||
- name: MySQL 5.7 auto-start
|
||||
command: sysrc mysql_enable=YES
|
||||
become: true
|
||||
when: sql_server.changed == true
|
||||
|
||||
- name: Get MySQL root password
|
||||
command: tail -1 /root/.mysql_secret
|
||||
register: myql_root_pwd
|
||||
become: true
|
||||
when: sql_server.changed == true
|
||||
|
||||
- name: Change MySQL root password
|
||||
command: mysqladmin -u root -p'{{myql_root_pwd.stdout}}' password vagrant
|
||||
when: sql_server.changed == true
|
||||
|
||||
- name: Enable remote mysql
|
||||
replace:
|
||||
path: /usr/local/etc/mysql/my.cnf
|
||||
regexp: "127.0.0.1"
|
||||
replace: "0.0.0.0"
|
||||
become: true
|
||||
when: sql_server.changed == true
|
||||
|
||||
- name: Grant user vagrant privelages
|
||||
shell: mysql -u root -pvagrant -e "GRANT ALL PRIVILEGES ON *.* TO 'root'@'%' IDENTIFIED BY 'vagrant' WITH GRANT OPTION; FLUSH PRIVILEGES;"
|
||||
become: true
|
||||
when: sql_server.changed == true
|
||||
ignore_errors: true
|
||||
|
||||
- name: Restart MySQL server
|
||||
service:
|
||||
name: mysql-server
|
||||
state: restarted
|
||||
become: true
|
||||
|
||||
|
||||
#
|
||||
# Install Apache Web Server
|
||||
#
|
||||
- name: Install Apache 2.4
|
||||
pkgng:
|
||||
name: apache24
|
||||
state: present
|
||||
become: true
|
||||
register: apache24_server
|
||||
|
||||
- name: Apache 2.4 auto-start
|
||||
command: sysrc apache24_enable=YES
|
||||
become: true
|
||||
when: apache24_server.changed == true
|
||||
|
||||
- name: Enable Apache modules
|
||||
replace:
|
||||
path: /usr/local/etc/apache24/httpd.conf
|
||||
regexp: "#{{ item }}"
|
||||
replace: "{{ item }}"
|
||||
become: true
|
||||
with_items:
|
||||
- LoadModule rewrite_module libexec/apache24/mod_rewrite.so
|
||||
- LoadModule vhost_alias_module libexec/apache24/mod_vhost_alias.so
|
||||
- LoadModule deflate_module libexec/apache24/mod_deflate.so
|
||||
- LoadModule expires_module libexec/apache24/mod_expires.so
|
||||
- LoadModule mpm_worker_module libexec/apache24/mod_mpm_worker.so
|
||||
- LoadModule proxy_fcgi_module libexec/apache24/mod_proxy_fcgi.so
|
||||
- LoadModule proxy_module libexec/apache24/mod_proxy.so
|
||||
- Include etc/apache24/extra/httpd-vhosts.conf
|
||||
when: apache24_server.changed == true
|
||||
|
||||
- name: Disable Apache modules
|
||||
replace:
|
||||
path: /usr/local/etc/apache24/httpd.conf
|
||||
regexp: "{{ item }}"
|
||||
replace: "#{{ item }}"
|
||||
become: true
|
||||
with_items:
|
||||
- LoadModule mpm_prefork_module libexec/apache24/mod_mpm_prefork.so
|
||||
when: apache24_server.changed == true
|
||||
|
||||
- name: Backup vhosts
|
||||
command: cp /usr/local/etc/apache24/extra/httpd-vhosts.conf /usr/local/etc/apache24/extra/httpd-vhosts.conf.bak
|
||||
become: true
|
||||
when: apache24_server.changed == true
|
||||
|
||||
- name: Truncate vhosts
|
||||
command: truncate -s 0 /usr/local/etc/apache24/extra/httpd-vhosts.conf
|
||||
become: true
|
||||
when: apache24_server.changed == true
|
||||
|
||||
- name: Set up vhost
|
||||
blockinfile:
|
||||
path: "/usr/local/etc/apache24/extra/httpd-vhosts.conf"
|
||||
block: |
|
||||
<VirtualHost *>
|
||||
DocumentRoot /usr/local/www/apache24/data/public
|
||||
ServerName vagrant.app
|
||||
ProxyPassMatch ^/(.*\.php(/.*)?)$ fcgi://127.0.0.1:9000/usr/local/www/apache24/data/public/$1
|
||||
DirectoryIndex /index.php index.php
|
||||
<Directory /usr/local/www/apache24/data/public>
|
||||
Options -Indexes +FollowSymLinks
|
||||
AllowOverride All
|
||||
Require all granted
|
||||
</Directory>
|
||||
</VirtualHost>
|
||||
become: true
|
||||
when: apache24_server.changed == true
|
||||
|
||||
- name: Map apache dir to local folder
|
||||
shell: |
|
||||
if ! [ -L /var/www ]; then
|
||||
rm -rf /usr/local/www/apache24/data;
|
||||
ln -fs /vagrant /usr/local/www/apache24/data;
|
||||
fi
|
||||
become: true
|
||||
when: apache24_server.changed == true
|
||||
|
||||
- name: Start Apache 2.4 server
|
||||
service:
|
||||
name: apache24
|
||||
state: started
|
||||
become: true
|
|
@ -76,10 +76,4 @@ class CreateAdmin extends Command
|
|||
|
||||
}
|
||||
|
||||
// protected function getArguments()
|
||||
// {
|
||||
// return array(
|
||||
// array('username', InputArgument::REQUIRED, 'Username'),
|
||||
// );
|
||||
// }
|
||||
}
|
||||
|
|
|
@ -41,7 +41,7 @@ class DisableLDAP extends Command
|
|||
|
||||
if ($this->confirm("\n****************************************************\nThis will disable LDAP support. You will not be able \nto login with an account that does not exist \nlocally in the Snipe-IT local database. \n****************************************************\n\nDo you wish to continue? [y|N]")) {
|
||||
|
||||
$setting = Setting::first();
|
||||
$setting = Setting::getSettings();
|
||||
$setting->ldap_enabled = 0;
|
||||
if ($setting->save()) {
|
||||
$this->info('LDAP has been set to disabled.');
|
||||
|
|
|
@ -71,7 +71,7 @@ class FixDoubleEscape extends Command
|
|||
|
||||
foreach($classname::where("$field",'LIKE','%&%')->get() as $row) {
|
||||
$this->info('Updating '.$field.' for '.$classname);
|
||||
$row->{$field} = html_entity_decode($row->{$field});
|
||||
$row->{$field} = html_entity_decode($row->{$field},ENT_QUOTES);
|
||||
$row->save();
|
||||
$count[$classname][$field]++;
|
||||
|
||||
|
|
|
@ -1,14 +1,23 @@
|
|||
<?php
|
||||
|
||||
declare(strict_types=1);
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Ldap;
|
||||
use App\Models\User;
|
||||
use App\Services\LdapAd;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Exception;
|
||||
use App\Models\Location;
|
||||
use Log;
|
||||
use Illuminate\Console\Command;
|
||||
use Adldap\Models\User as AdldapUser;
|
||||
|
||||
/**
|
||||
* LDAP / AD sync command.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
class LdapSync extends Command
|
||||
{
|
||||
/**
|
||||
|
@ -16,23 +25,75 @@ class LdapSync extends Command
|
|||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:ldap-sync {--location=} {--location_id=} {--base_dn=} {--summary} {--json_summary}';
|
||||
protected $signature = 'snipeit:ldap-sync
|
||||
{--location= : A location name }
|
||||
{--location_id= : A location id}
|
||||
{--base_dn= : A diffrent base DN to use }
|
||||
{--summary : Print summary }
|
||||
{--json_summary : Print summary in json format }
|
||||
{--dryrun : Run the sync process but don\'t update the database}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command line LDAP sync';
|
||||
protected $description = 'Command line LDAP/AD sync';
|
||||
|
||||
/**
|
||||
* An LdapAd instance.
|
||||
*
|
||||
* @var \App\Models\LdapAd
|
||||
*/
|
||||
private $ldap;
|
||||
|
||||
/**
|
||||
* A default location collection.
|
||||
*
|
||||
* @var \Illuminate\Support\Collection
|
||||
*/
|
||||
private $defaultLocation = null;
|
||||
|
||||
/**
|
||||
* Mapped locations collection.
|
||||
*
|
||||
* @var \Illuminate\Support\Collection
|
||||
*/
|
||||
private $mappedLocations = null;
|
||||
|
||||
/**
|
||||
* The summary collection.
|
||||
*
|
||||
* @var \Illuminate\Support\Collection
|
||||
*/
|
||||
private $summary;
|
||||
|
||||
/**
|
||||
* Is dry-run?
|
||||
*
|
||||
* @var bool
|
||||
*/
|
||||
private $dryrun = false;
|
||||
|
||||
/**
|
||||
* Show users to be imported.
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
private $userlist = [];
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
* @param LdapAd $ldap
|
||||
*/
|
||||
public function __construct()
|
||||
public function __construct(LdapAd $ldap)
|
||||
{
|
||||
|
||||
parent::__construct();
|
||||
$this->summary = collect();
|
||||
|
||||
$this->ldap = $ldap;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -42,207 +103,280 @@ class LdapSync extends Command
|
|||
*/
|
||||
public function handle()
|
||||
{
|
||||
ini_set('max_execution_time', 600); //600 seconds = 10 minutes
|
||||
ini_set('max_execution_time', '600'); //600 seconds = 10 minutes
|
||||
ini_set('memory_limit', '500M');
|
||||
|
||||
$ldap_result_username = Setting::getSettings()->ldap_username_field;
|
||||
$ldap_result_last_name = Setting::getSettings()->ldap_lname_field;
|
||||
$ldap_result_first_name = Setting::getSettings()->ldap_fname_field;
|
||||
|
||||
$ldap_result_active_flag = Setting::getSettings()->ldap_active_flag_field;
|
||||
$ldap_result_emp_num = Setting::getSettings()->ldap_emp_num;
|
||||
$ldap_result_email = Setting::getSettings()->ldap_email;
|
||||
|
||||
try {
|
||||
$ldapconn = Ldap::connectToLdap();
|
||||
Ldap::bindAdminToLdap($ldapconn);
|
||||
} catch (\Exception $e) {
|
||||
if ($this->option('json_summary')) {
|
||||
$json_summary = [ "error" => true, "error_message" => $e->getMessage(), "summary" => [] ];
|
||||
$this->info(json_encode($json_summary));
|
||||
}
|
||||
LOG::error($e);
|
||||
return [];
|
||||
if ($this->option('dryrun')) {
|
||||
$this->dryrun = true;
|
||||
}
|
||||
|
||||
$summary = array();
|
||||
$this->checkIfLdapIsEnabled();
|
||||
$this->checkLdapConnetion();
|
||||
$this->setBaseDn();
|
||||
$this->getUserDefaultLocation();
|
||||
/*
|
||||
* Use the default location if set, this is needed for the LDAP users sync page
|
||||
*/
|
||||
if (!$this->option('base_dn') && null == $this->defaultLocation) {
|
||||
$this->getMappedLocations();
|
||||
}
|
||||
$this->processLdapUsers();
|
||||
|
||||
try {
|
||||
if ($this->option('base_dn') != '') {
|
||||
$search_base = $this->option('base_dn');
|
||||
LOG::debug('Importing users from specified base DN: \"'.$search_base.'\".');
|
||||
} else {
|
||||
$search_base = null;
|
||||
}
|
||||
$results = Ldap::findLdapUsers($search_base);
|
||||
} catch (\Exception $e) {
|
||||
if ($this->option('json_summary')) {
|
||||
$json_summary = [ "error" => true, "error_message" => $e->getMessage(), "summary" => [] ];
|
||||
$this->info(json_encode($json_summary));
|
||||
}
|
||||
LOG::error($e);
|
||||
return [];
|
||||
// Print table of users
|
||||
if ($this->dryrun) {
|
||||
$this->info('The following users will be synced!');
|
||||
$headers = ['First Name', 'Last Name', 'Username', 'Email', 'Employee #', 'Location Id', 'Status'];
|
||||
$this->table($headers, $this->summary->toArray());
|
||||
}
|
||||
|
||||
/* Determine which location to assign users to by default. */
|
||||
$location = NULL;
|
||||
|
||||
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.')');
|
||||
} 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.')');
|
||||
}
|
||||
|
||||
if (!isset($location)) {
|
||||
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. */
|
||||
if ($this->option('base_dn')=='') {
|
||||
// Retrieve locations with a mapped OU, and sort them from the shallowest to deepest OU (see #3993)
|
||||
$ldap_ou_locations = Location::where('ldap_ou', '!=', '')->get()->toArray();
|
||||
$ldap_ou_lengths = array();
|
||||
|
||||
foreach ($ldap_ou_locations as $location) {
|
||||
$ldap_ou_lengths[] = strlen($location["ldap_ou"]);
|
||||
}
|
||||
|
||||
array_multisort($ldap_ou_lengths, SORT_ASC, $ldap_ou_locations);
|
||||
|
||||
if (sizeof($ldap_ou_locations) > 0) {
|
||||
LOG::debug('Some locations have special OUs set. Locations will be automatically set for users in those OUs.');
|
||||
}
|
||||
|
||||
// Inject location information fields
|
||||
for ($i = 0; $i < $results["count"]; $i++) {
|
||||
$results[$i]["ldap_location_override"] = false;
|
||||
$results[$i]["location_id"] = 0;
|
||||
}
|
||||
|
||||
// Grab subsets based on location-specific DNs, and overwrite location for these users.
|
||||
foreach ($ldap_ou_locations as $ldap_loc) {
|
||||
$location_users = Ldap::findLdapUsers($ldap_loc["ldap_ou"]);
|
||||
$usernames = array();
|
||||
for ($i = 0; $i < $location_users["count"]; $i++) {
|
||||
|
||||
if (array_key_exists($ldap_result_username, $location_users[$i])) {
|
||||
$location_users[$i]["ldap_location_override"] = true;
|
||||
$location_users[$i]["location_id"] = $ldap_loc["id"];
|
||||
$usernames[] = $location_users[$i][$ldap_result_username][0];
|
||||
}
|
||||
return $this->getSummary();
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate the LDAP sync summary.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
private function getSummary(): string
|
||||
{
|
||||
if ($this->option('summary') && !$this->dryrun) {
|
||||
$this->summary->each(function ($item) {
|
||||
if ('ERROR' === $item['status']) {
|
||||
$this->error('ERROR: '.$item['note']);
|
||||
}
|
||||
|
||||
// Delete located users from the general group.
|
||||
foreach ($results as $key => $generic_entry) {
|
||||
if ((is_array($generic_entry)) && (array_key_exists($ldap_result_username, $generic_entry))) {
|
||||
if (in_array($generic_entry[$ldap_result_username][0], $usernames)) {
|
||||
unset($results[$key]);
|
||||
}
|
||||
}
|
||||
else {
|
||||
$this->info('USER: '.$item['note']);
|
||||
}
|
||||
|
||||
$global_count = $results['count'];
|
||||
$results = array_merge($location_users, $results);
|
||||
$results['count'] = $global_count;
|
||||
}
|
||||
}
|
||||
|
||||
/* Create user account entries in Snipe-IT */
|
||||
$tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
|
||||
$pass = bcrypt($tmp_pass);
|
||||
|
||||
for ($i = 0; $i < $results["count"]; $i++) {
|
||||
if (empty($ldap_result_active_flag) || $results[$i][$ldap_result_active_flag][0] == "TRUE") {
|
||||
|
||||
$item = array();
|
||||
$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"]:"";
|
||||
|
||||
|
||||
// This is active directory, not regular LDAP
|
||||
if ( array_key_exists('useraccountcontrol', $results[$i]) ) {
|
||||
$enabled_accounts = [
|
||||
'512', '544', '66048', '66080', '262656', '262688', '328192', '328224'
|
||||
];
|
||||
$item['activated'] = ( in_array($results[$i]['useraccountcontrol'][0], $enabled_accounts) ) ? 1 : 0;
|
||||
|
||||
// Fall through to LDAP
|
||||
} else {
|
||||
$item['activated'] = 0;
|
||||
}
|
||||
|
||||
// User exists
|
||||
$item["createorupdate"] = 'updated';
|
||||
if (!$user = User::where('username', $item["username"])->first()) {
|
||||
$user = new User;
|
||||
$user->password = $pass;
|
||||
$item["createorupdate"] = 'created';
|
||||
}
|
||||
|
||||
// Create the user if they don't exist.
|
||||
$user->first_name = e($item["firstname"]);
|
||||
$user->last_name = e($item["lastname"]);
|
||||
$user->username = e($item["username"]);
|
||||
$user->email = e($item["email"]);
|
||||
$user->employee_num = e($item["employee_number"]);
|
||||
$user->activated = $item['activated'];
|
||||
|
||||
if ($item['ldap_location_override'] == true) {
|
||||
$user->location_id = $item['location_id'];
|
||||
} elseif ((isset($location)) && (!empty($location))) {
|
||||
|
||||
if ((is_array($location)) && (array_key_exists('id', $location))) {
|
||||
$user->location_id = $location['id'];
|
||||
} elseif (is_object($location)) {
|
||||
$user->location_id = $location->id;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$user->notes = 'Imported from LDAP';
|
||||
$user->ldap_import = 1;
|
||||
|
||||
$errors = '';
|
||||
|
||||
if ($user->save()) {
|
||||
$item["note"] = $item["createorupdate"];
|
||||
$item["status"]='success';
|
||||
} else {
|
||||
foreach ($user->getErrors()->getMessages() as $key => $err) {
|
||||
$errors .= $err[0];
|
||||
}
|
||||
$item["note"] = $errors;
|
||||
$item["status"]='error';
|
||||
}
|
||||
|
||||
array_push($summary, $item);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
if ($this->option('summary')) {
|
||||
for ($x = 0; $x < count($summary); $x++) {
|
||||
if ($summary[$x]['status']=='error') {
|
||||
$this->error('ERROR: '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].') was not imported: '.$summary[$x]['note']);
|
||||
} else {
|
||||
$this->info('User '.$summary[$x]['firstname'].' '.$summary[$x]['lastname'].' (username: '.$summary[$x]['username'].') was '.strtoupper($summary[$x]['createorupdate']).'.');
|
||||
}
|
||||
}
|
||||
} else if ($this->option('json_summary')) {
|
||||
$json_summary = [ "error" => false, "error_message" => "", "summary" => $summary ];
|
||||
});
|
||||
} elseif ($this->option('json_summary')) {
|
||||
$json_summary = [
|
||||
'error' => false,
|
||||
'error_message' => '',
|
||||
'summary' => $this->summary->toArray(),
|
||||
];
|
||||
$this->info(json_encode($json_summary));
|
||||
} else {
|
||||
return $summary;
|
||||
}
|
||||
|
||||
return '';
|
||||
}
|
||||
|
||||
/**
|
||||
* Create a new user or update an existing user.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param \Adldap\Models\User $snipeUser
|
||||
*/
|
||||
private function updateCreateUser(AdldapUser $snipeUser): void
|
||||
{
|
||||
$user = $this->ldap->processUser($snipeUser, $this->defaultLocation, $this->mappedLocations);
|
||||
if(!$user) {
|
||||
$summary['note'] = sprintf("'%s' was not imported. REASON: User inactive or not found", $snipeUser->ou);
|
||||
$summary['status'] = 'ERROR';
|
||||
$this->summary->push($summary);
|
||||
return;
|
||||
}
|
||||
$summary = [
|
||||
'firstname' => $user->first_name,
|
||||
'lastname' => $user->last_name,
|
||||
'username' => $user->username,
|
||||
'employee_number' => $user->employee_num,
|
||||
'email' => $user->email,
|
||||
'location_id' => $user->location_id,
|
||||
];
|
||||
// Only update the database if is not a dry run
|
||||
if (!$this->dryrun) {
|
||||
if ($user->save()) {
|
||||
$summary['note'] = sprintf("'%s' %s", $user->username, ($user->wasRecentlyCreated ? 'CREATED' : 'UPDATED'));
|
||||
$summary['status'] = 'SUCCESS';
|
||||
} else {
|
||||
$errors = '';
|
||||
foreach ($user->getErrors()->getMessages() as $error) {
|
||||
$errors .= $error[0];
|
||||
}
|
||||
$summary['note'] = sprintf("'%s' was not imported. REASON: %s", $user->username, $errors);
|
||||
$summary['status'] = 'ERROR';
|
||||
}
|
||||
}
|
||||
|
||||
//$summary['note'] = ($user->getOriginal('username') ? 'UPDATED' : 'CREATED');
|
||||
$this->summary->push($summary);
|
||||
}
|
||||
|
||||
/**
|
||||
* Process the users to update / create.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param int $page The page to get the result set
|
||||
*/
|
||||
private function processLdapUsers(int $page=0): void
|
||||
{
|
||||
try {
|
||||
$ldapUsers = $this->ldap->getLdapUsers($page);
|
||||
} catch (Exception $e) {
|
||||
$this->outputError($e);
|
||||
exit($e->getMessage());
|
||||
}
|
||||
|
||||
if (0 == $ldapUsers->count()) {
|
||||
$msg = 'ERROR: No users found!';
|
||||
Log::error($msg);
|
||||
if ($this->dryrun) {
|
||||
$this->error($msg);
|
||||
}
|
||||
exit($msg);
|
||||
}
|
||||
|
||||
// Process each individual users
|
||||
foreach ($ldapUsers as $user) {
|
||||
$this->updateCreateUser($user);
|
||||
}
|
||||
|
||||
if ($ldapUsers->getCurrentPage() < $ldapUsers->getPages()) {
|
||||
$this->processLdapUsers($ldapUsers->getCurrentPage() + 1);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mapped locations if a base_dn is provided.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
private function getMappedLocations()
|
||||
{
|
||||
$ldapOuLocation = Location::where('ldap_ou', '!=', '')->select(['id', 'ldap_ou'])->get();
|
||||
$locations = $ldapOuLocation->sortBy(function ($ou, $key) {
|
||||
return strlen($ou->ldap_ou);
|
||||
});
|
||||
if ($locations->count() > 0) {
|
||||
$msg = 'Some locations have special OUs set. Locations will be automatically set for users in those OUs.';
|
||||
LOG::debug($msg);
|
||||
if ($this->dryrun) {
|
||||
$this->info($msg);
|
||||
}
|
||||
|
||||
$this->mappedLocations = $locations->pluck('ldap_ou', 'id');
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Set the base dn if supplied.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
private function setBaseDn(): void
|
||||
{
|
||||
if ($this->option('base_dn')) {
|
||||
$this->ldap->baseDn = $this->option('base_dn');
|
||||
$msg = sprintf('Importing users from specified base DN: "%s"', $this->ldap->baseDn);
|
||||
LOG::debug($msg);
|
||||
if ($this->dryrun) {
|
||||
$this->info($msg);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a default location id for imported users.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
private function getUserDefaultLocation(): void
|
||||
{
|
||||
$location = $this->option('location_id') ?? $this->option('location');
|
||||
if ($location) {
|
||||
$userLocation = Location::where('name', '=', $location)
|
||||
->orWhere('id', '=', intval($location))
|
||||
->select(['name', 'id'])
|
||||
->first();
|
||||
if ($userLocation) {
|
||||
$msg = 'Importing users with default location: '.$userLocation->name.' ('.$userLocation->id.')';
|
||||
LOG::debug($msg);
|
||||
|
||||
if ($this->dryrun) {
|
||||
$this->info($msg);
|
||||
}
|
||||
|
||||
$this->defaultLocation = collect([
|
||||
$userLocation->id => $userLocation->name,
|
||||
]);
|
||||
} else {
|
||||
$msg = 'The supplied location is invalid!';
|
||||
LOG::error($msg);
|
||||
if ($this->dryrun) {
|
||||
$this->error($msg);
|
||||
}
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check if LDAP intergration is enabled.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
private function checkIfLdapIsEnabled(): void
|
||||
{
|
||||
if (!$this->ldap->init()) {
|
||||
$msg = 'LDAP intergration is not enabled. Exiting sync process.';
|
||||
$this->info($msg);
|
||||
Log::info($msg);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Check to make sure we can access the server.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*/
|
||||
private function checkLdapConnetion(): void
|
||||
{
|
||||
try {
|
||||
$this->ldap->testLdapAdUserConnection();
|
||||
$this->ldap->testLdapAdBindConnection();
|
||||
} catch (Exception $e) {
|
||||
$this->outputError($e);
|
||||
exit(0);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Output the json summary to the screen if enabled.
|
||||
*
|
||||
* @param Exception $error
|
||||
*/
|
||||
private function outputError($error): void
|
||||
{
|
||||
if ($this->option('json_summary')) {
|
||||
$json_summary = [
|
||||
'error' => true,
|
||||
'error_message' => $error->getMessage(),
|
||||
'summary' => [],
|
||||
];
|
||||
$this->info(json_encode($json_summary));
|
||||
}
|
||||
$this->error($error->getMessage());
|
||||
LOG::error($error);
|
||||
}
|
||||
}
|
||||
|
|
183
app/Console/Commands/MoveUploadsToNewDisk.php
Normal file
183
app/Console/Commands/MoveUploadsToNewDisk.php
Normal file
|
@ -0,0 +1,183 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class MoveUploadsToNewDisk extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:move-uploads {delete_local?}';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'This will move your uploaded files to whatever your current disk is.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
if (config('filesystems.default')=='local') {
|
||||
$this->error('Your current disk is set to local so we cannot proceed.');
|
||||
$this->warn("Please configure your .env settings for S3 or Rackspace, \nand change your FILESYSTEM_DISK value to 's3' or 'rackspace'.");
|
||||
return false;
|
||||
}
|
||||
$delete_local = $this->argument('delete_local');
|
||||
|
||||
$public_uploads['accessories'] = glob('storage/app/public/accessories'."/*.*");
|
||||
$public_uploads['assets'] = glob('storage/app/public/assets'."/*.*");
|
||||
$public_uploads['avatars'] = glob('storage/app/public/avatars'."/*.*");
|
||||
$public_uploads['barcodes'] = glob('storage/app/public/barcodes'."/*.*");
|
||||
$public_uploads['categories'] = glob('storage/app/public/categories'."/*.*");
|
||||
$public_uploads['companies'] = glob('storage/app/public/companies'."/*.*");
|
||||
$public_uploads['components'] = glob('storage/app/public/components'."/*.*");
|
||||
$public_uploads['consumables'] = glob('storage/app/public/consumables'."/*.*");
|
||||
$public_uploads['departments'] = glob('storage/app/public/departments'."/*.*");
|
||||
$public_uploads['locations'] = glob('storage/app/public/locations'."/*.*");
|
||||
$public_uploads['manufacturers'] = glob('storage/app/public/manufacturers'."/*.*");
|
||||
$public_uploads['suppliers'] = glob('storage/app/public/suppliers'."/*.*");
|
||||
$public_uploads['assetmodels'] = glob('storage/app/public/models'."/*.*");
|
||||
|
||||
|
||||
// iterate files
|
||||
foreach($public_uploads as $public_type => $public_upload)
|
||||
{
|
||||
$type_count = 0;
|
||||
$this->info("\nThere are ".count($public_upload).' PUBLIC '.$public_type.' files.');
|
||||
|
||||
for ($i = 0; $i < count($public_upload); $i++) {
|
||||
$type_count++;
|
||||
$filename = basename($public_upload[$i]);
|
||||
|
||||
try {
|
||||
Storage::disk('public')->put($public_type.'/'.$filename, file_get_contents($public_upload[$i]));
|
||||
$new_url = Storage::disk('public')->url($public_type.'/'.$filename, $filename);
|
||||
$this->info($type_count.'. PUBLIC: '.$filename.' was copied to '.$new_url);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
$this->error($e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$logos = glob('public/uploads'."/logo*.*");
|
||||
$this->info("\nThere are ".count($logos).' files that might be logos.');
|
||||
$type_count=0;
|
||||
|
||||
for ($l = 0; $l < count($logos); $l++) {
|
||||
$type_count++;
|
||||
$filename = basename($logos[$l]);
|
||||
$new_url = Storage::disk('public')->url($logos[$l], file_get_contents($public_upload[$i]));
|
||||
$this->info($type_count.'. LOGO: '.$filename.' was copied to '.$new_url);
|
||||
}
|
||||
|
||||
$private_uploads['assets'] = glob('storage/private_uploads/assets'."/*.*");
|
||||
$private_uploads['signatures'] = glob('storage/private_uploads/signatures'."/*.*");
|
||||
$private_uploads['audits'] = glob('storage/private_uploads/audits'."/*.*");
|
||||
$private_uploads['assetmodels'] = glob('storage/private_uploads/assetmodels'."/*.*");
|
||||
$private_uploads['imports'] = glob('storage/private_uploads/imports'."/*.*");
|
||||
$private_uploads['licenses'] = glob('storage/private_uploads/licenses'."/*.*");
|
||||
$private_uploads['users'] = glob('storage/private_uploads/users'."/*.*");
|
||||
|
||||
|
||||
foreach($private_uploads as $private_type => $private_upload)
|
||||
{
|
||||
$this->info("\nThere are ".count($private_upload).' PRIVATE '.$private_type.' files.');
|
||||
// $this->info(print_r($private_upload, true));
|
||||
|
||||
$type_count = 0;
|
||||
for ($x = 0; $x < count($private_upload); $x++) {
|
||||
$type_count++;
|
||||
$filename = basename($private_upload[$x]);
|
||||
|
||||
try {
|
||||
Storage::disk('private_uploads')->put($private_type.'/'.$filename, file_get_contents($public_upload[$i]));
|
||||
$new_url = Storage::url($private_type.'/'.$filename, $filename);
|
||||
$this->info($type_count.'. PRIVATE: '.$filename.' was copied to '.$new_url);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
$this->error($e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
if ($delete_local=='true') {
|
||||
$public_delete_count = 0;
|
||||
$private_delete_count = 0;
|
||||
|
||||
$this->info("\n\n");
|
||||
$this->error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
|
||||
$this->warn("\nTHIS WILL DELETE ALL OF YOUR LOCAL UPLOADED FILES. \n\nThis cannot be undone, so you should take a backup of your system before you proceed.\n");
|
||||
$this->error('!!!!!!!!!!!!!!!!!!!!!!!!!!!!! WARNING!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!');
|
||||
|
||||
if ($this->confirm("Do you wish to continue?")) {
|
||||
|
||||
foreach($public_uploads as $public_type => $public_upload) {
|
||||
|
||||
for ($i = 0; $i < count($public_upload); $i++) {
|
||||
$filename = $public_upload[$i];
|
||||
try {
|
||||
unlink($filename);
|
||||
$public_delete_count++;
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
$this->error($e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
foreach($private_uploads as $private_type => $private_upload)
|
||||
{
|
||||
|
||||
for ($i = 0; $i < count($private_upload); $i++) {
|
||||
$filename = $private_upload[$i];
|
||||
try {
|
||||
unlink($filename);
|
||||
$private_delete_count++;
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
$this->error($e);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
$this->info($public_delete_count." PUBLIC local files and ".$private_delete_count." PRIVATE local files were delete from your filesystem.");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -65,7 +65,7 @@ class ObjectImportCommand extends Command
|
|||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fire()
|
||||
public function handle()
|
||||
{
|
||||
$filename = $this->argument('filename');
|
||||
$class = title_case($this->option('item-type'));
|
||||
|
|
61
app/Console/Commands/SendCurrentInventoryToUsers.php
Normal file
61
app/Console/Commands/SendCurrentInventoryToUsers.php
Normal file
|
@ -0,0 +1,61 @@
|
|||
<?php
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use App\Models\Asset;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CurrentInventory;
|
||||
|
||||
class SendCurrentInventoryToUsers extends Command
|
||||
{
|
||||
/**
|
||||
* The name and signature of the console command.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $signature = 'snipeit:user-inventory';
|
||||
|
||||
/**
|
||||
* The console command description.
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'This will send users a report of all of the items currently checked out to them.';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
/**
|
||||
* Execute the console command.
|
||||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$users = User::whereNull('deleted_at')->whereNotNull('email')->with('assets', 'accessories', 'licenses')->get();
|
||||
|
||||
$count = 0;
|
||||
foreach ($users as $user) {
|
||||
|
||||
if (($user->assets->count() > 0) || ($user->accessories->count() > 0) || ($user->licenses->count() > 0))
|
||||
{
|
||||
$count++;
|
||||
$user->notify((new CurrentInventory($user)));
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this->info($count.' users notified.');
|
||||
|
||||
|
||||
}
|
||||
}
|
|
@ -2,17 +2,15 @@
|
|||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
|
||||
use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Console\Command;
|
||||
use App\Notifications\ExpectedCheckinNotification;
|
||||
use App\Notifications\ExpectedCheckinAdminNotification;
|
||||
use App\Notifications\ExpectedCheckinNotification;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class SendExpectedCheckinAlerts extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
|
@ -29,8 +27,6 @@ class SendExpectedCheckinAlerts extends Command
|
|||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -42,17 +38,17 @@ class SendExpectedCheckinAlerts extends Command
|
|||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fire()
|
||||
public function handle()
|
||||
{
|
||||
$settings = Setting::getSettings();
|
||||
$settings = Setting::getSettings();
|
||||
$whenNotify = Carbon::now()->addDays(7);
|
||||
$assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
|
||||
$assets = Asset::with('assignedTo')->whereNotNull('assigned_to')->whereNotNull('expected_checkin')->where('expected_checkin', '<=', $whenNotify)->get();
|
||||
|
||||
$this->info($whenNotify.' is deadline');
|
||||
$this->info($assets->count().' assets');
|
||||
$this->info($whenNotify . ' is deadline');
|
||||
$this->info($assets->count() . ' assets');
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
if ($asset->assigned && $asset->checkedOutToUser()) {
|
||||
if ($asset->assigned && $asset->checkedOutToUser()) {
|
||||
$asset->assigned->notify((new ExpectedCheckinNotification($asset)));
|
||||
}
|
||||
}
|
||||
|
@ -60,14 +56,9 @@ class SendExpectedCheckinAlerts extends Command
|
|||
if (($assets) && ($assets->count() > 0) && ($settings->alert_email != '')) {
|
||||
// Send a rollup to the admin, if settings dictate
|
||||
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
|
||||
return new \App\Models\Recipients\AlertRecipient($item);
|
||||
return new AlertRecipient($item);
|
||||
});
|
||||
\Notification::send($recipients, new ExpectedCheckinAdminNotification($assets));
|
||||
Notification::send($recipients, new ExpectedCheckinAdminNotification($assets));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -4,16 +4,14 @@ namespace App\Console\Commands;
|
|||
|
||||
use App\Models\Asset;
|
||||
use App\Models\License;
|
||||
use App\Models\Recipients\AlertRecipient;
|
||||
use App\Models\Setting;
|
||||
use DB;
|
||||
use App\Notifications\ExpiringLicenseNotification;
|
||||
use App\Notifications\ExpiringAssetsNotification;
|
||||
|
||||
use App\Notifications\ExpiringLicenseNotification;
|
||||
use Illuminate\Console\Command;
|
||||
|
||||
class SendExpirationAlerts extends Command
|
||||
{
|
||||
|
||||
/**
|
||||
* The console command name.
|
||||
*
|
||||
|
@ -30,8 +28,6 @@ class SendExpirationAlerts extends Command
|
|||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -43,50 +39,37 @@ class SendExpirationAlerts extends Command
|
|||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fire()
|
||||
public function handle()
|
||||
{
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
$settings = Setting::getSettings();
|
||||
$threshold = $settings->alert_interval;
|
||||
|
||||
|
||||
if (($settings->alert_email != '') && ($settings->alerts_enabled == 1)) {
|
||||
|
||||
// Send a rollup to the admin, if settings dictate
|
||||
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
|
||||
return new \App\Models\Recipients\AlertRecipient($item);
|
||||
return new AlertRecipient($item);
|
||||
});
|
||||
|
||||
// Expiring Assets
|
||||
$assets = Asset::getExpiringWarrantee(Setting::getSettings()->alert_interval);
|
||||
$assets = Asset::getExpiringWarrantee($threshold);
|
||||
if ($assets->count() > 0) {
|
||||
$this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(),
|
||||
['count' => $assets->count(), 'threshold' => $threshold]));
|
||||
\Notification::send($recipients, new ExpiringAssetsNotification($assets, $threshold));
|
||||
$this->info(trans_choice('mail.assets_warrantee_alert', $assets->count(), ['count' => $assets->count(), 'threshold' => $threshold]));
|
||||
Notification::send($recipients, new ExpiringAssetsNotification($assets, $threshold));
|
||||
}
|
||||
|
||||
// Expiring licenses
|
||||
$licenses = License::getExpiringLicenses($threshold);
|
||||
|
||||
|
||||
if ($licenses->count() > 0) {
|
||||
$this->info(trans_choice('mail.license_expiring_alert', $licenses->count(), ['count' => $licenses->count(), 'threshold' => $threshold]));
|
||||
\Notification::send($recipients, new ExpiringLicenseNotification($licenses, $threshold));
|
||||
Notification::send($recipients, new ExpiringLicenseNotification($licenses, $threshold));
|
||||
}
|
||||
|
||||
|
||||
} else {
|
||||
|
||||
if ($settings->alert_email=='') {
|
||||
if ($settings->alert_email == '') {
|
||||
$this->error('Could not send email. No alert email configured in settings');
|
||||
} elseif ($settings->alerts_enabled!=1) {
|
||||
} elseif (1 != $settings->alerts_enabled) {
|
||||
$this->info('Alerts are disabled in the settings. No mail will be sent');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,13 +2,12 @@
|
|||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Models\Setting;
|
||||
use DB;
|
||||
use Mail;
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Recipients\AlertRecipient;
|
||||
use App\Models\Setting;
|
||||
use App\Notifications\InventoryAlert;
|
||||
|
||||
use Illuminate\Console\Command;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
|
||||
class SendInventoryAlerts extends Command
|
||||
{
|
||||
|
@ -28,8 +27,6 @@ class SendInventoryAlerts extends Command
|
|||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
{
|
||||
|
@ -45,29 +42,24 @@ class SendInventoryAlerts extends Command
|
|||
{
|
||||
$settings = Setting::getSettings();
|
||||
|
||||
if (($settings->alert_email!='') && ($settings->alerts_enabled==1)) {
|
||||
|
||||
if (($settings->alert_email != '') && ($settings->alerts_enabled == 1)) {
|
||||
$items = Helper::checkLowInventory();
|
||||
|
||||
// Send a rollup to the admin, if settings dictate
|
||||
|
||||
if (($items) && (count($items) > 0)) {
|
||||
$this->info(trans_choice('mail.low_inventory_alert', count($items)));
|
||||
// Send a rollup to the admin, if settings dictate
|
||||
$recipients = collect(explode(',', $settings->alert_email))->map(function ($item, $key) {
|
||||
return new \App\Models\Recipients\AlertRecipient($item);
|
||||
return new AlertRecipient($item);
|
||||
});
|
||||
\Notification::send($recipients, new InventoryAlert($items, $settings->alert_threshold));
|
||||
}
|
||||
|
||||
Notification::send($recipients, new InventoryAlert($items, $settings->alert_threshold));
|
||||
}
|
||||
} else {
|
||||
if (Setting::getSettings()->alert_email=='') {
|
||||
if ($settings->alert_email == '') {
|
||||
$this->error('Could not send email. No alert email configured in settings');
|
||||
} elseif (Setting::getSettings()->alerts_enabled!=1) {
|
||||
} elseif (1 != $settings->alerts_enabled) {
|
||||
$this->info('Alerts are disabled in the settings. No mail will be sent');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ class SyncAssetCounters extends Command
|
|||
public function handle()
|
||||
{
|
||||
$start = microtime(true);
|
||||
$assets = Asset::withCount('checkins', 'checkouts', 'userRequests')
|
||||
$assets = Asset::withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')
|
||||
->withTrashed()->get();
|
||||
|
||||
if ($assets) {
|
||||
|
|
|
@ -36,7 +36,7 @@ class SystemBackup extends Command
|
|||
*
|
||||
* @return mixed
|
||||
*/
|
||||
public function fire()
|
||||
public function handle()
|
||||
{
|
||||
//
|
||||
$this->call('backup:run');
|
||||
|
|
|
@ -31,17 +31,17 @@ class Kernel extends ConsoleKernel
|
|||
Commands\RegenerateAssetTags::class,
|
||||
Commands\SyncAssetCounters::class,
|
||||
Commands\RestoreDeletedUsers::class,
|
||||
Commands\SendCurrentInventoryToUsers::class,
|
||||
Commands\MoveUploadsToNewDisk::class,
|
||||
];
|
||||
|
||||
/**
|
||||
* Define the application's command schedule.
|
||||
*
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
* @return void
|
||||
* @param \Illuminate\Console\Scheduling\Schedule $schedule
|
||||
*/
|
||||
protected function schedule(Schedule $schedule)
|
||||
{
|
||||
|
||||
$schedule->command('snipeit:inventory-alerts')->daily();
|
||||
$schedule->command('snipeit:expiring-alerts')->daily();
|
||||
$schedule->command('snipeit:expected-checkin')->daily();
|
||||
|
@ -49,6 +49,10 @@ class Kernel extends ConsoleKernel
|
|||
$schedule->command('backup:clean')->daily();
|
||||
}
|
||||
|
||||
/**
|
||||
* This method is required by Laravel to handle any console routes
|
||||
* that are defined in routes/console.php.
|
||||
*/
|
||||
protected function commands()
|
||||
{
|
||||
require base_path('routes/console.php');
|
||||
|
|
27
app/Events/CheckoutAccepted.php
Normal file
27
app/Events/CheckoutAccepted.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\Contracts\Acceptable;
|
||||
use App\Models\User;
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CheckoutAccepted
|
||||
{
|
||||
use Dispatchable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(CheckoutAcceptance $acceptance)
|
||||
{
|
||||
$this->acceptance = $acceptance;
|
||||
}
|
||||
}
|
27
app/Events/CheckoutDeclined.php
Normal file
27
app/Events/CheckoutDeclined.php
Normal file
|
@ -0,0 +1,27 @@
|
|||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\Contracts\Acceptable;
|
||||
use App\Models\User;
|
||||
use Illuminate\Broadcasting\Channel;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CheckoutDeclined
|
||||
{
|
||||
use Dispatchable, SerializesModels;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(CheckoutAcceptance $acceptance)
|
||||
{
|
||||
$this->acceptance = $acceptance;
|
||||
}
|
||||
}
|
30
app/Events/CheckoutableCheckedIn.php
Normal file
30
app/Events/CheckoutableCheckedIn.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CheckoutableCheckedIn
|
||||
{
|
||||
use Dispatchable, SerializesModels;
|
||||
|
||||
public $checkoutable;
|
||||
public $checkedOutTo;
|
||||
public $checkedInBy;
|
||||
public $note;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($checkoutable, $checkedOutTo, User $checkedInBy, $note)
|
||||
{
|
||||
$this->checkoutable = $checkoutable;
|
||||
$this->checkedOutTo = $checkedOutTo;
|
||||
$this->checkedInBy = $checkedInBy;
|
||||
$this->note = $note;
|
||||
}
|
||||
}
|
30
app/Events/CheckoutableCheckedOut.php
Normal file
30
app/Events/CheckoutableCheckedOut.php
Normal file
|
@ -0,0 +1,30 @@
|
|||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\User;
|
||||
use Illuminate\Foundation\Events\Dispatchable;
|
||||
use Illuminate\Queue\SerializesModels;
|
||||
|
||||
class CheckoutableCheckedOut
|
||||
{
|
||||
use Dispatchable, SerializesModels;
|
||||
|
||||
public $checkoutable;
|
||||
public $checkedOutTo;
|
||||
public $checkedOutBy;
|
||||
public $note;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($checkoutable, $checkedOutTo, User $checkedOutBy, $note)
|
||||
{
|
||||
$this->checkoutable = $checkoutable;
|
||||
$this->checkedOutTo = $checkedOutTo;
|
||||
$this->checkedOutBy = $checkedOutBy;
|
||||
$this->note = $note;
|
||||
}
|
||||
}
|
20
app/Events/SettingSaved.php
Normal file
20
app/Events/SettingSaved.php
Normal file
|
@ -0,0 +1,20 @@
|
|||
<?php
|
||||
|
||||
namespace App\Events;
|
||||
|
||||
use App\Models\Setting;
|
||||
|
||||
class SettingSaved
|
||||
{
|
||||
public $settings;
|
||||
|
||||
/**
|
||||
* Create a new event instance.
|
||||
*
|
||||
* @param \App\Models\Setting $settings
|
||||
*/
|
||||
public function __construct(Setting $settings)
|
||||
{
|
||||
$this->settings = $settings;
|
||||
}
|
||||
}
|
|
@ -225,8 +225,9 @@ class Helper
|
|||
*/
|
||||
public static function predefined_formats()
|
||||
{
|
||||
$keys = array_keys(CustomField::$PredefinedFormats);
|
||||
$keys = array_keys(CustomField::PREDEFINED_FORMATS);
|
||||
$stuff = array_combine($keys, $keys);
|
||||
|
||||
return $stuff;
|
||||
}
|
||||
|
||||
|
@ -281,9 +282,9 @@ class Helper
|
|||
*/
|
||||
public static function checkLowInventory()
|
||||
{
|
||||
$consumables = Consumable::withCount('consumableAssignments')->whereNotNull('min_amt')->get();
|
||||
$accessories = Accessory::withCount('users')->whereNotNull('min_amt')->get();
|
||||
$components = Component::withCount('assets')->whereNotNull('min_amt')->get();
|
||||
$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::withCount('assets as assets_count')->whereNotNull('min_amt')->get();
|
||||
|
||||
$avail_consumables = 0;
|
||||
$items_array = array();
|
||||
|
@ -669,7 +670,37 @@ class Helper
|
|||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate a random encrypted password.
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function generateEncyrptedPassword(): string
|
||||
{
|
||||
return bcrypt(Helper::generateUnencryptedPassword());
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a random unencrypted password.
|
||||
*
|
||||
* @author Steffen Buehl <sb@sbuehl.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
public static function generateUnencryptedPassword(): string
|
||||
{
|
||||
$chars = '0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ';
|
||||
|
||||
|
||||
$password = '';
|
||||
for ( $i = 0; $i < 20; $i++ ) {
|
||||
$password .= substr( $chars, random_int( 0, strlen( $chars ) - 1 ), 1 );
|
||||
}
|
||||
return $password;
|
||||
}
|
||||
}
|
||||
|
|
208
app/Http/Controllers/Accessories/AccessoriesController.php
Executable file
208
app/Http/Controllers/Accessories/AccessoriesController.php
Executable file
|
@ -0,0 +1,208 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers\Accessories;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Company;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Redirect;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/** This controller handles all actions related to Accessories for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class AccessoriesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the accessories listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see AccessoriesController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('index', Accessory::class);
|
||||
return view('accessories/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view with a form to create a new Accessory.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', Accessory::class);
|
||||
$category_type = 'accessory';
|
||||
return view('accessories/edit')->with('category_type', $category_type)
|
||||
->with('item', new Accessory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate and save new Accessory from form post
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param ImageUploadRequest $request
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize(Accessory::class);
|
||||
// create a new model instance
|
||||
$accessory = new Accessory();
|
||||
|
||||
// Update the accessory data
|
||||
$accessory->name = request('name');
|
||||
$accessory->category_id = request('category_id');
|
||||
$accessory->location_id = request('location_id');
|
||||
$accessory->min_amt = request('min_amt');
|
||||
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
|
||||
$accessory->order_number = request('order_number');
|
||||
$accessory->manufacturer_id = request('manufacturer_id');
|
||||
$accessory->model_number = request('model_number');
|
||||
$accessory->purchase_date = request('purchase_date');
|
||||
$accessory->purchase_cost = Helper::ParseFloat(request('purchase_cost'));
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->user_id = Auth::user()->id;
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
|
||||
$accessory = $request->handleImages($accessory);
|
||||
|
||||
// Was the accessory created?
|
||||
if ($accessory->save()) {
|
||||
// Redirect to the new accessory page
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.create.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($accessory->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return view for the Accessory update form, prepopulated with existing data
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryId
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($accessoryId = null)
|
||||
{
|
||||
|
||||
if ($item = Accessory::find($accessoryId)) {
|
||||
$this->authorize($item);
|
||||
return view('accessories/edit', compact('item'))->with('category_type', 'accessory');
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save edited Accessory from form post
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param ImageUploadRequest $request
|
||||
* @param int $accessoryId
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $accessoryId = null)
|
||||
{
|
||||
if (is_null($accessory = Accessory::find($accessoryId))) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize($accessory);
|
||||
|
||||
// Update the accessory data
|
||||
$accessory->name = request('name');
|
||||
$accessory->location_id = request('location_id');
|
||||
$accessory->min_amt = request('min_amt');
|
||||
$accessory->category_id = request('category_id');
|
||||
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
|
||||
$accessory->manufacturer_id = request('manufacturer_id');
|
||||
$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->qty = request('qty');
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
|
||||
$accessory = $request->handleImages($accessory);
|
||||
|
||||
// Was the accessory updated?
|
||||
if ($accessory->save()) {
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($accessory->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given accessory.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryId
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($accessoryId)
|
||||
{
|
||||
if (is_null($accessory = Accessory::find($accessoryId))) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
|
||||
}
|
||||
|
||||
$this->authorize($accessory);
|
||||
|
||||
|
||||
if ($accessory->hasUsers() > 0) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.assoc_users', array('count'=> $accessory->hasUsers())));
|
||||
}
|
||||
|
||||
if ($accessory->image) {
|
||||
try {
|
||||
Storage::disk('public')->delete('accessories'.'/'.$accessory->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$accessory->delete();
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.delete.success'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax table which contains
|
||||
* the content for the accessory detail view, which is generated in getDataView.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryID
|
||||
* @see AccessoriesController::getDataView() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($accessoryID = null)
|
||||
{
|
||||
$accessory = Accessory::find($accessoryID);
|
||||
$this->authorize('view', $accessory);
|
||||
if (isset($accessory->id)) {
|
||||
return view('accessories/view', compact('accessory'));
|
||||
}
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist', ['id' => $accessoryID]));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,74 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Accessories;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
|
||||
class AccessoryCheckinController extends Controller
|
||||
{
|
||||
/**
|
||||
* Check the accessory back into inventory
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param Request $request
|
||||
* @param integer $accessoryUserId
|
||||
* @param string $backto
|
||||
* @return View
|
||||
* @internal param int $accessoryId
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($accessoryUserId = null, $backto = null)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
|
||||
// Redirect to the accessory management page with error
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
|
||||
}
|
||||
|
||||
$accessory = Accessory::find($accessory_user->accessory_id);
|
||||
$this->authorize('checkin', $accessory);
|
||||
return view('accessories/checkin', compact('accessory'))->with('backto', $backto);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check in the item so that it can be checked out again to someone else
|
||||
*
|
||||
* @uses Accessory::checkin_email() to determine if an email can and should be sent
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param null $accessoryUserId
|
||||
* @param string $backto
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @internal param int $accessoryId
|
||||
*/
|
||||
public function store(Request $request, $accessoryUserId = null, $backto = null)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
|
||||
// Redirect to the accessory management page with error
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$accessory = Accessory::find($accessory_user->accessory_id);
|
||||
|
||||
$this->authorize('checkin', $accessory);
|
||||
|
||||
// Was the accessory updated?
|
||||
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
|
||||
$return_to = e($accessory_user->assigned_to);
|
||||
|
||||
event(new CheckoutableCheckedIn($accessory, User::find($return_to), Auth::user(), $request->input('note')));
|
||||
|
||||
return redirect()->route("accessories.show", $accessory->id)->with('success', trans('admin/accessories/message.checkin.success'));
|
||||
}
|
||||
// Redirect to the accessory management page with error
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkin.error'));
|
||||
}
|
||||
}
|
|
@ -0,0 +1,88 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Accessories;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
|
||||
class AccessoryCheckoutController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Return the form to checkout an Accessory to a user.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryId
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($accessoryId)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
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'));
|
||||
}
|
||||
|
||||
if ($accessory->category) {
|
||||
|
||||
$this->authorize('checkout', $accessory);
|
||||
|
||||
// Get the dropdown of users and then pass it to the checkout view
|
||||
return view('accessories/checkout', compact('accessory'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', 'The category type for this accessory is not valid. Edit the accessory and select a valid accessory category.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the Accessory checkout information.
|
||||
*
|
||||
* If Slack is enabled and/or asset acceptance is enabled, it will also
|
||||
* trigger a Slack message and send an email.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param Request $request
|
||||
* @param int $accessoryId
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(Request $request, $accessoryId)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
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(Input::get('assigned_to'))) {
|
||||
return redirect()->route('checkout/accessory', $accessory->id)->with('error', trans('admin/accessories/message.checkout.user_does_not_exist'));
|
||||
}
|
||||
|
||||
// Update the accessory data
|
||||
$accessory->assigned_to = e(Input::get('assigned_to'));
|
||||
|
||||
$accessory->users()->attach($accessory->id, [
|
||||
'accessory_id' => $accessory->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'user_id' => Auth::id(),
|
||||
'assigned_to' => $request->get('assigned_to')
|
||||
]);
|
||||
|
||||
DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first();
|
||||
|
||||
event(new CheckoutableCheckedOut($accessory, $user, Auth::user(), $request->input('note')));
|
||||
|
||||
// Redirect to the new accessory page
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.checkout.success'));
|
||||
}
|
||||
}
|
|
@ -1,400 +0,0 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Company;
|
||||
use App\Models\User;
|
||||
use Auth;
|
||||
use Carbon\Carbon;
|
||||
use Config;
|
||||
use DB;
|
||||
use Gate;
|
||||
use Input;
|
||||
use Lang;
|
||||
use Redirect;
|
||||
use Illuminate\Http\Request;
|
||||
use Slack;
|
||||
use Str;
|
||||
use View;
|
||||
use Image;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
|
||||
/** This controller handles all actions related to Accessories for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class AccessoriesController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the accessories listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see AccessoriesController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('index', Accessory::class);
|
||||
return view('accessories/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view with a form to create a new Accessory.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @return View
|
||||
*/
|
||||
public function create(Request $request)
|
||||
{
|
||||
$this->authorize('create', Accessory::class);
|
||||
$category_type = 'accessory';
|
||||
return view('accessories/edit')->with('category_type', $category_type)
|
||||
->with('item', new Accessory);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate and save new Accessory from form post
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @return Redirect
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize(Accessory::class);
|
||||
// create a new model instance
|
||||
$accessory = new Accessory();
|
||||
|
||||
// Update the accessory data
|
||||
$accessory->name = request('name');
|
||||
$accessory->category_id = request('category_id');
|
||||
$accessory->location_id = request('location_id');
|
||||
$accessory->min_amt = request('min_amt');
|
||||
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
|
||||
$accessory->order_number = request('order_number');
|
||||
$accessory->manufacturer_id = request('manufacturer_id');
|
||||
$accessory->model_number = request('model_number');
|
||||
$accessory->purchase_date = request('purchase_date');
|
||||
$accessory->purchase_cost = Helper::ParseFloat(request('purchase_cost'));
|
||||
$accessory->qty = request('qty');
|
||||
$accessory->user_id = Auth::user()->id;
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
|
||||
if (!config('app.lock_passwords')) {
|
||||
$image = $request->file('image');
|
||||
$ext = $image->getClientOriginalExtension();
|
||||
$file_name = "accessory-".str_random(18).'.'.$ext;
|
||||
$path = public_path('/uploads/accessories');
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(null, 250, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path.'/'.$file_name);
|
||||
} else {
|
||||
$image->move($path, $file_name);
|
||||
}
|
||||
$accessory->image = $file_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Was the accessory created?
|
||||
if ($accessory->save()) {
|
||||
// Redirect to the new accessory page
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.create.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($accessory->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return view for the Accessory update form, prepopulated with existing data
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryId
|
||||
* @return View
|
||||
*/
|
||||
public function edit(Request $request, $accessoryId = null)
|
||||
{
|
||||
|
||||
if ($item = Accessory::find($accessoryId)) {
|
||||
$this->authorize($item);
|
||||
$category_type = 'accessory';
|
||||
return view('accessories/edit', compact('item'))->with('category_type', $category_type);
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Save edited Accessory from form post
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryId
|
||||
* @return Redirect
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $accessoryId = null)
|
||||
{
|
||||
if (is_null($accessory = Accessory::find($accessoryId))) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize($accessory);
|
||||
|
||||
// Update the accessory data
|
||||
$accessory->name = request('name');
|
||||
$accessory->location_id = request('location_id');
|
||||
$accessory->min_amt = request('min_amt');
|
||||
$accessory->category_id = request('category_id');
|
||||
$accessory->company_id = Company::getIdForCurrentUser(request('company_id'));
|
||||
$accessory->manufacturer_id = request('manufacturer_id');
|
||||
$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->qty = request('qty');
|
||||
$accessory->supplier_id = request('supplier_id');
|
||||
|
||||
if ($request->hasFile('image')) {
|
||||
|
||||
if (!config('app.lock_passwords')) {
|
||||
$image = $request->file('image');
|
||||
$ext = $image->getClientOriginalExtension();
|
||||
$file_name = "accessory-".str_random(18).'.'.$ext;
|
||||
$path = public_path('/uploads/accessories');
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(null, 250, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path.'/'.$file_name);
|
||||
} else {
|
||||
$image->move($path, $file_name);
|
||||
}
|
||||
if (($accessory->image) && (file_exists($path.'/'.$accessory->image))) {
|
||||
unlink($path.'/'.$accessory->image);
|
||||
}
|
||||
|
||||
$accessory->image = $file_name;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Was the accessory updated?
|
||||
if ($accessory->save()) {
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.update.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($accessory->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the given accessory.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryId
|
||||
* @return Redirect
|
||||
*/
|
||||
public function destroy(Request $request, $accessoryId)
|
||||
{
|
||||
if (is_null($accessory = Accessory::find($accessoryId))) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
|
||||
}
|
||||
|
||||
$this->authorize($accessory);
|
||||
|
||||
|
||||
if ($accessory->hasUsers() > 0) {
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.assoc_users', array('count'=> $accessory->hasUsers())));
|
||||
}
|
||||
$accessory->delete();
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.delete.success'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax table which contains
|
||||
* the content for the accessory detail view, which is generated in getDataView.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryID
|
||||
* @see AccessoriesController::getDataView() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
public function show(Request $request, $accessoryID = null)
|
||||
{
|
||||
$accessory = Accessory::find($accessoryID);
|
||||
$this->authorize('view', $accessory);
|
||||
if (isset($accessory->id)) {
|
||||
return view('accessories/view', compact('accessory'));
|
||||
}
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist', compact('id')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return the form to checkout an Accessory to a user.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryId
|
||||
* @return View
|
||||
*/
|
||||
public function getCheckout(Request $request, $accessoryId)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
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'));
|
||||
}
|
||||
|
||||
if ($accessory->category) {
|
||||
|
||||
$this->authorize('checkout', $accessory);
|
||||
|
||||
// Get the dropdown of users and then pass it to the checkout view
|
||||
return view('accessories/checkout', compact('accessory'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', 'The category type for this accessory is not valid. Edit the accessory and select a valid accessory category.');
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the Accessory checkout information.
|
||||
*
|
||||
* If Slack is enabled and/or asset acceptance is enabled, it will also
|
||||
* trigger a Slack message and send an email.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $accessoryId
|
||||
* @return Redirect
|
||||
*/
|
||||
public function postCheckout(Request $request, $accessoryId)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
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(Input::get('assigned_to'))) {
|
||||
return redirect()->route('checkout/accessory', $accessory->id)->with('error', trans('admin/accessories/message.checkout.user_does_not_exist'));
|
||||
}
|
||||
|
||||
// Update the accessory data
|
||||
$accessory->assigned_to = e(Input::get('assigned_to'));
|
||||
|
||||
$accessory->users()->attach($accessory->id, [
|
||||
'accessory_id' => $accessory->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'user_id' => Auth::id(),
|
||||
'assigned_to' => $request->get('assigned_to')
|
||||
]);
|
||||
|
||||
$logaction = $accessory->logCheckout(e(Input::get('note')), $user);
|
||||
|
||||
DB::table('accessories_users')->where('assigned_to', '=', $accessory->assigned_to)->where('accessory_id', '=', $accessory->id)->first();
|
||||
|
||||
$data['log_id'] = $logaction->id;
|
||||
$data['eula'] = $accessory->getEula();
|
||||
$data['first_name'] = $user->first_name;
|
||||
$data['item_name'] = $accessory->name;
|
||||
$data['checkout_date'] = $logaction->created_at;
|
||||
$data['item_tag'] = '';
|
||||
$data['expected_checkin'] = '';
|
||||
$data['note'] = $logaction->note;
|
||||
$data['require_acceptance'] = $accessory->requireAcceptance();
|
||||
|
||||
// Redirect to the new accessory page
|
||||
return redirect()->route('accessories.index')->with('success', trans('admin/accessories/message.checkout.success'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check the accessory back into inventory
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param Request $request
|
||||
* @param integer $accessoryUserId
|
||||
* @param string $backto
|
||||
* @return View
|
||||
* @internal param int $accessoryId
|
||||
*/
|
||||
public function getCheckin(Request $request, $accessoryUserId = null, $backto = null)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
|
||||
// Redirect to the accessory management page with error
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.not_found'));
|
||||
}
|
||||
|
||||
$accessory = Accessory::find($accessory_user->accessory_id);
|
||||
$this->authorize('checkin', $accessory);
|
||||
return view('accessories/checkin', compact('accessory'))->with('backto', $backto);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Check in the item so that it can be checked out again to someone else
|
||||
*
|
||||
* @uses Accessory::checkin_email() to determine if an email can and should be sent
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param Request $request
|
||||
* @param integer $accessoryUserId
|
||||
* @param string $backto
|
||||
* @return Redirect
|
||||
* @internal param int $accessoryId
|
||||
*/
|
||||
public function postCheckin(Request $request, $accessoryUserId = null, $backto = null)
|
||||
{
|
||||
// Check if the accessory exists
|
||||
if (is_null($accessory_user = DB::table('accessories_users')->find($accessoryUserId))) {
|
||||
// Redirect to the accessory management page with error
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$accessory = Accessory::find($accessory_user->accessory_id);
|
||||
|
||||
$this->authorize('checkin', $accessory);
|
||||
|
||||
$return_to = e($accessory_user->assigned_to);
|
||||
$logaction = $accessory->logCheckin(User::find($return_to), e(Input::get('note')));
|
||||
|
||||
// Was the accessory updated?
|
||||
if (DB::table('accessories_users')->where('id', '=', $accessory_user->id)->delete()) {
|
||||
if (!is_null($accessory_user->assigned_to)) {
|
||||
$user = User::find($accessory_user->assigned_to);
|
||||
}
|
||||
|
||||
$data['log_id'] = $logaction->id;
|
||||
$data['first_name'] = e($user->first_name);
|
||||
$data['last_name'] = e($user->last_name);
|
||||
$data['item_name'] = e($accessory->name);
|
||||
$data['checkin_date'] = e($logaction->created_at);
|
||||
$data['item_tag'] = '';
|
||||
$data['note'] = e($logaction->note);
|
||||
|
||||
if ($backto=='user') {
|
||||
return redirect()->route("users.show", $return_to)->with('success', trans('admin/accessories/message.checkin.success'));
|
||||
}
|
||||
return redirect()->route("accessories.show", $accessory->id)->with('success', trans('admin/accessories/message.checkin.success'));
|
||||
}
|
||||
// Redirect to the accessory management page with error
|
||||
return redirect()->route('accessories.index')->with('error', trans('admin/accessories/message.checkin.error'));
|
||||
}
|
||||
|
||||
|
||||
}
|
130
app/Http/Controllers/Account/AcceptanceController.php
Normal file
130
app/Http/Controllers/Account/AcceptanceController.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers\Account;
|
||||
|
||||
use App\Events\CheckoutAccepted;
|
||||
use App\Events\CheckoutDeclined;
|
||||
use App\Events\ItemAccepted;
|
||||
use App\Events\ItemDeclined;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\Company;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\Contracts\Acceptable;
|
||||
use App\Models\License;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Str;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class AcceptanceController extends Controller {
|
||||
|
||||
/**
|
||||
* Show a listing of pending checkout acceptances for the current user
|
||||
*
|
||||
* @return View
|
||||
*/
|
||||
public function index() {
|
||||
$acceptances = CheckoutAcceptance::forUser(Auth::user())->pending()->get();
|
||||
|
||||
return view('account/accept.index', compact('acceptances'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Shows a form to either accept or decline the checkout acceptance
|
||||
*
|
||||
* @param int $id
|
||||
* @return mixed
|
||||
*/
|
||||
public function create($id) {
|
||||
|
||||
$acceptance = CheckoutAcceptance::find($id);
|
||||
|
||||
if (is_null($acceptance)) {
|
||||
return redirect()->route('account.accept')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
|
||||
if (! $acceptance->isPending()) {
|
||||
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted'));
|
||||
}
|
||||
|
||||
if (! $acceptance->isCheckedOutTo(Auth::user())) {
|
||||
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
|
||||
}
|
||||
|
||||
if (!Company::isCurrentUserHasAccess($acceptance->checkoutable)) {
|
||||
return redirect()->route('account.accept')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
return view('account/accept.create', compact('acceptance'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Stores the accept/decline of the checkout acceptance
|
||||
*
|
||||
* @param Request $request
|
||||
* @param int $id
|
||||
* @return Redirect
|
||||
*/
|
||||
public function store(Request $request, $id) {
|
||||
|
||||
$acceptance = CheckoutAcceptance::find($id);
|
||||
|
||||
if (is_null($acceptance)) {
|
||||
return redirect()->route('account.accept')->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
}
|
||||
|
||||
if (! $acceptance->isPending()) {
|
||||
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.asset_already_accepted'));
|
||||
}
|
||||
|
||||
if (! $acceptance->isCheckedOutTo(Auth::user())) {
|
||||
return redirect()->route('account.accept')->with('error', trans('admin/users/message.error.incorrect_user_accepted'));
|
||||
}
|
||||
|
||||
if (!Company::isCurrentUserHasAccess($acceptance->checkoutable)) {
|
||||
return redirect()->route('account.accept')->with('error', trans('general.insufficient_permissions'));
|
||||
}
|
||||
|
||||
if (!$request->filled('asset_acceptance')) {
|
||||
return redirect()->back()->with('error', trans('admin/users/message.error.accept_or_decline'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the signature and save it
|
||||
*/
|
||||
|
||||
if (!Storage::exists('private_uploads/signatures')) Storage::makeDirectory('private_uploads/signatures', 775);
|
||||
|
||||
|
||||
|
||||
if ($request->filled('signature_output')) {
|
||||
$sig_filename = "siglog-" .Str::uuid() . '-'.date('Y-m-d-his').".png";
|
||||
$data_uri = e($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);
|
||||
}
|
||||
|
||||
|
||||
if ($request->input('asset_acceptance') == 'accepted') {
|
||||
|
||||
$acceptance->accept($sig_filename);
|
||||
|
||||
event(new CheckoutAccepted($acceptance));
|
||||
|
||||
$return_msg = trans('admin/users/message.accepted');
|
||||
|
||||
} else {
|
||||
|
||||
$acceptance->decline($sig_filename);
|
||||
|
||||
event(new CheckoutDeclined($acceptance));
|
||||
|
||||
$return_msg = trans('admin/users/message.declined');
|
||||
|
||||
}
|
||||
|
||||
return redirect()->to('account/accept')->with('success', $return_msg);
|
||||
}
|
||||
}
|
|
@ -26,23 +26,23 @@ class AccessoriesController extends Controller
|
|||
|
||||
$accessories = Accessory::with('category', 'company', 'manufacturer', 'users', 'location');
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$accessories = $accessories->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
if ($request->has('company_id')) {
|
||||
if ($request->filled('company_id')) {
|
||||
$accessories->where('company_id','=',$request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($request->has('category_id')) {
|
||||
if ($request->filled('category_id')) {
|
||||
$accessories->where('category_id','=',$request->input('category_id'));
|
||||
}
|
||||
|
||||
if ($request->has('manufacturer_id')) {
|
||||
if ($request->filled('manufacturer_id')) {
|
||||
$accessories->where('manufacturer_id','=',$request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->has('supplier_id')) {
|
||||
if ($request->filled('supplier_id')) {
|
||||
$accessories->where('supplier_id','=',$request->input('supplier_id'));
|
||||
}
|
||||
|
||||
|
@ -132,18 +132,28 @@ class AccessoriesController extends Controller
|
|||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function checkedout($id)
|
||||
public function checkedout($id, Request $request)
|
||||
{
|
||||
$this->authorize('view', Accessory::class);
|
||||
|
||||
$accessory = Accessory::findOrFail($id);
|
||||
$accessory = Accessory::with('lastCheckout')->findOrFail($id);
|
||||
if (!Company::isCurrentUserHasAccess($accessory)) {
|
||||
return ['total' => 0, 'rows' => []];
|
||||
}
|
||||
$accessory_users = $accessory->users;
|
||||
$total = $accessory_users->count();
|
||||
|
||||
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory_users, $total);
|
||||
$accessory->lastCheckoutArray = $accessory->lastCheckout->toArray();
|
||||
$accessory_users = $accessory->users;
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$accessory_users = $accessory->users()
|
||||
->where('first_name', 'like', '%'.$request->input('search').'%')
|
||||
->orWhere('last_name', 'like', '%'.$request->input('search').'%')
|
||||
->get();
|
||||
}
|
||||
|
||||
$total = $accessory_users->count();
|
||||
|
||||
return (new AccessoriesTransformer)->transformCheckedoutAccessory($accessory, $accessory_users, $total);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -34,13 +34,13 @@ class AssetMaintenancesController extends Controller
|
|||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$maintenances = AssetMaintenance::with('asset', 'supplier', 'asset.company', 'admin');
|
||||
$maintenances = AssetMaintenance::with('asset', 'asset.model','asset.location', 'supplier', 'asset.company', 'admin');
|
||||
|
||||
if (Input::has('search')) {
|
||||
$maintenances = $maintenances->TextSearch(e($request->input('search')));
|
||||
if ($request->filled('search')) {
|
||||
$maintenances = $maintenances->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
if ($request->has('asset_id')) {
|
||||
if ($request->filled('asset_id')) {
|
||||
$maintenances->where('asset_id', '=', $request->input('asset_id'));
|
||||
}
|
||||
|
||||
|
|
|
@ -9,6 +9,7 @@ use Illuminate\Http\Request;
|
|||
use App\Http\Transformers\AssetModelsTransformer;
|
||||
use App\Http\Transformers\AssetsTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
|
||||
/**
|
||||
|
@ -48,15 +49,15 @@ class AssetModelsController extends Controller
|
|||
'models.updated_at',
|
||||
])
|
||||
->with('category','depreciation', 'manufacturer','fieldset')
|
||||
->withCount('assets');
|
||||
->withCount('assets as assets_count');
|
||||
|
||||
|
||||
|
||||
if ($request->has('status')) {
|
||||
if ($request->filled('status')) {
|
||||
$assetmodels->onlyTrashed();
|
||||
}
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$assetmodels->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -114,7 +115,7 @@ class AssetModelsController extends Controller
|
|||
public function show($id)
|
||||
{
|
||||
$this->authorize('view', AssetModel::class);
|
||||
$assetmodel = AssetModel::withCount('assets')->findOrFail($id);
|
||||
$assetmodel = AssetModel::withCount('assets as assets_count')->findOrFail($id);
|
||||
return (new AssetModelsTransformer)->transformAssetModel($assetmodel);
|
||||
}
|
||||
|
||||
|
@ -177,7 +178,7 @@ class AssetModelsController extends Controller
|
|||
|
||||
if ($assetmodel->image) {
|
||||
try {
|
||||
unlink(public_path().'/uploads/models/'.$assetmodel->image);
|
||||
Storage::disk('public')->delete('assetmodels/'.$assetmodel->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
|
@ -210,7 +211,7 @@ class AssetModelsController extends Controller
|
|||
|
||||
$settings = \App\Models\Setting::getSettings();
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$assetmodels = $assetmodels->SearchByManufacturerOrCat($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -234,7 +235,7 @@ class AssetModelsController extends Controller
|
|||
$assetmodel->use_text .= ' (#'.e($assetmodel->model_number).')';
|
||||
}
|
||||
|
||||
$assetmodel->use_image = ($settings->modellistCheckedValue('image') && ($assetmodel->image)) ? url('/').'/uploads/models/'.$assetmodel->image : null;
|
||||
$assetmodel->use_image = ($settings->modellistCheckedValue('image') && ($assetmodel->image)) ? Storage::disk('public')->url('assetmodels/'.e($assetmodel->image)) : null;
|
||||
}
|
||||
|
||||
return (new SelectlistTransformer)->transformSelectlist($assetmodels);
|
||||
|
|
|
@ -3,13 +3,14 @@ namespace App\Http\Controllers\Api;
|
|||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetRequest;
|
||||
use App\Http\Requests\AssetCheckoutRequest;
|
||||
use App\Http\Transformers\AssetsTransformer;
|
||||
use App\Http\Transformers\LicensesTransformer;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Company;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\License;
|
||||
use App\Models\Location;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
|
@ -84,7 +85,7 @@ class AssetsController extends Controller
|
|||
|
||||
$filter = array();
|
||||
|
||||
if ($request->has('filter')) {
|
||||
if ($request->filled('filter')) {
|
||||
$filter = json_decode($request->input('filter'), true);
|
||||
}
|
||||
|
||||
|
@ -101,7 +102,7 @@ class AssetsController extends Controller
|
|||
// 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.
|
||||
if ($request->has('status_id')) {
|
||||
if ($request->filled('status_id')) {
|
||||
$assets->where('assets.status_id', '=', $request->input('status_id'));
|
||||
}
|
||||
|
||||
|
@ -109,40 +110,40 @@ class AssetsController extends Controller
|
|||
$assets->where('assets.requestable', '=', '1');
|
||||
}
|
||||
|
||||
if ($request->has('model_id')) {
|
||||
if ($request->filled('model_id')) {
|
||||
$assets->InModelList([$request->input('model_id')]);
|
||||
}
|
||||
|
||||
if ($request->has('category_id')) {
|
||||
if ($request->filled('category_id')) {
|
||||
$assets->InCategory($request->input('category_id'));
|
||||
}
|
||||
|
||||
if ($request->has('location_id')) {
|
||||
if ($request->filled('location_id')) {
|
||||
$assets->where('assets.location_id', '=', $request->input('location_id'));
|
||||
}
|
||||
|
||||
if ($request->has('supplier_id')) {
|
||||
if ($request->filled('supplier_id')) {
|
||||
$assets->where('assets.supplier_id', '=', $request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if (($request->has('assigned_to')) && ($request->has('assigned_type'))) {
|
||||
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->has('company_id')) {
|
||||
if ($request->filled('company_id')) {
|
||||
$assets->where('assets.company_id', '=', $request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($request->has('manufacturer_id')) {
|
||||
if ($request->filled('manufacturer_id')) {
|
||||
$assets->ByManufacturer($request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->has('depreciation_id')) {
|
||||
if ($request->filled('depreciation_id')) {
|
||||
$assets->ByDepreciationId($request->input('depreciation_id'));
|
||||
}
|
||||
|
||||
$request->has('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
|
||||
$request->filled('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
|
||||
|
||||
$offset = request('offset', 0);
|
||||
$limit = $request->input('limit', 50);
|
||||
|
@ -155,7 +156,7 @@ class AssetsController extends Controller
|
|||
// I am sad. :(
|
||||
switch ($request->input('status')) {
|
||||
case 'Deleted':
|
||||
$assets->withTrashed()->Deleted();
|
||||
$assets->onlyTrashed();
|
||||
break;
|
||||
case 'Pending':
|
||||
$assets->join('status_labels AS status_alias',function ($join) {
|
||||
|
@ -201,7 +202,7 @@ class AssetsController extends Controller
|
|||
break;
|
||||
default:
|
||||
|
||||
if ((!$request->has('status_id')) && ($settings->show_archived_in_list!='1')) {
|
||||
if ((!$request->filled('status_id')) && ($settings->show_archived_in_list!='1')) {
|
||||
// terrible workaround for complex-query Laravel bug in fulltext
|
||||
$assets->join('status_labels AS status_alias',function ($join) {
|
||||
$join->on('status_alias.id', "=", "assets.status_id")
|
||||
|
@ -220,7 +221,7 @@ class AssetsController extends Controller
|
|||
|
||||
if ((!is_null($filter)) && (count($filter)) > 0) {
|
||||
$assets->ByFilter($filter);
|
||||
} elseif ($request->has('search')) {
|
||||
} elseif ($request->filled('search')) {
|
||||
$assets->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -270,9 +271,9 @@ class AssetsController extends Controller
|
|||
break;
|
||||
}
|
||||
|
||||
|
||||
$total = $assets->count();
|
||||
$assets = $assets->skip($offset)->take($limit)->get();
|
||||
// dd($assets);
|
||||
return (new AssetsTransformer)->transformAssets($assets, $total);
|
||||
}
|
||||
|
||||
|
@ -308,8 +309,7 @@ class AssetsController extends Controller
|
|||
$this->authorize('index', Asset::class);
|
||||
if ($assets = Asset::with('assetstatus')->with('assignedTo')
|
||||
->withTrashed()->where('serial',$serial)->get()) {
|
||||
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
||||
|
||||
|
@ -326,14 +326,22 @@ class AssetsController extends Controller
|
|||
*/
|
||||
public function show($id)
|
||||
{
|
||||
if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()->withCount('checkins', 'checkouts', 'userRequests')->findOrFail($id)) {
|
||||
if ($asset = Asset::with('assetstatus')->with('assignedTo')->withTrashed()
|
||||
->withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')->findOrFail($id)) {
|
||||
$this->authorize('view', $asset);
|
||||
return (new AssetsTransformer)->transformAsset($asset);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function licenses($id)
|
||||
{
|
||||
$this->authorize('view', Asset::class);
|
||||
$this->authorize('view', License::class);
|
||||
$asset = Asset::where('id', $id)->withTrashed()->first();
|
||||
$licenses = $asset->licenses()->get();
|
||||
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets a paginated collection for the select2 menus
|
||||
|
@ -354,13 +362,13 @@ class AssetsController extends Controller
|
|||
'assets.assigned_to',
|
||||
'assets.assigned_type',
|
||||
'assets.status_id'
|
||||
])->with('model', 'assetstatus', 'assignedTo')->NotArchived(),'company_id', 'assets');
|
||||
])->with('model', 'assetstatus', 'assignedTo')->NotArchived());
|
||||
|
||||
if ($request->has('assetStatusType') && $request->input('assetStatusType') === 'RTD') {
|
||||
if ($request->filled('assetStatusType') && $request->input('assetStatusType') === 'RTD') {
|
||||
$assets = $assets->RTD();
|
||||
}
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$assets = $assets->AssignedSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -379,7 +387,7 @@ class AssetsController extends Controller
|
|||
$asset->use_text .= ' → '.$asset->assigned->getFullNameAttribute();
|
||||
}
|
||||
|
||||
|
||||
|
||||
if ($asset->assetstatus->getStatuslabelType()=='pending') {
|
||||
$asset->use_text .= '('.$asset->assetstatus->getStatuslabelType().')';
|
||||
}
|
||||
|
@ -400,7 +408,7 @@ class AssetsController extends Controller
|
|||
* @since [v4.0]
|
||||
* @return JsonResponse
|
||||
*/
|
||||
public function store(AssetRequest $request)
|
||||
public function store(Request $request)
|
||||
{
|
||||
|
||||
$this->authorize('create', Asset::class);
|
||||
|
@ -431,7 +439,7 @@ class AssetsController extends Controller
|
|||
// 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->fieldset) {
|
||||
if (($model) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug(), null));
|
||||
}
|
||||
|
@ -468,21 +476,22 @@ class AssetsController extends Controller
|
|||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
$asset->fill($request->all());
|
||||
|
||||
|
||||
if ($asset = Asset::find($id)) {
|
||||
|
||||
$asset->fill($request->all());
|
||||
|
||||
($request->has('model_id')) ?
|
||||
($request->filled('model_id')) ?
|
||||
$asset->model()->associate(AssetModel::find($request->get('model_id'))) : null;
|
||||
($request->has('company_id')) ?
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : null;
|
||||
($request->has('rtd_location_id')) ?
|
||||
$asset->location_id = $request->get('rtd_location_id') : null;
|
||||
($request->filled('rtd_location_id')) ?
|
||||
$asset->location_id = $request->get('rtd_location_id') : '';
|
||||
($request->filled('company_id')) ?
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->get('company_id')) : '';
|
||||
|
||||
|
||||
// Update custom fields
|
||||
if (($model = AssetModel::find($asset->model_id)) && (isset($model->fieldset))) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($request->has($field->convertUnicodeDbSlug())) {
|
||||
if ($request->filled($field->convertUnicodeDbSlug())) {
|
||||
$asset->{$field->convertUnicodeDbSlug()} = e($request->input($field->convertUnicodeDbSlug()));
|
||||
}
|
||||
}
|
||||
|
@ -491,11 +500,11 @@ class AssetsController extends Controller
|
|||
|
||||
if ($asset->save()) {
|
||||
|
||||
if (($request->has('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
|
||||
$location = $target->location_id;
|
||||
} elseif (($request->has('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
|
||||
$location = $target->location_id;
|
||||
} elseif (($request->has('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
|
||||
if (($request->filled('assigned_user')) && ($target = User::find($request->get('assigned_user')))) {
|
||||
$location = $target->location_id;
|
||||
} elseif (($request->filled('assigned_asset')) && ($target = Asset::find($request->get('assigned_asset')))) {
|
||||
$location = $target->location_id;
|
||||
} elseif (($request->filled('assigned_location')) && ($target = Location::find($request->get('assigned_location')))) {
|
||||
$location = $target->id;
|
||||
}
|
||||
|
||||
|
@ -650,7 +659,7 @@ class AssetsController extends Controller
|
|||
$asset->name = Input::get('name');
|
||||
$asset->location_id = $asset->rtd_location_id;
|
||||
|
||||
if ($request->has('location_id')) {
|
||||
if ($request->filled('location_id')) {
|
||||
$asset->location_id = $request->input('location_id');
|
||||
}
|
||||
|
||||
|
@ -690,13 +699,27 @@ class AssetsController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()->all()));
|
||||
}
|
||||
|
||||
$settings = Setting::getSettings();
|
||||
$dt = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
|
||||
|
||||
$asset = Asset::where('asset_tag','=', $request->input('asset_tag'))->first();
|
||||
|
||||
|
||||
if ($asset) {
|
||||
// We don't want to log this as a normal update, so let's bypass that
|
||||
$asset->unsetEventDispatcher();
|
||||
$asset->next_audit_date = $request->input('next_audit_date');
|
||||
$asset->next_audit_date = $dt;
|
||||
|
||||
if ($request->filled('next_audit_date')) {
|
||||
$asset->next_audit_date = $request->input('next_audit_date');
|
||||
}
|
||||
|
||||
// Check to see if they checked the box to update the physical location,
|
||||
// not just note it in the audit notes
|
||||
if ($request->input('update_location')=='1') {
|
||||
$asset->location_id = $request->input('location_id');
|
||||
}
|
||||
|
||||
$asset->last_audit_date = date('Y-m-d h:i:s');
|
||||
|
||||
if ($asset->save()) {
|
||||
|
@ -704,7 +727,7 @@ class AssetsController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('success', [
|
||||
'asset_tag'=> e($asset->asset_tag),
|
||||
'note'=> e($request->input('note')),
|
||||
'next_audit_date' => Helper::getFormattedDateObject($log->calcNextAuditDate())
|
||||
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date)
|
||||
], trans('admin/hardware/message.audit.success')));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use App\Helpers\Helper;
|
|||
use App\Models\Category;
|
||||
use App\Http\Transformers\CategoriesTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class CategoriesController extends Controller
|
||||
{
|
||||
|
@ -24,9 +25,9 @@ class CategoriesController extends Controller
|
|||
$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('assets', 'accessories', 'consumables', 'components','licenses');
|
||||
->withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count','licenses as licenses_count');
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$categories = $categories->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -114,15 +115,15 @@ class CategoriesController extends Controller
|
|||
public function destroy($id)
|
||||
{
|
||||
$this->authorize('delete', Category::class);
|
||||
$category = Category::findOrFail($id);
|
||||
$category = Category::withCount('models as models_count', 'accessories as accessories_count','consumables as consumables_count','components as components_count')->findOrFail($id);
|
||||
|
||||
if ($category->has_models() > 0) {
|
||||
if ($category->models_count > 0) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'model'])));
|
||||
} elseif ($category->accessories()->count() > 0) {
|
||||
} elseif ($category->accessories_count > 0) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory'])));
|
||||
} elseif ($category->consumables()->count() > 0) {
|
||||
} elseif ($category->consumables_count > 0) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable'])));
|
||||
} elseif ($category->components()->count() > 0) {
|
||||
} elseif ($category->components_count > 0) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.assoc_items', ['asset_type'=>'component'])));
|
||||
}
|
||||
$category->delete();
|
||||
|
@ -148,7 +149,7 @@ class CategoriesController extends Controller
|
|||
'image',
|
||||
]);
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$categories = $categories->where('name', 'LIKE', '%'.$request->get('search').'%');
|
||||
}
|
||||
|
||||
|
@ -158,7 +159,7 @@ class CategoriesController extends Controller
|
|||
// 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 ($categories as $category) {
|
||||
$category->use_image = ($category->image) ? url('/').'/uploads/categories/'.$category->image : null;
|
||||
$category->use_image = ($category->image) ? Storage::disk('public')->url('categories/'.$category->image, $category->image) : null;
|
||||
}
|
||||
|
||||
return (new SelectlistTransformer)->transformSelectlist($categories);
|
||||
|
|
|
@ -35,9 +35,9 @@ class CompaniesController extends Controller
|
|||
'components_count',
|
||||
];
|
||||
|
||||
$companies = Company::withCount('assets','licenses','accessories','consumables','components','users');
|
||||
$companies = Company::withCount('assets as assets_count','licenses as licenses_count','accessories as accessories_count','consumables as consumables_count','components as components_count','users as users_count');
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$companies->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -168,7 +168,7 @@ class CompaniesController extends Controller
|
|||
'companies.image',
|
||||
]);
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$companies = $companies->where('companies.name', 'LIKE', '%'.$request->get('search').'%');
|
||||
}
|
||||
|
||||
|
@ -178,7 +178,7 @@ class CompaniesController extends Controller
|
|||
// 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 ($companies as $company) {
|
||||
$company->use_image = ($company->image) ? url('/').'/uploads/companies/'.$company->image : null;
|
||||
$company->use_image = ($company->image) ? Storage::disk('public')->url('companies/'.$company->image, $company->image) : null;
|
||||
}
|
||||
|
||||
return (new SelectlistTransformer)->transformSelectlist($companies);
|
||||
|
|
|
@ -27,19 +27,19 @@ class ComponentsController extends Controller
|
|||
$components = Company::scopeCompanyables(Component::select('components.*')
|
||||
->with('company', 'location', 'category'));
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$components = $components->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
if ($request->has('company_id')) {
|
||||
if ($request->filled('company_id')) {
|
||||
$components->where('company_id','=',$request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($request->has('category_id')) {
|
||||
if ($request->filled('category_id')) {
|
||||
$components->where('category_id','=',$request->input('category_id'));
|
||||
}
|
||||
|
||||
if ($request->has('location_id')) {
|
||||
if ($request->filled('location_id')) {
|
||||
$components->where('location_id','=',$request->input('location_id'));
|
||||
}
|
||||
|
||||
|
|
|
@ -27,15 +27,15 @@ class ConsumablesController extends Controller
|
|||
->with('company', 'location', 'category', 'users', 'manufacturer')
|
||||
);
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$consumables = $consumables->TextSearch(e($request->input('search')));
|
||||
}
|
||||
|
||||
if ($request->has('company_id')) {
|
||||
if ($request->filled('company_id')) {
|
||||
$consumables->where('company_id','=',$request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($request->has('manufacturer_id')) {
|
||||
if ($request->filled('manufacturer_id')) {
|
||||
$consumables->where('manufacturer_id','=',$request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
|
@ -152,7 +152,7 @@ class ConsumablesController extends Controller
|
|||
* Returns a JSON response containing details on the users associated with this consumable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::getView() method that returns the form.
|
||||
* @see \App\Http\Controllers\Consumables\ConsumablesController::getView() method that returns the form.
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @return array
|
||||
|
|
|
@ -16,7 +16,6 @@ use App\Http\Controllers\Controller;
|
|||
use App\Helpers\Helper;
|
||||
use App\Http\Transformers\CustomFieldsTransformer;
|
||||
use App\Http\Transformers\CustomFieldsetsTransformer;
|
||||
use App\Http\Requests\AssetRequest;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Custom Asset Fieldsets for
|
||||
|
@ -43,7 +42,7 @@ class CustomFieldsetsController extends Controller
|
|||
public function index()
|
||||
{
|
||||
$this->authorize('index', CustomFieldset::class);
|
||||
$fieldsets = CustomFieldset::withCount(['fields', 'models'])->get();
|
||||
$fieldsets = CustomFieldset::withCount('fields as fields_count', 'models as models_count')->get();
|
||||
return (new CustomFieldsetsTransformer)->transformCustomFieldsets($fieldsets, $fieldsets->count());
|
||||
|
||||
}
|
||||
|
|
|
@ -9,6 +9,7 @@ use App\Http\Transformers\DepartmentsTransformer;
|
|||
use App\Helpers\Helper;
|
||||
use Auth;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class DepartmentsController extends Controller
|
||||
{
|
||||
|
@ -33,9 +34,9 @@ class DepartmentsController extends Controller
|
|||
'departments.created_at',
|
||||
'departments.updated_at',
|
||||
'departments.image'
|
||||
])->with('users')->with('location')->with('manager')->with('company')->withCount('users');
|
||||
])->with('users')->with('location')->with('manager')->with('company')->withCount('users as users_count');
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$departments = $departments->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -76,7 +77,7 @@ class DepartmentsController extends Controller
|
|||
$department = new Department;
|
||||
$department->fill($request->all());
|
||||
$department->user_id = Auth::user()->id;
|
||||
$department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null);
|
||||
$department->manager_id = ($request->filled('manager_id' ) ? $request->input('manager_id') : null);
|
||||
|
||||
if ($department->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $department, trans('admin/departments/message.create.success')));
|
||||
|
@ -100,14 +101,36 @@ class DepartmentsController extends Controller
|
|||
return (new DepartmentsTransformer)->transformDepartment($department);
|
||||
}
|
||||
|
||||
/**
|
||||
* Update the specified resource in storage.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v5.0]
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function update(Request $request, $id)
|
||||
{
|
||||
$this->authorize('update', Department::class);
|
||||
$department = Department::findOrFail($id);
|
||||
$department->fill($request->all());
|
||||
|
||||
if ($department->save()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $department, trans('admin/departments/message.update.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $department->getErrors()));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Validates and deletes selected location.
|
||||
* Validates and deletes selected department.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $locationId
|
||||
* @since [v1.0]
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy($id)
|
||||
|
@ -142,7 +165,7 @@ class DepartmentsController extends Controller
|
|||
'image',
|
||||
]);
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$departments = $departments->where('name', 'LIKE', '%'.$request->get('search').'%');
|
||||
}
|
||||
|
||||
|
@ -152,7 +175,7 @@ class DepartmentsController extends Controller
|
|||
// 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 ($departments as $department) {
|
||||
$department->use_image = ($department->image) ? url('/').'/uploads/departments/'.$department->image : null;
|
||||
$department->use_image = ($department->image) ? Storage::disk('public')->url('departments/'.$department->image, $department->image) : null;
|
||||
}
|
||||
|
||||
return (new SelectlistTransformer)->transformSelectlist($departments);
|
||||
|
|
|
@ -24,7 +24,7 @@ class DepreciationsController extends Controller
|
|||
|
||||
$depreciations = Depreciation::select('id','name','months','user_id','created_at','updated_at');
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$depreciations = $depreciations->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -110,10 +110,10 @@ class DepreciationsController extends Controller
|
|||
public function destroy($id)
|
||||
{
|
||||
$this->authorize('delete', Depreciation::class);
|
||||
$depreciation = Depreciation::findOrFail($id);
|
||||
$depreciation = Depreciation::withCount('models as models_count')->findOrFail($id);
|
||||
$this->authorize('delete', $depreciation);
|
||||
|
||||
if ($depreciation->has_models() > 0) {
|
||||
if ($depreciation->models_count > 0) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', trans('admin/depreciations/message.assoc_users')));
|
||||
}
|
||||
|
||||
|
|
|
@ -22,9 +22,9 @@ class GroupsController extends Controller
|
|||
$this->authorize('view', Group::class);
|
||||
$allowed_columns = ['id','name','created_at', 'users_count'];
|
||||
|
||||
$groups = Group::select('id','name','permissions','created_at','updated_at')->withCount('users');
|
||||
$groups = Group::select('id','name','permissions','created_at','updated_at')->withCount('users as users_count');
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$groups = $groups->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
|
|
@ -15,6 +15,7 @@ use League\Csv\Reader;
|
|||
use Symfony\Component\HttpFoundation\File\Exception\FileException;
|
||||
use Artisan;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ImportController extends Controller
|
||||
{
|
||||
|
@ -114,7 +115,7 @@ class ImportController extends Controller
|
|||
/**
|
||||
* Processes the specified Import.
|
||||
*
|
||||
* @param \App\Import $import
|
||||
* @param int $import_id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function process(ItemImportRequest $request, $import_id)
|
||||
|
@ -157,19 +158,26 @@ class ImportController extends Controller
|
|||
/**
|
||||
* Remove the specified resource from storage.
|
||||
*
|
||||
* @param \App\Import $import
|
||||
* @param int $import_id
|
||||
* @return \Illuminate\Http\Response
|
||||
*/
|
||||
public function destroy($import_id)
|
||||
{
|
||||
$this->authorize('create', Asset::class);
|
||||
$import = Import::find($import_id);
|
||||
try {
|
||||
unlink(config('app.private_uploads').'/imports/'.$import->file_path);
|
||||
$import->delete();
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.import.file_delete_success')));
|
||||
} catch (\Exception $e) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.import.file_delete_error')), 500);
|
||||
|
||||
if ($import = Import::find($import_id)) {
|
||||
try {
|
||||
// Try to delete the file
|
||||
Storage::delete('imports/'.$import->file_path);
|
||||
$import->delete();
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.import.file_delete_success')));
|
||||
|
||||
} catch (\Exception $e) {
|
||||
// If the file delete didn't work, remove it from the database anyway and return a warning
|
||||
$import->delete();
|
||||
return response()->json(Helper::formatStandardApiResponse('warning', null, trans('admin/hardware/message.import.file_not_deleted_warning')));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
|
|
@ -25,59 +25,59 @@ class LicensesController extends Controller
|
|||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('view', License::class);
|
||||
$licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'freeSeats', 'supplier','category')->withCount('freeSeats'));
|
||||
$licenses = Company::scopeCompanyables(License::with('company', 'manufacturer', 'freeSeats', 'supplier','category')->withCount('freeSeats as free_seats_count'));
|
||||
|
||||
|
||||
if ($request->has('company_id')) {
|
||||
if ($request->filled('company_id')) {
|
||||
$licenses->where('company_id','=',$request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($request->has('name')) {
|
||||
if ($request->filled('name')) {
|
||||
$licenses->where('licenses.name','=',$request->input('name'));
|
||||
}
|
||||
|
||||
if ($request->has('product_key')) {
|
||||
if ($request->filled('product_key')) {
|
||||
$licenses->where('licenses.serial','=',$request->input('product_key'));
|
||||
}
|
||||
|
||||
if ($request->has('order_number')) {
|
||||
if ($request->filled('order_number')) {
|
||||
$licenses->where('order_number','=',$request->input('order_number'));
|
||||
}
|
||||
|
||||
if ($request->has('purchase_order')) {
|
||||
if ($request->filled('purchase_order')) {
|
||||
$licenses->where('purchase_order','=',$request->input('purchase_order'));
|
||||
}
|
||||
|
||||
if ($request->has('license_name')) {
|
||||
if ($request->filled('license_name')) {
|
||||
$licenses->where('license_name','=',$request->input('license_name'));
|
||||
}
|
||||
|
||||
if ($request->has('license_email')) {
|
||||
if ($request->filled('license_email')) {
|
||||
$licenses->where('license_email','=',$request->input('license_email'));
|
||||
}
|
||||
|
||||
if ($request->has('manufacturer_id')) {
|
||||
if ($request->filled('manufacturer_id')) {
|
||||
$licenses->where('manufacturer_id','=',$request->input('manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->has('supplier_id')) {
|
||||
if ($request->filled('supplier_id')) {
|
||||
$licenses->where('supplier_id','=',$request->input('supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->has('category_id')) {
|
||||
if ($request->filled('category_id')) {
|
||||
$licenses->where('category_id','=',$request->input('category_id'));
|
||||
}
|
||||
|
||||
if ($request->has('depreciation_id')) {
|
||||
if ($request->filled('depreciation_id')) {
|
||||
$licenses->where('depreciation_id','=',$request->input('depreciation_id'));
|
||||
}
|
||||
|
||||
if ($request->has('supplier_id')) {
|
||||
if ($request->filled('supplier_id')) {
|
||||
$licenses->where('supplier_id','=',$request->input('supplier_id'));
|
||||
}
|
||||
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$licenses = $licenses->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -150,7 +150,7 @@ class LicensesController extends Controller
|
|||
public function show($id)
|
||||
{
|
||||
$this->authorize('view', License::class);
|
||||
$license = License::findOrFail($id);
|
||||
$license = License::withCount('freeSeats')->findOrFail($id);
|
||||
$license = $license->load('assignedusers', 'licenseSeats.user', 'licenseSeats.asset');
|
||||
return (new LicensesTransformer)->transformLicense($license);
|
||||
}
|
||||
|
@ -229,9 +229,18 @@ class LicensesController extends Controller
|
|||
|
||||
$offset = request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
|
||||
if($seats->count() < $offset){
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$total = $seats->count();
|
||||
|
||||
if($total < $offset){
|
||||
$offset = 0;
|
||||
}
|
||||
|
||||
$seats = $seats->skip($offset)->take($limit)->get();
|
||||
|
||||
if ($seats) {
|
||||
|
|
|
@ -8,6 +8,7 @@ use App\Helpers\Helper;
|
|||
use App\Models\Location;
|
||||
use App\Http\Transformers\LocationsTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class LocationsController extends Controller
|
||||
{
|
||||
|
@ -41,11 +42,11 @@ class LocationsController extends Controller
|
|||
'locations.updated_at',
|
||||
'locations.image',
|
||||
'locations.currency'
|
||||
])->withCount('assignedAssets')
|
||||
->withCount('assets')
|
||||
->withCount('users');
|
||||
])->withCount('assignedAssets as assigned_assets_count')
|
||||
->withCount('assets as assets_count')
|
||||
->withCount('users as users_count');
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$locations = $locations->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -192,7 +193,7 @@ class LocationsController extends Controller
|
|||
'locations.image',
|
||||
]);
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$locations = $locations->where('locations.name', 'LIKE', '%'.$request->get('search').'%');
|
||||
}
|
||||
|
||||
|
@ -203,7 +204,7 @@ class LocationsController extends Controller
|
|||
// they may not have a ->name value but we want to display something anyway
|
||||
foreach ($locations as $location) {
|
||||
$location->use_text = $location->name;
|
||||
$location->use_image = ($location->image) ? url('/').'/uploads/locations/'.$location->image : null;
|
||||
$location->use_image = ($location->image) ? Storage::disk('public')->url('locations/'.$location->image, $location->image): null;
|
||||
}
|
||||
|
||||
return (new SelectlistTransformer)->transformSelectlist($locations);
|
||||
|
|
|
@ -9,6 +9,7 @@ use App\Models\Manufacturer;
|
|||
use App\Http\Transformers\DatatablesTransformer;
|
||||
use App\Http\Transformers\ManufacturersTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class ManufacturersController extends Controller
|
||||
{
|
||||
|
@ -26,13 +27,13 @@ class ManufacturersController extends Controller
|
|||
|
||||
$manufacturers = Manufacturer::select(
|
||||
array('id','name','url','support_url','support_email','support_phone','created_at','updated_at','image', 'deleted_at')
|
||||
)->withCount('assets')->withCount('licenses')->withCount('consumables')->withCount('accessories');
|
||||
)->withCount('assets as assets_count')->withCount('licenses as licenses_count')->withCount('consumables as consumables_count')->withCount('accessories as accessories_count');
|
||||
|
||||
if ($request->input('deleted')=='true') {
|
||||
$manufacturers->onlyTrashed();
|
||||
}
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$manufacturers = $manufacturers->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -83,7 +84,7 @@ class ManufacturersController extends Controller
|
|||
public function show($id)
|
||||
{
|
||||
$this->authorize('view', Manufacturer::class);
|
||||
$manufacturer = Manufacturer::withCount('assets')->withCount('licenses')->withCount('consumables')->withCount('accessories')->findOrFail($id);
|
||||
$manufacturer = Manufacturer::withCount('assets as assets_count', 'licenses as licenses_count', 'consumables as consumables_count', 'accessories as accessories_count', 'models as models_count' )->findOrFail($id);
|
||||
return (new ManufacturersTransformer)->transformManufacturer($manufacturer);
|
||||
}
|
||||
|
||||
|
@ -120,11 +121,21 @@ class ManufacturersController extends Controller
|
|||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
|
||||
$this->authorize('delete', Manufacturer::class);
|
||||
$manufacturer = Manufacturer::findOrFail($id);
|
||||
$manufacturer = Manufacturer::withCount('assets as assets_count', 'licenses as licenses_count', 'consumables as consumables_count', 'accessories as accessories_count', 'models as models_count' )->findOrFail($id);
|
||||
$this->authorize('delete', $manufacturer);
|
||||
$manufacturer->delete();
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/manufacturers/message.delete.success')));
|
||||
|
||||
if (($manufacturer->assets_count == 0) && ($manufacturer->licenses_count==0) && ($manufacturer->consumables_count==0) && ($manufacturer->accessories_count==0) && ($manufacturer->models_count==0) && ($manufacturer->deleted_at=='')) {
|
||||
$manufacturer->delete();
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/manufacturers/message.delete.success')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/manufacturers/message.delete.error')));
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
@ -145,7 +156,7 @@ class ManufacturersController extends Controller
|
|||
'image',
|
||||
]);
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$manufacturers = $manufacturers->where('name', 'LIKE', '%'.$request->get('search').'%');
|
||||
}
|
||||
|
||||
|
@ -156,7 +167,7 @@ class ManufacturersController extends Controller
|
|||
// they may not have a ->name value but we want to display something anyway
|
||||
foreach ($manufacturers as $manufacturer) {
|
||||
$manufacturer->use_text = $manufacturer->name;
|
||||
$manufacturer->use_image = ($manufacturer->image) ? url('/').'/uploads/manufacturers/'.$manufacturer->image : null;
|
||||
$manufacturer->use_image = ($manufacturer->image) ? Storage::disk('public')->url('manufacturers/'.$manufacturer->image, $manufacturer->image) : null;
|
||||
}
|
||||
|
||||
return (new SelectlistTransformer)->transformSelectlist($manufacturers);
|
||||
|
|
|
@ -22,25 +22,25 @@ class ReportsController extends Controller
|
|||
|
||||
$actionlogs = Actionlog::with('item', 'user', 'target','location');
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$actionlogs = $actionlogs->TextSearch(e($request->input('search')));
|
||||
}
|
||||
|
||||
if (($request->has('target_type')) && ($request->has('target_id'))) {
|
||||
if (($request->filled('target_type')) && ($request->filled('target_id'))) {
|
||||
$actionlogs = $actionlogs->where('target_id','=',$request->input('target_id'))
|
||||
->where('target_type','=',"App\\Models\\".ucwords($request->input('target_type')));
|
||||
}
|
||||
|
||||
if (($request->has('item_type')) && ($request->has('item_id'))) {
|
||||
if (($request->filled('item_type')) && ($request->filled('item_id'))) {
|
||||
$actionlogs = $actionlogs->where('item_id','=',$request->input('item_id'))
|
||||
->where('item_type','=',"App\\Models\\".ucwords($request->input('item_type')));
|
||||
}
|
||||
|
||||
if ($request->has('action_type')) {
|
||||
if ($request->filled('action_type')) {
|
||||
$actionlogs = $actionlogs->where('action_type','=',$request->input('action_type'))->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
if ($request->has('uploads')) {
|
||||
if ($request->filled('uploads')) {
|
||||
$actionlogs = $actionlogs->whereNotNull('filename')->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
|
|
|
@ -2,104 +2,85 @@
|
|||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Ldap;
|
||||
use Validator;
|
||||
use App\Services\LdapAd;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use App\Models\Setting;
|
||||
use Mail;
|
||||
use App\Notifications\SlackTest;
|
||||
use Notification;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Notifications\MailTest;
|
||||
use App\Notifications\SlackTest;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\LoginAttemptsTransformer;
|
||||
|
||||
class SettingsController extends Controller
|
||||
{
|
||||
|
||||
|
||||
public function ldaptest()
|
||||
/**
|
||||
* Test the ldap settings
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param App\Models\LdapAd $ldap
|
||||
*
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function ldapAdSettingsTest(LdapAd $ldap): JsonResponse
|
||||
{
|
||||
|
||||
if (Setting::getSettings()->ldap_enabled!='1') {
|
||||
\Log::debug('LDAP is not enabled cannot test.');
|
||||
if(!$ldap->init()) {
|
||||
Log::info('LDAP is not enabled cannot test.');
|
||||
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
|
||||
}
|
||||
|
||||
\Log::debug('Preparing to test LDAP connection');
|
||||
// The connect, bind and resulting users message
|
||||
$message = [];
|
||||
|
||||
Log::info('Preparing to test LDAP user login');
|
||||
// Test user can connect to the LDAP server
|
||||
try {
|
||||
$connection = Ldap::connectToLdap();
|
||||
try {
|
||||
\Log::debug('attempting to bind to LDAP for LDAP test');
|
||||
Ldap::bindAdminToLdap($connection);
|
||||
return response()->json(['message' => 'It worked!'], 200);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Bind failed');
|
||||
return response()->json(['message' => $e->getMessage()], 400);
|
||||
//return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Connection failed');
|
||||
return response()->json(['message' => $e->getMessage()], 600);
|
||||
$ldap->testLdapAdUserConnection();
|
||||
$message['login'] = [
|
||||
'message' => 'Successfully connected to LDAP server.'
|
||||
];
|
||||
} catch (\Exception $ex) {
|
||||
return response()->json([
|
||||
'message' => 'Error logging into LDAP server, error: ' . $ex->getMessage() . ' - Verify your that your username and password are correct'
|
||||
], 400);
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
public function ldaptestlogin(Request $request)
|
||||
{
|
||||
|
||||
if (Setting::getSettings()->ldap_enabled!='1') {
|
||||
\Log::debug('LDAP is not enabled. Cannot test.');
|
||||
return response()->json(['message' => 'LDAP is not enabled, cannot test.'], 400);
|
||||
}
|
||||
|
||||
|
||||
$rules = array(
|
||||
'ldaptest_user' => 'required',
|
||||
'ldaptest_password' => 'required'
|
||||
);
|
||||
|
||||
$validator = Validator::make($request->all(), $rules);
|
||||
if ($validator->fails()) {
|
||||
\Log::debug('LDAP Validation test failed.');
|
||||
$validation_errors = implode(' ',$validator->errors()->all());
|
||||
return response()->json(['message' => $validator->errors()->all()], 400);
|
||||
}
|
||||
|
||||
|
||||
\Log::debug('Preparing to test LDAP login');
|
||||
Log::info('Preparing to test LDAP bind connection');
|
||||
// Test user can bind to the LDAP server
|
||||
try {
|
||||
$connection = Ldap::connectToLdap();
|
||||
try {
|
||||
Ldap::bindAdminToLdap($connection);
|
||||
\Log::debug('Attempting to bind to LDAP for LDAP test');
|
||||
try {
|
||||
$ldap_user = Ldap::findAndBindUserLdap($request->input('ldaptest_user'), $request->input('ldaptest_password'));
|
||||
if ($ldap_user) {
|
||||
\Log::debug('It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.');
|
||||
return response()->json(['message' => 'It worked! '. $request->input('ldaptest_user').' successfully binded to LDAP.'], 200);
|
||||
}
|
||||
return response()->json(['message' => 'Login Failed. '. $request->input('ldaptest_user').' did not successfully bind to LDAP.'], 400);
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('LDAP login failed');
|
||||
return response()->json(['message' => $e->getMessage()], 400);
|
||||
}
|
||||
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Bind failed');
|
||||
return response()->json(['message' => $e->getMessage()], 400);
|
||||
//return response()->json(['message' => $e->getMessage()], 500);
|
||||
}
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Connection failed');
|
||||
return response()->json(['message' => $e->getMessage()], 500);
|
||||
$ldap->testLdapAdBindConnection();
|
||||
$message['bind'] = [
|
||||
'message' => 'Successfully binded to LDAP server.'
|
||||
];
|
||||
} catch (\Exception $ex) {
|
||||
return response()->json([
|
||||
'message' => 'Error binding to LDAP server, error: ' . $ex->getMessage()
|
||||
], 400);
|
||||
}
|
||||
|
||||
Log::info('Preparing to get sample user set from LDAP directory');
|
||||
// Get a sample of 10 users so user can verify the data is correct
|
||||
try {
|
||||
$users = $ldap->testUserImportSync();
|
||||
$message['user_sync'] = [
|
||||
'users' => $users
|
||||
];
|
||||
} catch (\Exception $ex) {
|
||||
$message['user_sync'] = [
|
||||
'message' => 'Error getting users from LDAP directory, error: ' . $ex->getMessage()
|
||||
];
|
||||
return response()->json($message, 400);
|
||||
}
|
||||
|
||||
return response()->json($message, 200);
|
||||
}
|
||||
|
||||
|
||||
public function slacktest()
|
||||
{
|
||||
|
||||
|
@ -143,6 +124,30 @@ class SettingsController extends Controller
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a list of login attempts
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v5.0.0]
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return array
|
||||
*/
|
||||
public function showLoginAttempts(Request $request)
|
||||
{
|
||||
$allowed_columns = ['id', 'username', 'remote_ip', 'user_agent','successful','created_at'];
|
||||
|
||||
$login_attempts = DB::table('login_attempts');
|
||||
$order = $request->input('order') === 'asc' ? 'asc' : 'desc';
|
||||
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'created_at';
|
||||
|
||||
$total = $login_attempts->count();
|
||||
$login_attempts->orderBy($sort, $order);
|
||||
$login_attempt_results = $login_attempts->skip(request('offset', 0))->take(request('limit', 20))->get();
|
||||
|
||||
return (new LoginAttemptsTransformer)->transformLoginAttempts($login_attempt_results, $total);
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -24,9 +24,9 @@ class StatuslabelsController extends Controller
|
|||
$this->authorize('view', Statuslabel::class);
|
||||
$allowed_columns = ['id','name','created_at', 'assets_count','color','default_label'];
|
||||
|
||||
$statuslabels = Statuslabel::withCount('assets');
|
||||
$statuslabels = Statuslabel::withCount('assets as assets_count');
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$statuslabels = $statuslabels->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -55,7 +55,7 @@ class StatuslabelsController extends Controller
|
|||
$this->authorize('create', Statuslabel::class);
|
||||
$request->except('deployable', 'pending','archived');
|
||||
|
||||
if (!$request->has('type')) {
|
||||
if (!$request->filled('type')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, ["type" => ["Status label type is required."]]),500);
|
||||
}
|
||||
|
||||
|
@ -106,7 +106,7 @@ class StatuslabelsController extends Controller
|
|||
|
||||
$request->except('deployable', 'pending','archived');
|
||||
|
||||
if (!$request->has('type')) {
|
||||
if (!$request->filled('type')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Status label type is required.'));
|
||||
}
|
||||
|
||||
|
@ -162,7 +162,7 @@ class StatuslabelsController extends Controller
|
|||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
|
||||
$statuslabels = Statuslabel::with('assets')->groupBy('id')->withCount('assets')->get();
|
||||
$statuslabels = Statuslabel::with('assets')->groupBy('id')->withCount('assets as assets_count')->get();
|
||||
|
||||
$labels=[];
|
||||
$points=[];
|
||||
|
@ -204,11 +204,11 @@ class StatuslabelsController extends Controller
|
|||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
$this->authorize('index', Asset::class);
|
||||
$assets = Asset::where('status_id','=',$id);
|
||||
$assets = Asset::where('status_id','=',$id)->with('assignedTo');
|
||||
|
||||
$allowed_columns = [
|
||||
'id',
|
||||
'name'
|
||||
'name',
|
||||
];
|
||||
|
||||
$offset = request('offset', 0);
|
||||
|
@ -238,8 +238,6 @@ class StatuslabelsController extends Controller
|
|||
*/
|
||||
public function checkIfDeployable($id) {
|
||||
$statuslabel = Statuslabel::findOrFail($id);
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
if ($statuslabel->getStatuslabelType()=='deployable') {
|
||||
return '1';
|
||||
}
|
||||
|
|
|
@ -8,6 +8,7 @@ use App\Helpers\Helper;
|
|||
use App\Models\Supplier;
|
||||
use App\Http\Transformers\SuppliersTransformer;
|
||||
use App\Http\Transformers\SelectlistTransformer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
|
||||
class SuppliersController extends Controller
|
||||
|
@ -22,14 +23,14 @@ 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'];
|
||||
$allowed_columns = ['id','name','address','phone','contact','fax','email','image','assets_count','licenses_count', 'accessories_count','url'];
|
||||
|
||||
$suppliers = Supplier::select(
|
||||
array('id','name','address','address2','city','state','country','fax', 'phone','email','contact','created_at','updated_at','deleted_at','image','notes')
|
||||
)->withCount('assets')->withCount('licenses')->withCount('accessories');
|
||||
array('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');
|
||||
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$suppliers = $suppliers->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -115,7 +116,7 @@ class SuppliersController extends Controller
|
|||
public function destroy($id)
|
||||
{
|
||||
$this->authorize('delete', Supplier::class);
|
||||
$supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances','assets', 'licenses')->findOrFail($id);
|
||||
$supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count','assets as assets_count', 'licenses as licenses_count')->findOrFail($id);
|
||||
$this->authorize('delete', $supplier);
|
||||
|
||||
|
||||
|
@ -153,7 +154,7 @@ class SuppliersController extends Controller
|
|||
'image',
|
||||
]);
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$suppliers = $suppliers->where('suppliers.name', 'LIKE', '%'.$request->get('search').'%');
|
||||
}
|
||||
|
||||
|
@ -164,7 +165,7 @@ class SuppliersController extends Controller
|
|||
// they may not have a ->name value but we want to display something anyway
|
||||
foreach ($suppliers as $supplier) {
|
||||
$supplier->use_text = $supplier->name;
|
||||
$supplier->use_image = ($supplier->image) ? url('/').'/uploads/suppliers/'.$supplier->image : null;
|
||||
$supplier->use_image = ($supplier->image) ? Storage::disk('public')->url('suppliers/'.$supplier->image, $supplier->image) : null;
|
||||
}
|
||||
|
||||
return (new SelectlistTransformer)->transformSelectlist($suppliers);
|
||||
|
|
|
@ -2,6 +2,8 @@
|
|||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Http\Transformers\LicensesTransformer;
|
||||
use App\Models\License;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Transformers\UsersTransformer;
|
||||
|
@ -56,31 +58,31 @@ class UsersController extends Controller
|
|||
'users.zip',
|
||||
|
||||
])->with('manager', 'groups', 'userloc', 'company', 'department','assets','licenses','accessories','consumables')
|
||||
->withCount('assets','licenses','accessories','consumables');
|
||||
->withCount('assets as assets_count','licenses as licneses_count','accessories as accessories_count','consumables as consumables_count');
|
||||
$users = Company::scopeCompanyables($users);
|
||||
|
||||
|
||||
if (($request->has('deleted')) && ($request->input('deleted')=='true')) {
|
||||
$users = $users->GetDeleted();
|
||||
if (($request->filled('deleted')) && ($request->input('deleted')=='true')) {
|
||||
$users = $users->onlyTrashed();
|
||||
}
|
||||
|
||||
if ($request->has('company_id')) {
|
||||
if ($request->filled('company_id')) {
|
||||
$users = $users->where('users.company_id', '=', $request->input('company_id'));
|
||||
}
|
||||
|
||||
if ($request->has('location_id')) {
|
||||
if ($request->filled('location_id')) {
|
||||
$users = $users->where('users.location_id', '=', $request->input('location_id'));
|
||||
}
|
||||
|
||||
if ($request->has('group_id')) {
|
||||
if ($request->filled('group_id')) {
|
||||
$users = $users->ByGroup($request->get('group_id'));
|
||||
}
|
||||
|
||||
if ($request->has('department_id')) {
|
||||
if ($request->filled('department_id')) {
|
||||
$users = $users->where('users.department_id','=',$request->input('department_id'));
|
||||
}
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$users = $users->TextSearch($request->input('search'));
|
||||
}
|
||||
|
||||
|
@ -146,7 +148,7 @@ class UsersController extends Controller
|
|||
|
||||
$users = Company::scopeCompanyables($users);
|
||||
|
||||
if ($request->has('search')) {
|
||||
if ($request->filled('search')) {
|
||||
$users = $users->where('first_name', 'LIKE', '%'.$request->get('search').'%')
|
||||
->orWhere('last_name', 'LIKE', '%'.$request->get('search').'%')
|
||||
->orWhere('username', 'LIKE', '%'.$request->get('search').'%')
|
||||
|
@ -199,6 +201,7 @@ class UsersController extends Controller
|
|||
$tmp_pass = substr(str_shuffle("0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"), 0, 20);
|
||||
$user->password = bcrypt($request->get('password', $tmp_pass));
|
||||
|
||||
|
||||
if ($user->save()) {
|
||||
if ($request->has('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
|
@ -240,13 +243,23 @@ class UsersController extends Controller
|
|||
$this->authorize('update', User::class);
|
||||
|
||||
$user = User::findOrFail($id);
|
||||
|
||||
// This is a janky hack to prevent people from changing admin demo user data on the public demo.
|
||||
// The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder.
|
||||
// Thanks, jerks. You are why we can't have nice things. - snipe
|
||||
|
||||
if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.'));
|
||||
}
|
||||
|
||||
|
||||
$user->fill($request->all());
|
||||
|
||||
if ($user->id == $request->input('manager_id')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
|
||||
}
|
||||
|
||||
if ($request->has('password')) {
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
|
@ -255,6 +268,9 @@ class UsersController extends Controller
|
|||
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
|
||||
|
||||
if ($user->save()) {
|
||||
if ($request->filled('groups')) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
|
||||
}
|
||||
|
||||
|
@ -280,6 +296,15 @@ class UsersController extends Controller
|
|||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete_has_assets')));
|
||||
}
|
||||
|
||||
// Remove the user's avatar if they have one
|
||||
if (Storage::disk('public')->exists('avatars/'.$user->avatar)) {
|
||||
try {
|
||||
Storage::disk('public')->delete('avatars/'.$user->avatar);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
if ($user->delete()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
|
||||
}
|
||||
|
@ -302,6 +327,23 @@ class UsersController extends Controller
|
|||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return JSON containing a list of licenses assigned to a user.
|
||||
*
|
||||
* @author [N. Mathar] [<snipe@snipe.net>]
|
||||
* @since [v5.0]
|
||||
* @param $userId
|
||||
* @return string JSON
|
||||
*/
|
||||
public function licenses($id)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$this->authorize('view', License::class);
|
||||
$user = User::where('id', $id)->withTrashed()->first();
|
||||
$licenses = $user->licenses()->get();
|
||||
return (new LicensesTransformer())->transformLicenses($licenses, $licenses->count());
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the user's two-factor status
|
||||
*
|
||||
|
@ -315,7 +357,7 @@ class UsersController extends Controller
|
|||
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
if ($request->has('id')) {
|
||||
if ($request->filled('id')) {
|
||||
try {
|
||||
$user = User::find($request->get('id'));
|
||||
$user->two_factor_secret = null;
|
||||
|
|
|
@ -165,6 +165,7 @@ class AssetMaintenancesController extends Controller
|
|||
} elseif (!$assetMaintenance->asset) {
|
||||
return redirect()->route('maintenances.index')
|
||||
->with('error', 'The asset associated with this maintenance does not exist.');
|
||||
|
||||
} elseif (!Company::isCurrentUserHasAccess($assetMaintenance->asset)) {
|
||||
return static::getInsufficientPermissionsRedirect();
|
||||
}
|
||||
|
|
|
@ -1,26 +1,15 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\CustomField;
|
||||
use Image;
|
||||
use Input;
|
||||
use Lang;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\View;
|
||||
use App\Models\AssetModel;
|
||||
use Redirect;
|
||||
use Auth;
|
||||
use DB;
|
||||
use Str;
|
||||
use Validator;
|
||||
use View;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use Config;
|
||||
use App\Helpers\Helper;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
||||
/**
|
||||
* This class controls all actions related to asset models for
|
||||
* the Snipe-IT Asset Management application.
|
||||
|
@ -31,13 +20,14 @@ use Symfony\Component\HttpFoundation\JsonResponse;
|
|||
class AssetModelsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the accessories listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the accessories listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('index', AssetModel::class);
|
||||
|
@ -45,29 +35,31 @@ class AssetModelsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a view containing the asset model creation form.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
* Returns a view containing the asset model creation form.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', AssetModel::class);
|
||||
$category_type = 'asset';
|
||||
return view('models/edit')->with('category_type',$category_type)
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('item', new AssetModel);
|
||||
return view('models/edit')->with('category_type', 'asset')
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('item', new AssetModel);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate and process the new Asset Model data.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return Redirect
|
||||
*/
|
||||
* Validate and process the new Asset Model data.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param ImageUploadRequest $request
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
|
||||
|
@ -90,23 +82,7 @@ class AssetModelsController extends Controller
|
|||
$model->fieldset_id = e($request->input('custom_fieldset'));
|
||||
}
|
||||
|
||||
if (Input::file('image')) {
|
||||
|
||||
$image = Input::file('image');
|
||||
$file_name = str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
$path = app('models_upload_path');
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path.'/'.$file_name);
|
||||
} else {
|
||||
$image->move($path, $file_name);
|
||||
}
|
||||
$model->image = $file_name;
|
||||
|
||||
}
|
||||
$model = $request->handleImages($model);
|
||||
|
||||
// Was it created?
|
||||
if ($model->save()) {
|
||||
|
@ -121,13 +97,14 @@ class AssetModelsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a view containing the asset model edit form.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
* @return View
|
||||
*/
|
||||
* Returns a view containing the asset model edit form.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($modelId = null)
|
||||
{
|
||||
$this->authorize('update', AssetModel::class);
|
||||
|
@ -144,14 +121,16 @@ class AssetModelsController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Validates and processes form data from the edit
|
||||
* Asset Model form based on the model ID passed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
* @return Redirect
|
||||
*/
|
||||
* Validates and processes form data from the edit
|
||||
* Asset Model form based on the model ID passed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param ImageUploadRequest $request
|
||||
* @param int $modelId
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $modelId = null)
|
||||
{
|
||||
$this->authorize('update', AssetModel::class);
|
||||
|
@ -182,37 +161,7 @@ class AssetModelsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
$old_image = $model->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$model->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $model->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('models_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('models_upload_path'), $file_name);
|
||||
}
|
||||
$model->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('models_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
}
|
||||
|
||||
$model = $request->handleImages($model);
|
||||
|
||||
if ($model->save()) {
|
||||
return redirect()->route("models.index")->with('success', trans('admin/models/message.update.success'));
|
||||
|
@ -221,14 +170,15 @@ class AssetModelsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Validate and delete the given Asset Model. An Asset Model
|
||||
* cannot be deleted if there are associated assets.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
* @return Redirect
|
||||
*/
|
||||
* Validate and delete the given Asset Model. An Asset Model
|
||||
* cannot be deleted if there are associated assets.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($modelId)
|
||||
{
|
||||
$this->authorize('delete', AssetModel::class);
|
||||
|
@ -244,7 +194,7 @@ class AssetModelsController extends Controller
|
|||
|
||||
if ($model->image) {
|
||||
try {
|
||||
unlink(public_path().'/uploads/models/'.$model->image);
|
||||
Storage::disk('public')->delete('models/'.$model->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
|
@ -259,13 +209,14 @@ class AssetModelsController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Restore a given Asset Model (mark as un-deleted)
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
* @return Redirect
|
||||
*/
|
||||
* Restore a given Asset Model (mark as un-deleted)
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function getRestore($modelId = null)
|
||||
{
|
||||
$this->authorize('create', AssetModel::class);
|
||||
|
@ -273,16 +224,8 @@ class AssetModelsController extends Controller
|
|||
$model = AssetModel::withTrashed()->find($modelId);
|
||||
|
||||
if (isset($model->id)) {
|
||||
|
||||
// Restore the model
|
||||
$model->restore();
|
||||
|
||||
// Prepare the success message
|
||||
$success = trans('admin/models/message.restore.success');
|
||||
|
||||
// Redirect back
|
||||
return redirect()->route('models.index')->with('success', $success);
|
||||
|
||||
return redirect()->route('models.index')->with('success', trans('admin/models/message.restore.success'));
|
||||
}
|
||||
return redirect()->back()->with('error', trans('admin/models/message.not_found'));
|
||||
|
||||
|
@ -290,13 +233,14 @@ class AssetModelsController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Get the model information to present to the model view page
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
* @return View
|
||||
*/
|
||||
* Get the model information to present to the model view page
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($modelId = null)
|
||||
{
|
||||
$this->authorize('view', AssetModel::class);
|
||||
|
@ -305,11 +249,8 @@ class AssetModelsController extends Controller
|
|||
if (isset($model->id)) {
|
||||
return view('models/view', compact('model'));
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/models/message.does_not_exist', compact('id'));
|
||||
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('models.index')->with('error', $error);
|
||||
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -331,12 +272,10 @@ class AssetModelsController extends Controller
|
|||
$model->id = null;
|
||||
|
||||
// Show the page
|
||||
$view = View::make('models/edit');
|
||||
$view->with('depreciation_list', Helper::depreciationList());
|
||||
$view->with('item', $model);
|
||||
$view->with('clone_model', $model_to_clone);
|
||||
return $view;
|
||||
|
||||
return view('models/edit')
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('item', $model)
|
||||
->with('clone_model', $model_to_clone);
|
||||
}
|
||||
|
||||
|
||||
|
@ -350,150 +289,10 @@ class AssetModelsController extends Controller
|
|||
*/
|
||||
public function getCustomFields($modelId)
|
||||
{
|
||||
$model = AssetModel::find($modelId);
|
||||
return view("models.custom_fields_form")->with("model", $model);
|
||||
return view("models.custom_fields_form")->with("model", AssetModel::find($modelId));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view that allows the user to bulk edit model attrbutes
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.7]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function postBulkEdit(Request $request)
|
||||
{
|
||||
|
||||
$models_raw_array = Input::get('ids');
|
||||
|
||||
// Make sure some IDs have been selected
|
||||
if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) {
|
||||
|
||||
|
||||
$models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets')->orderBy('assets_count', 'ASC')->get();
|
||||
|
||||
// If deleting....
|
||||
if ($request->input('bulk_actions')=='delete') {
|
||||
$valid_count = 0;
|
||||
foreach ($models as $model) {
|
||||
if ($model->assets_count == 0) {
|
||||
$valid_count++;
|
||||
}
|
||||
}
|
||||
return view('models/bulk-delete', compact('models'))->with('valid_count', $valid_count);
|
||||
|
||||
// Otherwise display the bulk edit screen
|
||||
} else {
|
||||
|
||||
$nochange = ['NC' => 'No Change'];
|
||||
$fieldset_list = $nochange + Helper::customFieldsetList();
|
||||
$depreciation_list = $nochange + Helper::depreciationList();
|
||||
|
||||
return view('models/bulk-edit', compact('models'))
|
||||
->with('fieldset_list', $fieldset_list)
|
||||
->with('depreciation_list', $depreciation_list);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('models.index')
|
||||
->with('error', 'You must select at least one model to edit.');
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view that allows the user to bulk edit model attrbutes
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.7]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function postBulkEditSave(Request $request)
|
||||
{
|
||||
|
||||
$models_raw_array = Input::get('ids');
|
||||
$update_array = array();
|
||||
|
||||
|
||||
if (($request->has('manufacturer_id') && ($request->input('manufacturer_id')!='NC'))) {
|
||||
$update_array['manufacturer_id'] = $request->input('manufacturer_id');
|
||||
}
|
||||
if (($request->has('category_id') && ($request->input('category_id')!='NC'))) {
|
||||
$update_array['category_id'] = $request->input('category_id');
|
||||
}
|
||||
if ($request->input('fieldset_id')!='NC') {
|
||||
$update_array['fieldset_id'] = $request->input('fieldset_id');
|
||||
}
|
||||
if ($request->input('depreciation_id')!='NC') {
|
||||
$update_array['depreciation_id'] = $request->input('depreciation_id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (count($update_array) > 0) {
|
||||
AssetModel::whereIn('id', $models_raw_array)->update($update_array);
|
||||
return redirect()->route('models.index')
|
||||
->with('success', trans('admin/models/message.bulkedit.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('models.index')
|
||||
->with('warning', trans('admin/models/message.bulkedit.error'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and delete the given Asset Models. An Asset Model
|
||||
* cannot be deleted if there are associated assets.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $modelId
|
||||
* @return Redirect
|
||||
*/
|
||||
public function postBulkDelete(Request $request)
|
||||
{
|
||||
$models_raw_array = Input::get('ids');
|
||||
|
||||
if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) {
|
||||
|
||||
$models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets')->get();
|
||||
|
||||
$del_error_count = 0;
|
||||
$del_count = 0;
|
||||
|
||||
foreach ($models as $model) {
|
||||
\Log::debug($model->id);
|
||||
|
||||
if ($model->assets_count > 0) {
|
||||
$del_error_count++;
|
||||
} else {
|
||||
$model->delete();
|
||||
$del_count++;
|
||||
}
|
||||
}
|
||||
|
||||
\Log::debug($del_count);
|
||||
\Log::debug($del_error_count);
|
||||
|
||||
if ($del_error_count == 0) {
|
||||
return redirect()->route('models.index')
|
||||
->with('success', trans('admin/models/message.bulkdelete.success',['success_count'=> $del_count] ));
|
||||
}
|
||||
|
||||
return redirect()->route('models.index')
|
||||
->with('warning', trans('admin/models/message.bulkdelete.success_partial', ['fail_count'=>$del_error_count, 'success_count'=> $del_count]));
|
||||
}
|
||||
|
||||
return redirect()->route('models.index')
|
||||
->with('error', trans('admin/models/message.bulkdelete.error'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns true if a fieldset is set, 'add default values' is ticked and if
|
||||
* any default values were entered into the form.
|
||||
|
|
|
@ -1,25 +1,29 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Assets;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetCheckinRequest;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
use Illuminate\Support\Facades\View;
|
||||
|
||||
class AssetCheckinController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns a view that presents a form to check an asset back into inventory.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @param string $backto
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
* Returns a view that presents a form to check an asset back into inventory.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @param string $backto
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function create($assetId, $backto = null)
|
||||
{
|
||||
// Check if the asset exists
|
||||
|
@ -40,6 +44,7 @@ class AssetCheckinController extends Controller
|
|||
* @param int $assetId
|
||||
* @param null $backto
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function store(AssetCheckinRequest $request, $assetId = null, $backto = null)
|
||||
|
@ -67,31 +72,20 @@ class AssetCheckinController extends Controller
|
|||
$asset->accepted = null;
|
||||
$asset->name = e($request->get('name'));
|
||||
|
||||
if ($request->has('status_id')) {
|
||||
if ($request->filled('status_id')) {
|
||||
$asset->status_id = e($request->get('status_id'));
|
||||
}
|
||||
|
||||
$asset->location_id = $asset->rtd_location_id;
|
||||
|
||||
if ($request->has('location_id')) {
|
||||
if ($request->filled('location_id')) {
|
||||
$asset->location_id = e($request->get('location_id'));
|
||||
}
|
||||
|
||||
// Was the asset updated?
|
||||
if ($asset->save()) {
|
||||
$logaction = $asset->logCheckin($target, e(request('note')));
|
||||
|
||||
$data['log_id'] = $logaction->id;
|
||||
$data['first_name'] = get_class($target) == User::class ? $target->first_name : '';
|
||||
$data['last_name'] = get_class($target) == User::class ? $target->last_name : '';
|
||||
$data['item_name'] = $asset->present()->name();
|
||||
$data['checkin_date'] = $logaction->created_at;
|
||||
$data['item_tag'] = $asset->asset_tag;
|
||||
$data['item_serial'] = $asset->serial;
|
||||
$data['note'] = $logaction->note;
|
||||
$data['manufacturer_name'] = $asset->model->manufacturer->name;
|
||||
$data['model_name'] = $asset->model->name;
|
||||
$data['model_number'] = $asset->model->model_number;
|
||||
|
||||
event(new CheckoutableCheckedIn($asset, $target, Auth::user(), $request->input('note')));
|
||||
|
||||
if ($backto=='user') {
|
||||
return redirect()->route("users.show", $user->id)->with('success', trans('admin/hardware/message.checkin.success'));
|
|
@ -1,9 +1,11 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Assets;
|
||||
|
||||
|
||||
use App\Exceptions\CheckoutNotAllowed;
|
||||
use App\Http\Controllers\CheckInOutRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetCheckoutRequest;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Location;
|
||||
|
@ -71,12 +73,12 @@ class AssetCheckoutController extends Controller
|
|||
$asset = $this->updateAssetLocation($asset, $target);
|
||||
|
||||
$checkout_at = date("Y-m-d H:i:s");
|
||||
if (($request->has('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) {
|
||||
if (($request->filled('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) {
|
||||
$checkout_at = $request->get('checkout_at');
|
||||
}
|
||||
|
||||
$expected_checkin = '';
|
||||
if ($request->has('expected_checkin')) {
|
||||
if ($request->filled('expected_checkin')) {
|
||||
$expected_checkin = $request->get('expected_checkin');
|
||||
}
|
||||
|
|
@ -1,13 +1,14 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Assets;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class AssetFilesController extends Controller
|
||||
{
|
||||
|
@ -19,6 +20,7 @@ class AssetFilesController extends Controller
|
|||
* @param int $assetId
|
||||
* @return Redirect
|
||||
* @since [v1.0]
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $assetId = null)
|
||||
{
|
||||
|
@ -28,15 +30,15 @@ class AssetFilesController extends Controller
|
|||
|
||||
$this->authorize('update', $asset);
|
||||
|
||||
$destinationPath = config('app.private_uploads').'/assets';
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
|
||||
if (!Storage::exists('private_uploads/assets')) Storage::makeDirectory('private_uploads/assets', 775);
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$filename = 'hardware-'.$asset->id.'-'.str_random(8);
|
||||
$filename .= '-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
$file->move($destinationPath, $filename);
|
||||
$asset->logUpload($filename, e($request->get('notes')));
|
||||
$file_name = 'hardware-'.$asset->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
Storage::put('private_uploads/assets/'.$file_name, $file);
|
||||
$asset->logUpload($file_name, e($request->get('notes')));
|
||||
}
|
||||
return redirect()->back()->with('success', trans('admin/hardware/message.upload.success'));
|
||||
}
|
||||
|
@ -45,14 +47,15 @@ class AssetFilesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
* Check for permissions and display the file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($assetId = null, $fileId = null, $download = true)
|
||||
{
|
||||
$asset = Asset::find($assetId);
|
||||
|
@ -65,24 +68,25 @@ class AssetFilesController extends Controller
|
|||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
$file = $log->get_src('assets');
|
||||
$file = 'private_uploads/assets/'.$log->filename;
|
||||
\Log::debug('Checking for '.$file);
|
||||
|
||||
if ($log->action_type =='audit') {
|
||||
$file = $log->get_src('audits');
|
||||
$file = 'private_uploads/audits/'.$log->filename;
|
||||
}
|
||||
|
||||
if (!file_exists($file)) {
|
||||
if (!Storage::exists($file)) {
|
||||
return response('File '.$file.' not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
if ($download != 'true') {
|
||||
if ($contents = file_get_contents($file)) {
|
||||
return Response::make($contents)->header('Content-Type', mime_content_type($file));
|
||||
if ($contents = file_get_contents(Storage::url($file))) {
|
||||
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
|
||||
}
|
||||
return JsonResponse::create(["error" => "Failed validation: "], 500);
|
||||
}
|
||||
return Response::download($file);
|
||||
return Storage::download($file);
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/hardware/message.does_not_exist', ['id' => $fileId]);
|
||||
|
@ -92,31 +96,31 @@ class AssetFilesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Delete the associated file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
*/
|
||||
* Delete the associated file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $assetId
|
||||
* @param int $fileId
|
||||
* @since [v1.0]
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($assetId = null, $fileId = null)
|
||||
{
|
||||
$asset = Asset::find($assetId);
|
||||
$this->authorize('update', $asset);
|
||||
$destinationPath = config('app.private_uploads').'/imports/assets';
|
||||
$rel_path = 'storage/private_uploads/assets';
|
||||
|
||||
// the asset is valid
|
||||
if (isset($asset->id)) {
|
||||
$this->authorize('update', $asset);
|
||||
|
||||
$log = Actionlog::find($fileId);
|
||||
$full_filename = $destinationPath.'/'.$log->filename;
|
||||
if (file_exists($full_filename)) {
|
||||
unlink($destinationPath.'/'.$log->filename);
|
||||
if (file_exists(base_path().'/'.$rel_path.'/'.$log->filename)) {
|
||||
Storage::disk('public')->delete($rel_path.'/'.$log->filename);
|
||||
}
|
||||
$log->delete();
|
||||
return redirect()->back()->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
return redirect()->back()
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
// Redirect to the hardware management page
|
|
@ -1,18 +1,13 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Assets;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Requests\AssetCheckinRequest;
|
||||
use App\Http\Requests\AssetCheckoutRequest;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Http\Requests\AssetRequest;
|
||||
use App\Http\Requests\ItemImportRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Company;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Import;
|
||||
use App\Models\Location;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
|
@ -27,6 +22,8 @@ use Image;
|
|||
use Input;
|
||||
use Lang;
|
||||
use League\Csv\Reader;
|
||||
use League\Csv\Statement;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Log;
|
||||
use Mail;
|
||||
use Paginator;
|
||||
|
@ -34,11 +31,11 @@ use Redirect;
|
|||
use Response;
|
||||
use Slack;
|
||||
use Str;
|
||||
use Symfony\Component\HttpFoundation\File\Exception\FileException;
|
||||
use TCPDF;
|
||||
use Validator;
|
||||
use View;
|
||||
use App\Models\CheckoutRequest;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* This class controls all actions related to assets for
|
||||
|
@ -66,12 +63,14 @@ class AssetsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see AssetController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @param Request $request
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('index', Asset::class);
|
||||
if ($request->has('company_id')) {
|
||||
if ($request->filled('company_id')) {
|
||||
$company = Company::find($request->input('company_id'));
|
||||
} else {
|
||||
$company = null;
|
||||
|
@ -96,7 +95,7 @@ class AssetsController extends Controller
|
|||
->with('item', new Asset)
|
||||
->with('statuslabel_types', Helper::statusTypeList());
|
||||
|
||||
if ($request->has('model_id')) {
|
||||
if ($request->filled('model_id')) {
|
||||
$selected_model = AssetModel::find($request->input('model_id'));
|
||||
$view->with('selected_model', $selected_model);
|
||||
}
|
||||
|
@ -110,116 +109,106 @@ class AssetsController extends Controller
|
|||
* @since [v1.0]
|
||||
* @return Redirect
|
||||
*/
|
||||
public function store(AssetRequest $request)
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize(Asset::class);
|
||||
|
||||
// Handle asset tags - there could be one, or potentially many.
|
||||
// This is only necessary on create, not update, since bulk editing is handled
|
||||
// differently
|
||||
$asset_tags = $request->input('asset_tags');
|
||||
|
||||
$asset = new Asset();
|
||||
$asset->model()->associate(AssetModel::find($request->input('model_id')));
|
||||
$success = false;
|
||||
$serials = $request->input('serials');
|
||||
|
||||
$asset->name = $request->input('name');
|
||||
$asset->serial = $request->input('serial');
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$asset->model_id = $request->input('model_id');
|
||||
$asset->order_number = $request->input('order_number');
|
||||
$asset->notes = $request->input('notes');
|
||||
$asset->asset_tag = $request->input('asset_tag');
|
||||
$asset->user_id = Auth::id();
|
||||
$asset->archived = '0';
|
||||
$asset->physical = '1';
|
||||
$asset->depreciate = '0';
|
||||
$asset->status_id = request('status_id', 0);
|
||||
$asset->warranty_months = request('warranty_months', null);
|
||||
$asset->purchase_cost = Helper::ParseFloat($request->get('purchase_cost'));
|
||||
$asset->purchase_date = request('purchase_date', null);
|
||||
$asset->assigned_to = request('assigned_to', null);
|
||||
$asset->supplier_id = request('supplier_id', 0);
|
||||
$asset->requestable = request('requestable', 0);
|
||||
$asset->rtd_location_id = request('rtd_location_id', null);
|
||||
for ($a = 1; $a <= count($asset_tags); $a++) {
|
||||
|
||||
if ($asset->assigned_to=='') {
|
||||
$asset->location_id = $request->input('rtd_location_id', null);
|
||||
}
|
||||
$asset = new Asset();
|
||||
$asset->model()->associate(AssetModel::find($request->input('model_id')));
|
||||
$asset->name = $request->input('name');
|
||||
// Check for a corresponding serial
|
||||
if (($serials) && (array_key_exists($a, $serials))) {
|
||||
$asset->serial = $serials[$a];
|
||||
}
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$asset->model_id = $request->input('model_id');
|
||||
$asset->order_number = $request->input('order_number');
|
||||
$asset->notes = $request->input('notes');
|
||||
$asset->user_id = Auth::id();
|
||||
$asset->archived = '0';
|
||||
$asset->physical = '1';
|
||||
$asset->depreciate = '0';
|
||||
$asset->status_id = request('status_id', 0);
|
||||
$asset->warranty_months = request('warranty_months', null);
|
||||
$asset->purchase_cost = Helper::ParseFloat($request->get('purchase_cost'));
|
||||
$asset->purchase_date = request('purchase_date', null);
|
||||
$asset->assigned_to = request('assigned_to', null);
|
||||
$asset->supplier_id = request('supplier_id', 0);
|
||||
$asset->requestable = request('requestable', 0);
|
||||
$asset->rtd_location_id = request('rtd_location_id', null);
|
||||
|
||||
if ($asset->assigned_to=='') {
|
||||
$asset->location_id = $request->input('rtd_location_id', null);
|
||||
}
|
||||
|
||||
// Create the image (if one was chosen.)
|
||||
if ($request->has('image')) {
|
||||
if ($request->hasFile('image')) {
|
||||
$image = $request->input('image');
|
||||
|
||||
// After modification, the image is prefixed by mime info like the following:
|
||||
// data:image/jpeg;base64,; This causes the image library to be unhappy, so we need to remove it.
|
||||
$header = explode(';', $image, 2)[0];
|
||||
// Grab the image type from the header while we're at it.
|
||||
$extension = substr($header, strpos($header, '/')+1);
|
||||
// Start reading the image after the first comma, postceding the base64.
|
||||
$image = substr($image, strpos($image, ',')+1);
|
||||
|
||||
$file_name = str_random(25).".".$extension;
|
||||
|
||||
$directory= public_path('uploads/assets/');
|
||||
// Check if the uploads directory exists. If not, try to create it.
|
||||
if (!file_exists($directory)) {
|
||||
mkdir($directory, 0755, true);
|
||||
}
|
||||
$path = public_path('uploads/assets/'.$file_name);
|
||||
try {
|
||||
Image::make($image)->resize(500, 500, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$asset->image = $file_name;
|
||||
} catch (\Exception $e) {
|
||||
\Input::flash();
|
||||
$messageBag = new \Illuminate\Support\MessageBag();
|
||||
$messageBag->add('image', $e->getMessage());
|
||||
\Session()->flash('errors', \Session::get('errors', new \Illuminate\Support\ViewErrorBag)
|
||||
->put('default', $messageBag));
|
||||
return response()->json(['image' => $e->getMessage()], 422);
|
||||
}
|
||||
}
|
||||
$asset->asset_tag = $asset_tags[$a];
|
||||
$asset = $request->handleImages($asset);
|
||||
|
||||
|
||||
// Update custom fields in the database.
|
||||
// Validation for these fields is handled through the AssetRequest form request
|
||||
$model = AssetModel::find($request->get('model_id'));
|
||||
// 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->fieldset) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($field->field_encrypted=='1') {
|
||||
if (Gate::allows('admin')) {
|
||||
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug()));
|
||||
if (($model) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($field->field_encrypted=='1') {
|
||||
if (Gate::allows('admin')) {
|
||||
$asset->{$field->convertUnicodeDbSlug()} = \Crypt::encrypt($request->input($field->convertUnicodeDbSlug()));
|
||||
}
|
||||
} else {
|
||||
$asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug());
|
||||
}
|
||||
} else {
|
||||
$asset->{$field->convertUnicodeDbSlug()} = $request->input($field->convertUnicodeDbSlug());
|
||||
}
|
||||
}
|
||||
|
||||
// Validate the asset before saving
|
||||
if ($asset->isValid() && $asset->save()) {
|
||||
|
||||
if (request('assigned_user')) {
|
||||
$target = User::find(request('assigned_user'));
|
||||
$location = $target->location_id;
|
||||
} elseif (request('assigned_asset')) {
|
||||
$target = Asset::find(request('assigned_asset'));
|
||||
$location = $target->location_id;
|
||||
} elseif (request('assigned_location')) {
|
||||
$target = Location::find(request('assigned_location'));
|
||||
$location = $target->id;
|
||||
}
|
||||
|
||||
if (isset($target)) {
|
||||
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e($request->get('name')), $location);
|
||||
}
|
||||
|
||||
$success = true;
|
||||
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Was the asset created?
|
||||
if ($asset->save()) {
|
||||
|
||||
|
||||
if (request('assigned_user')) {
|
||||
$target = User::find(request('assigned_user'));
|
||||
$location = $target->location_id;
|
||||
} elseif (request('assigned_asset')) {
|
||||
$target = Asset::find(request('assigned_asset'));
|
||||
$location = $target->location_id;
|
||||
} elseif (request('assigned_location')) {
|
||||
$target = Location::find(request('assigned_location'));
|
||||
$location = $target->id;
|
||||
}
|
||||
|
||||
if (isset($target)) {
|
||||
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), '', 'Checked out on asset creation', e($request->get('name')), $location);
|
||||
}
|
||||
if ($success) {
|
||||
// Redirect to the asset listing page
|
||||
\Session::flash('success', trans('admin/hardware/message.create.success'));
|
||||
return response()->json(['redirect_url' => route('hardware.index')]);
|
||||
return redirect()->route('hardware.index')
|
||||
->with('success', trans('admin/hardware/message.create.success'));
|
||||
}
|
||||
\Input::flash();
|
||||
\Session::flash('errors', $asset->getErrors());
|
||||
return response()->json(['errors' => $asset->getErrors()], 500);
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($asset->getErrors());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -297,7 +286,7 @@ class AssetsController extends Controller
|
|||
* @return Redirect
|
||||
*/
|
||||
|
||||
public function update(AssetRequest $request, $assetId = null)
|
||||
public function update(ImageUploadRequest $request, $assetId = null)
|
||||
{
|
||||
// Check if the asset exists
|
||||
if (!$asset = Asset::find($assetId)) {
|
||||
|
@ -313,7 +302,7 @@ class AssetsController extends Controller
|
|||
$asset->supplier_id = $request->input('supplier_id', null);
|
||||
|
||||
// If the box isn't checked, it's not in the request at all.
|
||||
$asset->requestable = $request->has('requestable');
|
||||
$asset->requestable = $request->filled('requestable');
|
||||
$asset->rtd_location_id = $request->input('rtd_location_id', null);
|
||||
|
||||
if ($asset->assigned_to=='') {
|
||||
|
@ -321,7 +310,7 @@ class AssetsController extends Controller
|
|||
}
|
||||
|
||||
|
||||
if ($request->has('image_delete')) {
|
||||
if ($request->filled('image_delete')) {
|
||||
try {
|
||||
unlink(public_path().'/uploads/assets/'.$asset->image);
|
||||
$asset->image = '';
|
||||
|
@ -333,47 +322,18 @@ class AssetsController extends Controller
|
|||
|
||||
|
||||
// Update the asset data
|
||||
$asset_tag = $request->input('asset_tags');
|
||||
$serial = $request->input('serials');
|
||||
$asset->name = $request->input('name');
|
||||
$asset->serial = $request->input('serial');
|
||||
$asset->serial = $serial[1];
|
||||
$asset->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$asset->model_id = $request->input('model_id');
|
||||
$asset->order_number = $request->input('order_number');
|
||||
$asset->asset_tag = $request->input('asset_tag');
|
||||
$asset->asset_tag = $asset_tag[1];
|
||||
$asset->notes = $request->input('notes');
|
||||
$asset->physical = '1';
|
||||
|
||||
// Update the image
|
||||
if ($request->has('image')) {
|
||||
$image = $request->input('image');
|
||||
// See postCreate for more explaination of the following.
|
||||
$header = explode(';', $image, 2)[0];
|
||||
$extension = substr($header, strpos($header, '/')+1);
|
||||
$image = substr($image, strpos($image, ',')+1);
|
||||
|
||||
$directory= public_path('uploads/assets/');
|
||||
// Check if the uploads directory exists. If not, try to create it.
|
||||
if (!file_exists($directory)) {
|
||||
mkdir($directory, 0755, true);
|
||||
}
|
||||
|
||||
$file_name = str_random(25).".".$extension;
|
||||
$path = public_path('uploads/assets/'.$file_name);
|
||||
try {
|
||||
Image::make($image)->resize(500, 500, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$asset->image = $file_name;
|
||||
} catch (\Exception $e) {
|
||||
\Input::flash();
|
||||
$messageBag = new \Illuminate\Support\MessageBag();
|
||||
$messageBag->add('image', $e->getMessage());
|
||||
\Session()->flash('errors', \Session::get('errors', new \Illuminate\Support\ViewErrorBag)
|
||||
->put('default', $messageBag));
|
||||
return response()->json(['image' => $e->getMessage()], 422);
|
||||
}
|
||||
$asset->image = $file_name;
|
||||
}
|
||||
$asset = $request->handleImages($asset);
|
||||
|
||||
// Update custom fields in the database.
|
||||
// Validation for these fields is handlded through the AssetRequest form request
|
||||
|
@ -394,13 +354,12 @@ class AssetsController extends Controller
|
|||
|
||||
|
||||
if ($asset->save()) {
|
||||
// Redirect to the new asset page
|
||||
\Session::flash('success', trans('admin/hardware/message.update.success'));
|
||||
return response()->json(['redirect_url' => route("hardware.show", $assetId)]);
|
||||
return redirect()->route("hardware.show", $assetId)
|
||||
->with('success', trans('admin/hardware/message.update.success'));
|
||||
}
|
||||
\Input::flash();
|
||||
\Session::flash('errors', $asset->getErrors());
|
||||
return response()->json(['errors' => $asset->getErrors()], 500);
|
||||
|
||||
return redirect()->back()->withInput()->withErrors()->with('error', trans('admin/hardware/message.does_not_exist'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -425,6 +384,14 @@ class AssetsController extends Controller
|
|||
->where('id', $asset->id)
|
||||
->update(array('assigned_to' => null));
|
||||
|
||||
if ($asset->image) {
|
||||
try {
|
||||
Storage::disk('public')->delete('assets'.'/'.$asset->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$asset->delete();
|
||||
|
||||
return redirect()->route('hardware.index')->with('success', trans('admin/hardware/message.delete.success'));
|
||||
|
@ -554,7 +521,7 @@ class AssetsController extends Controller
|
|||
*/
|
||||
public function getImportHistory()
|
||||
{
|
||||
$this->authorize('checkout', Asset::class);
|
||||
$this->authorize('admin');
|
||||
return view('hardware/history');
|
||||
}
|
||||
|
||||
|
@ -564,8 +531,8 @@ class AssetsController extends Controller
|
|||
* This needs a LOT of love. It's done very inelegantly right now, and there are
|
||||
* a ton of optimizations that could (and should) be done.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.3]
|
||||
* @author [herroworrd]
|
||||
* @since [v5.0]
|
||||
* @return View
|
||||
*/
|
||||
public function postImportHistory(Request $request)
|
||||
|
@ -574,129 +541,103 @@ class AssetsController extends Controller
|
|||
ini_set("auto_detect_line_endings", '1');
|
||||
}
|
||||
|
||||
$csv = Reader::createFromPath(Input::file('user_import_csv'));
|
||||
$csv->setNewline("\r\n");
|
||||
//get the first row, usually the CSV header
|
||||
//$headers = $csv->fetchOne();
|
||||
$requiredcolumns = ['Asset Tag', 'Checkout Date', 'Checkin Date', 'Full Name'];
|
||||
|
||||
$csv = Reader::createFromPath(Input::file('user_import_csv'));
|
||||
|
||||
$csv->setHeaderOffset(0);
|
||||
|
||||
//Stop here if we don't have the columns we need
|
||||
if(count(array_intersect($requiredcolumns, $csv->getHeader())) != count($requiredcolumns)) {
|
||||
$status['error'][]['csv'][]['msg'] = 'Headers do not match';
|
||||
return view('hardware/history')->with('status', $status);
|
||||
}
|
||||
$statement = (new Statement())
|
||||
->orderBy(\Closure::fromCallable([$this, 'sortByName']));
|
||||
|
||||
$results = $statement->process($csv);
|
||||
|
||||
$results = $csv->fetchAssoc();
|
||||
$item = array();
|
||||
$status = array();
|
||||
$status['error'] = array();
|
||||
$status['success'] = array();
|
||||
$base_username = null;
|
||||
$cachetime = Carbon::now()->addSeconds(120);
|
||||
|
||||
foreach ($results as $record) {
|
||||
|
||||
foreach ($results as $row) {
|
||||
if (is_array($row)) {
|
||||
$row = array_change_key_case($row, CASE_LOWER);
|
||||
$asset_tag = Helper::array_smart_fetch($row, "asset tag");
|
||||
if (!array_key_exists($asset_tag, $item)) {
|
||||
$item[$asset_tag] = array();
|
||||
}
|
||||
$batch_counter = count($item[$asset_tag]);
|
||||
$asset_tag = $record['Asset Tag'];
|
||||
|
||||
$item[$asset_tag][$batch_counter]['checkout_date'] = Carbon::parse(Helper::array_smart_fetch($row, "date"))->format('Y-m-d H:i:s');
|
||||
|
||||
$item[$asset_tag][$batch_counter]['asset_tag'] = Helper::array_smart_fetch($row, "asset tag");
|
||||
$item[$asset_tag][$batch_counter]['name'] = Helper::array_smart_fetch($row, "name");
|
||||
$item[$asset_tag][$batch_counter]['email'] = Helper::array_smart_fetch($row, "email");
|
||||
|
||||
if ($asset = Asset::where('asset_tag', '=', $asset_tag)->first()) {
|
||||
$item[$asset_tag][$batch_counter]['asset_id'] = $asset->id;
|
||||
|
||||
$base_username = User::generateFormattedNameFromFullName(Setting::getSettings()->username_format, $item[$asset_tag][$batch_counter]['name']);
|
||||
$user = User::where('username', '=', $base_username['username']);
|
||||
$user_query = ' on username '.$base_username['username'];
|
||||
|
||||
if ($request->input('match_firstnamelastname')=='1') {
|
||||
$firstnamedotlastname = User::generateFormattedNameFromFullName('firstname.lastname', $item[$asset_tag][$batch_counter]['name']);
|
||||
$item[$asset_tag][$batch_counter]['username'][] = $firstnamedotlastname['username'];
|
||||
$user->orWhere('username', '=', $firstnamedotlastname['username']);
|
||||
$user_query .= ', or on username '.$firstnamedotlastname['username'];
|
||||
}
|
||||
|
||||
if ($request->input('match_flastname')=='1') {
|
||||
$flastname = User::generateFormattedNameFromFullName('filastname', $item[$asset_tag][$batch_counter]['name']);
|
||||
$item[$asset_tag][$batch_counter]['username'][] = $flastname['username'];
|
||||
$user->orWhere('username', '=', $flastname['username']);
|
||||
$user_query .= ', or on username '.$flastname['username'];
|
||||
}
|
||||
if ($request->input('match_firstname')=='1') {
|
||||
$firstname = User::generateFormattedNameFromFullName('firstname', $item[$asset_tag][$batch_counter]['name']);
|
||||
$item[$asset_tag][$batch_counter]['username'][] = $firstname['username'];
|
||||
$user->orWhere('username', '=', $firstname['username']);
|
||||
$user_query .= ', or on username '.$firstname['username'];
|
||||
}
|
||||
if ($request->input('match_email')=='1') {
|
||||
if ($item[$asset_tag][$batch_counter]['email']=='') {
|
||||
$item[$asset_tag][$batch_counter]['username'][] = $user_email = User::generateEmailFromFullName($item[$asset_tag][$batch_counter]['name']);
|
||||
$user->orWhere('username', '=', $user_email);
|
||||
$user_query .= ', or on username '.$user_email;
|
||||
}
|
||||
}
|
||||
|
||||
// A matching user was found
|
||||
if ($user = $user->first()) {
|
||||
$item[$asset_tag][$batch_counter]['checkedout_to'] = $user->id;
|
||||
$item[$asset_tag][$batch_counter]['user_id'] = $user->id;
|
||||
|
||||
Actionlog::firstOrCreate(array(
|
||||
'item_id' => $asset->id,
|
||||
'item_type' => Asset::class,
|
||||
'user_id' => Auth::user()->id,
|
||||
'note' => 'Checkout imported by '.Auth::user()->present()->fullName().' from history importer',
|
||||
'target_id' => $item[$asset_tag][$batch_counter]['user_id'],
|
||||
'target_type' => User::class,
|
||||
'created_at' => $item[$asset_tag][$batch_counter]['checkout_date'],
|
||||
'action_type' => 'checkout',
|
||||
));
|
||||
|
||||
$asset->assigned_to = $user->id;
|
||||
|
||||
if ($asset->save()) {
|
||||
$status['success'][]['asset'][$asset_tag]['msg'] = 'Asset successfully matched for '.Helper::array_smart_fetch($row, "name").$user_query.' on '.$item[$asset_tag][$batch_counter]['checkout_date'];
|
||||
} else {
|
||||
$status['error'][]['asset'][$asset_tag]['msg'] = 'Asset and user was matched but could not be saved.';
|
||||
}
|
||||
} else {
|
||||
$item[$asset_tag][$batch_counter]['checkedout_to'] = null;
|
||||
$status['error'][]['user'][Helper::array_smart_fetch($row, "name")]['msg'] = 'User does not exist so no checkin log was created.';
|
||||
}
|
||||
} else {
|
||||
$item[$asset_tag][$batch_counter]['asset_id'] = null;
|
||||
$status['error'][]['asset'][$asset_tag]['msg'] = 'Asset does not exist so no match was attempted.';
|
||||
}
|
||||
try {
|
||||
$checkoutdate = Carbon::parse($record['Checkout Date'])->format('Y-m-d H:i:s');
|
||||
$checkindate = Carbon::parse($record['Checkin Date'])->format('Y-m-d H:i:s');
|
||||
}
|
||||
catch (\Exception $err) {
|
||||
$status['error'][]['asset'][$asset_tag]['msg'] = 'Your dates are screwed up. Format needs to be Y-m-d H:i:s';
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// Loop through and backfill the checkins
|
||||
foreach ($item as $key => $asset_batch) {
|
||||
$total_in_batch = count($asset_batch);
|
||||
for ($x = 0; $x < $total_in_batch; $x++) {
|
||||
$next = $x + 1;
|
||||
if($asset = Cache::remember('asset:' . $asset_tag, $cachetime, function () use( &$asset_tag) {
|
||||
$tocache = Asset::where('asset_tag', '=', $asset_tag)->value('id');
|
||||
return is_null($tocache) ? false : $tocache;}))
|
||||
{
|
||||
//we've found our asset, now lets look for a user
|
||||
if($base_username != User::generateFormattedNameFromFullName($record['Full Name'], Setting::getSettings()->username_format)) {
|
||||
|
||||
// Only do this if a matching user was found
|
||||
if ((array_key_exists('checkedout_to', $asset_batch[$x])) && ($asset_batch[$x]['checkedout_to']!='')) {
|
||||
if (($total_in_batch > 1) && ($x < $total_in_batch) && (array_key_exists($next, $asset_batch))) {
|
||||
$checkin_date = Carbon::parse($asset_batch[$next]['checkout_date'])->subDay(1)->format('Y-m-d H:i:s');
|
||||
$asset_batch[$x]['real_checkin'] = $checkin_date;
|
||||
$base_username = User::generateFormattedNameFromFullName($record['Full Name'], Setting::getSettings()->username_format);
|
||||
|
||||
if(!$user = Cache::remember('user:' . $base_username['username'], $cachetime, function () use( &$base_username) {
|
||||
$tocache = User::where('username', '=', $base_username['username'])->value('id');
|
||||
return is_null($tocache) ? false : $tocache;}))
|
||||
{
|
||||
$status['error'][]['asset'][$asset_tag]['msg'] = 'Asset was found but user (' . $record['Full Name'] . ') not matched';
|
||||
$base_username = null;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if($checkoutdate < $checkindate) {
|
||||
|
||||
Actionlog::firstOrCreate(array(
|
||||
'item_id' => $asset_batch[$x]['asset_id'],
|
||||
'item_id' => $asset,
|
||||
'item_type' => Asset::class,
|
||||
'user_id' => Auth::user()->id,
|
||||
'note' => 'Checkin imported by ' . Auth::user()->present()->fullName() . ' from history importer',
|
||||
'target_id' => null,
|
||||
'created_at' => $checkin_date,
|
||||
'note' => 'Historical record added by ' . Auth::user()->present()->fullName(),
|
||||
'target_id' => $user,
|
||||
'target_type' => User::class,
|
||||
'created_at' => $checkoutdate,
|
||||
'action_type' => 'checkout',
|
||||
));
|
||||
|
||||
Actionlog::firstOrCreate(array(
|
||||
'item_id' => $asset,
|
||||
'item_type' => Asset::class,
|
||||
'user_id' => Auth::user()->id,
|
||||
'note' => 'Historical record added by ' . Auth::user()->present()->fullName(),
|
||||
'target_id' => $user,
|
||||
'target_type' => User::class,
|
||||
'created_at' => $checkindate,
|
||||
'action_type' => 'checkin'
|
||||
));
|
||||
}
|
||||
|
||||
$status['success'][]['asset'][$asset_tag]['msg'] = 'Asset successfully matched for ' . $record['Full Name'] . ' on ' . $checkoutdate;
|
||||
}
|
||||
else {
|
||||
$status['error'][]['asset'][$asset_tag]['msg'] = 'Checkin date needs to be after checkout date.';
|
||||
}
|
||||
}
|
||||
else {
|
||||
$status['error'][]['asset'][$asset_tag]['msg'] = 'Asset not found in Snipe';
|
||||
}
|
||||
}
|
||||
|
||||
return view('hardware/history')->with('status', $status);
|
||||
}
|
||||
|
||||
protected function sortByName(array $recordA, array $recordB): int
|
||||
{
|
||||
return strcmp($recordB['Full Name'], $recordA['Full Name']);
|
||||
}
|
||||
|
||||
/**
|
||||
* Retore a deleted asset.
|
||||
*
|
||||
|
@ -745,7 +686,7 @@ class AssetsController extends Controller
|
|||
}
|
||||
|
||||
|
||||
public function auditStore(AssetFileRequest $request, $id)
|
||||
public function auditStore(Request $request, $id)
|
||||
{
|
||||
$this->authorize('audit', Asset::class);
|
||||
|
||||
|
@ -768,24 +709,28 @@ class AssetsController extends Controller
|
|||
$asset->next_audit_date = $request->input('next_audit_date');
|
||||
$asset->last_audit_date = date('Y-m-d h:i:s');
|
||||
|
||||
// Check to see if they checked the box to update the physical location,
|
||||
// not just note it in the audit notes
|
||||
if ($request->input('update_location')=='1') {
|
||||
\Log::debug('update location in audit');
|
||||
$asset->location_id = $request->input('location_id');
|
||||
}
|
||||
|
||||
|
||||
if ($asset->save()) {
|
||||
|
||||
|
||||
$filename = '';
|
||||
|
||||
$file_name = '';
|
||||
// Upload an image, if attached
|
||||
if ($request->hasFile('image')) {
|
||||
$file = $request->file('image');
|
||||
try {
|
||||
$destinationPath = config('app.private_uploads').'/audits';
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$filename = 'audit-'.$asset->id.'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
$file->move($destinationPath, $filename);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
$path = 'private_uploads/audits';
|
||||
if (!Storage::exists($path)) Storage::makeDirectory($path, 775);
|
||||
$upload = $image = $request->file('image');
|
||||
$ext = $image->getClientOriginalExtension();
|
||||
$file_name = 'audit-'.str_random(18).'.'.$ext;
|
||||
Storage::putFileAs($path, $upload, $file_name);
|
||||
}
|
||||
|
||||
$asset->logAudit($request->input('note'), $request->input('location_id'), $filename);
|
||||
|
||||
$asset->logAudit($request->input('note'), $request->input('location_id'), $file_name);
|
||||
return redirect()->to("hardware")->with('success', trans('admin/hardware/message.audit.success'));
|
||||
}
|
||||
}
|
|
@ -1,9 +1,10 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
namespace App\Http\Controllers\Assets;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\CheckInOutRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
|
@ -14,6 +15,7 @@ use Illuminate\Support\Facades\DB;
|
|||
class BulkAssetsController extends Controller
|
||||
{
|
||||
use CheckInOutRequest;
|
||||
|
||||
/**
|
||||
* Display the bulk edit page.
|
||||
*
|
||||
|
@ -21,18 +23,19 @@ class BulkAssetsController extends Controller
|
|||
* @return View
|
||||
* @internal param int $assetId
|
||||
* @since [v2.0]
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit(Request $request)
|
||||
{
|
||||
$this->authorize('update', Asset::class);
|
||||
|
||||
if (!$request->has('ids')) {
|
||||
if (!$request->filled('ids')) {
|
||||
return redirect()->back()->with('error', 'No assets selected');
|
||||
}
|
||||
|
||||
$asset_ids = array_keys($request->input('ids'));
|
||||
|
||||
if ($request->has('bulk_actions')) {
|
||||
if ($request->filled('bulk_actions')) {
|
||||
switch($request->input('bulk_actions')) {
|
||||
case 'labels':
|
||||
return view('hardware/labels')
|
||||
|
@ -68,22 +71,22 @@ class BulkAssetsController extends Controller
|
|||
|
||||
\Log::debug($request->input('ids'));
|
||||
|
||||
if(!$request->has('ids') || count($request->input('ids')) <= 0) {
|
||||
if(!$request->filled('ids') || count($request->input('ids')) <= 0) {
|
||||
return redirect()->route("hardware.index")->with('warning', trans('No assets selected, so nothing was updated.'));
|
||||
}
|
||||
|
||||
$assets = array_keys($request->input('ids'));
|
||||
|
||||
if (($request->has('purchase_date'))
|
||||
|| ($request->has('purchase_cost'))
|
||||
|| ($request->has('supplier_id'))
|
||||
|| ($request->has('order_number'))
|
||||
|| ($request->has('warranty_months'))
|
||||
|| ($request->has('rtd_location_id'))
|
||||
|| ($request->has('requestable'))
|
||||
|| ($request->has('company_id'))
|
||||
|| ($request->has('status_id'))
|
||||
|| ($request->has('model_id'))
|
||||
if (($request->filled('purchase_date'))
|
||||
|| ($request->filled('purchase_cost'))
|
||||
|| ($request->filled('supplier_id'))
|
||||
|| ($request->filled('order_number'))
|
||||
|| ($request->filled('warranty_months'))
|
||||
|| ($request->filled('rtd_location_id'))
|
||||
|| ($request->filled('requestable'))
|
||||
|| ($request->filled('company_id'))
|
||||
|| ($request->filled('status_id'))
|
||||
|| ($request->filled('model_id'))
|
||||
) {
|
||||
foreach ($assets as $assetId) {
|
||||
$this->update_array = [];
|
||||
|
@ -96,20 +99,20 @@ class BulkAssetsController extends Controller
|
|||
->conditionallyAddItem('supplier_id')
|
||||
->conditionallyAddItem('warranty_months');
|
||||
|
||||
if ($request->has('purchase_cost')) {
|
||||
if ($request->filled('purchase_cost')) {
|
||||
$this->update_array['purchase_cost'] = Helper::ParseFloat($request->input('purchase_cost'));
|
||||
}
|
||||
|
||||
if ($request->has('company_id')) {
|
||||
if ($request->filled('company_id')) {
|
||||
$this->update_array['company_id'] = $request->input('company_id');
|
||||
if ($request->input('company_id')=="clear") {
|
||||
$this->update_array['company_id'] = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($request->has('rtd_location_id')) {
|
||||
if ($request->filled('rtd_location_id')) {
|
||||
$this->update_array['rtd_location_id'] = $request->input('rtd_location_id');
|
||||
if (($request->has('update_real_loc')) && (($request->input('update_real_loc')) == '1')) {
|
||||
if (($request->filled('update_real_loc')) && (($request->input('update_real_loc')) == '1')) {
|
||||
$this->update_array['location_id'] = $request->input('rtd_location_id');
|
||||
}
|
||||
}
|
||||
|
@ -130,14 +133,15 @@ class BulkAssetsController extends Controller
|
|||
* @var Array
|
||||
*/
|
||||
private $update_array;
|
||||
|
||||
/**
|
||||
* Adds parameter to update array for an item if it exists in request
|
||||
* @param String $field field name
|
||||
* @return this Model for Chaining
|
||||
* @param String $field field name
|
||||
* @return BulkAssetsController Model for Chaining
|
||||
*/
|
||||
protected function conditionallyAddItem($field)
|
||||
{
|
||||
if(request()->has($field)) {
|
||||
if(request()->filled($field)) {
|
||||
$this->update_array[$field] = request()->input($field);
|
||||
}
|
||||
return $this;
|
||||
|
@ -147,7 +151,9 @@ class BulkAssetsController extends Controller
|
|||
* Save bulk deleted.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param Request $request
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @internal param array $assets
|
||||
* @since [v2.0]
|
||||
*/
|
||||
|
@ -155,7 +161,7 @@ class BulkAssetsController extends Controller
|
|||
{
|
||||
$this->authorize('delete', Asset::class);
|
||||
|
||||
if ($request->has('ids')) {
|
||||
if ($request->filled('ids')) {
|
||||
$assets = Asset::find($request->get('ids'));
|
||||
foreach ($assets as $asset) {
|
||||
$update_array['deleted_at'] = date('Y-m-d H:i:s');
|
||||
|
@ -206,13 +212,13 @@ class BulkAssetsController extends Controller
|
|||
}
|
||||
}
|
||||
$checkout_at = date("Y-m-d H:i:s");
|
||||
if (($request->has('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) {
|
||||
if (($request->filled('checkout_at')) && ($request->get('checkout_at')!= date("Y-m-d"))) {
|
||||
$checkout_at = e($request->get('checkout_at'));
|
||||
}
|
||||
|
||||
$expected_checkin = '';
|
||||
|
||||
if ($request->has('expected_checkin')) {
|
||||
if ($request->filled('expected_checkin')) {
|
||||
$expected_checkin = e($request->get('expected_checkin'));
|
||||
}
|
||||
|
|
@ -5,6 +5,7 @@ namespace App\Http\Controllers\Auth;
|
|||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\SendsPasswordResetEmails;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\User;
|
||||
|
||||
class ForgotPasswordController extends Controller
|
||||
{
|
||||
|
@ -49,27 +50,28 @@ class ForgotPasswordController extends Controller
|
|||
*/
|
||||
public function sendResetLinkEmail(Request $request)
|
||||
{
|
||||
$this->validate($request, ['email' => 'required|email']);
|
||||
$this->validate($request, ['username' => 'required'], ['username.required' => 'Please enter your username.']);
|
||||
|
||||
// We will send the password reset link to this user. Once we have attempted
|
||||
// to send the link, we will examine the response then see the message we
|
||||
// need to show to the user. Finally, we'll send out a proper response.
|
||||
|
||||
// Make sure the user is active, and their password is not controlled via LDAP
|
||||
$response = $this->broker()->sendResetLink(
|
||||
array_merge(
|
||||
$request->only('email'),
|
||||
['activated' => '1']
|
||||
$request->only('username'),
|
||||
['activated' => '1'],
|
||||
['ldap_import' => '0']
|
||||
)
|
||||
);
|
||||
|
||||
if ($response === \Password::RESET_LINK_SENT) {
|
||||
return redirect()->route('login')->with('status', trans($response));
|
||||
\Log::info('Password reset attempt: User '.$request->input('username').' found, password reset sent');
|
||||
} else {
|
||||
\Log::info('Password reset attempt: User '.$request->input('username').' not found or user is inactive');
|
||||
}
|
||||
|
||||
// If an error was returned by the password broker, we will get this message
|
||||
// translated so we can notify a user of the problem. We'll redirect back
|
||||
// to where the users came from so they can attempt this process again.
|
||||
return back()->withErrors(
|
||||
['email' => trans($response)]
|
||||
);
|
||||
|
||||
|
||||
// Regardless of response, we do not want to disclose the status of a user account,
|
||||
// so we give them a generic "If this exists, we're TOTALLY gonna email you" response
|
||||
return redirect()->route('login')->with('success',trans('passwords.sent'));
|
||||
}
|
||||
}
|
||||
|
|
|
@ -2,20 +2,19 @@
|
|||
|
||||
namespace App\Http\Controllers\Auth;
|
||||
|
||||
use Validator;
|
||||
use App\Services\LdapAd;
|
||||
use Illuminate\Support\Carbon;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ThrottlesLogins;
|
||||
use App\Models\Setting;
|
||||
use App\Models\Ldap;
|
||||
use App\Models\User;
|
||||
use Auth;
|
||||
use Config;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Input;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Redirect;
|
||||
use Log;
|
||||
use View;
|
||||
use PragmaRX\Google2FA\Google2FA;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
/**
|
||||
* This controller handles authentication for the user, including local
|
||||
|
@ -39,15 +38,24 @@ class LoginController extends Controller
|
|||
*/
|
||||
protected $redirectTo = '/';
|
||||
|
||||
/**
|
||||
* @var LdapAd
|
||||
*/
|
||||
protected $ldap;
|
||||
|
||||
/**
|
||||
* Create a new authentication controller instance.
|
||||
*
|
||||
* @param LdapAd $ldap
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct()
|
||||
public function __construct(LdapAd $ldap)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->middleware('guest', ['except' => ['logout','postTwoFactorAuth','getTwoFactorAuth','getTwoFactorEnroll']]);
|
||||
\Session::put('backUrl', \URL::previous());
|
||||
Session::put('backUrl', \URL::previous());
|
||||
$this->ldap = $ldap;
|
||||
}
|
||||
|
||||
function showLoginForm(Request $request)
|
||||
|
@ -64,6 +72,29 @@ class LoginController extends Controller
|
|||
return view('auth.login');
|
||||
}
|
||||
|
||||
/**
|
||||
* Log in a user by LDAP
|
||||
*
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return User
|
||||
*
|
||||
* @throws \Exception
|
||||
*/
|
||||
private function loginViaLdap(Request $request): User
|
||||
{
|
||||
try {
|
||||
return $this->ldap->ldapLogin($request->input('username'), $request->input('password'));
|
||||
} catch (\Exception $ex) {
|
||||
LOG::debug("LDAP user login: " . $ex->getMessage());
|
||||
throw new \Exception($ex->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
private function loginViaRemoteUser(Request $request)
|
||||
{
|
||||
$remote_user = $request->server('REMOTE_USER');
|
||||
|
@ -85,53 +116,6 @@ class LoginController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
private function loginViaLdap(Request $request)
|
||||
{
|
||||
Log::debug("Binding user to LDAP.");
|
||||
$ldap_user = Ldap::findAndBindUserLdap($request->input('username'), $request->input('password'));
|
||||
if (!$ldap_user) {
|
||||
Log::debug("LDAP user ".$request->input('username')." not found in LDAP or could not bind");
|
||||
throw new \Exception("Could not find user in LDAP directory");
|
||||
} else {
|
||||
Log::debug("LDAP user ".$request->input('username')." successfully bound to LDAP");
|
||||
}
|
||||
|
||||
// Check if the user already exists in the database and was imported via LDAP
|
||||
$user = User::where('username', '=', Input::get('username'))->whereNull('deleted_at')->where('ldap_import', '=', 1)->where('activated', '=', '1')->first();
|
||||
Log::debug("Local auth lookup complete");
|
||||
|
||||
// The user does not exist in the database. Try to get them from LDAP.
|
||||
// If user does not exist and authenticates successfully with LDAP we
|
||||
// will create it on the fly and sign in with default permissions
|
||||
if (!$user) {
|
||||
Log::debug("Local user ".Input::get('username')." does not exist");
|
||||
Log::debug("Creating local user ".Input::get('username'));
|
||||
|
||||
if ($user = Ldap::createUserFromLdap($ldap_user)) { //this handles passwords on its own
|
||||
Log::debug("Local user created.");
|
||||
} else {
|
||||
Log::debug("Could not create local user.");
|
||||
throw new \Exception("Could not create local user");
|
||||
}
|
||||
// If the user exists and they were imported from LDAP already
|
||||
} else {
|
||||
Log::debug("Local user ".$request->input('username')." exists in database. Updating existing user against LDAP.");
|
||||
|
||||
$ldap_attr = Ldap::parseAndMapLdapAttributes($ldap_user);
|
||||
|
||||
if (Setting::getSettings()->ldap_pw_sync=='1') {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
$user->email = $ldap_attr['email'];
|
||||
$user->first_name = $ldap_attr['firstname'];
|
||||
$user->last_name = $ldap_attr['lastname'];
|
||||
$user->save();
|
||||
} // End if(!user)
|
||||
return $user;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Account sign in form processing.
|
||||
*
|
||||
|
@ -160,9 +144,10 @@ class LoginController extends Controller
|
|||
$user = null;
|
||||
|
||||
// Should we even check for LDAP users?
|
||||
if (Setting::getSettings()->ldap_enabled=='1') {
|
||||
Log::debug("LDAP is enabled.");
|
||||
if ($this->ldap->init()) {
|
||||
LOG::debug("LDAP is enabled.");
|
||||
try {
|
||||
LOG::debug("Attempting to log user in by LDAP authentication.");
|
||||
$user = $this->loginViaLdap($request);
|
||||
Auth::login($user, true);
|
||||
|
||||
|
@ -192,8 +177,8 @@ class LoginController extends Controller
|
|||
}
|
||||
|
||||
if ($user = Auth::user()) {
|
||||
$user->last_login = \Carbon::now();
|
||||
\Log::debug('Last login:'.$user->last_login);
|
||||
$user->last_login = Carbon::now();
|
||||
Log::debug('Last login:'.$user->last_login);
|
||||
$user->save();
|
||||
}
|
||||
// Redirect to the users page
|
||||
|
@ -214,7 +199,7 @@ class LoginController extends Controller
|
|||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA');
|
||||
$google2fa = app()->make('pragmarx.google2fa');
|
||||
|
||||
if ($user->two_factor_secret=='') {
|
||||
$user->two_factor_secret = $google2fa->generateSecretKey(32);
|
||||
|
@ -222,7 +207,7 @@ class LoginController extends Controller
|
|||
}
|
||||
|
||||
|
||||
$google2fa_url = $google2fa->getQRCodeGoogleUrl(
|
||||
$google2fa_url = $google2fa->getQRCodeInline(
|
||||
urlencode(Setting::getSettings()->site_name),
|
||||
urlencode($user->username),
|
||||
$user->two_factor_secret
|
||||
|
@ -246,6 +231,8 @@ class LoginController extends Controller
|
|||
/**
|
||||
* Two factor code submission
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Redirect
|
||||
*/
|
||||
public function postTwoFactorAuth(Request $request)
|
||||
|
@ -257,7 +244,7 @@ class LoginController extends Controller
|
|||
|
||||
$user = Auth::user();
|
||||
$secret = $request->get('two_factor_secret');
|
||||
$google2fa = app()->make('PragmaRX\Google2FA\Contracts\Google2FA');
|
||||
$google2fa = app()->make('pragmarx.google2fa');
|
||||
$valid = $google2fa->verifyKey($user->two_factor_secret, $secret);
|
||||
|
||||
if ($valid) {
|
||||
|
@ -276,6 +263,8 @@ class LoginController extends Controller
|
|||
/**
|
||||
* Logout page.
|
||||
*
|
||||
* @param Request $request
|
||||
*
|
||||
* @return Redirect
|
||||
*/
|
||||
public function logout(Request $request)
|
||||
|
@ -340,7 +329,7 @@ class LoginController extends Controller
|
|||
* Override the lockout time and duration
|
||||
*
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @return bool
|
||||
*/
|
||||
protected function hasTooManyLoginAttempts(Request $request)
|
||||
{
|
||||
|
|
|
@ -4,9 +4,9 @@ namespace App\Http\Controllers\Auth;
|
|||
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Foundation\Auth\ResetsPasswords;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
|
||||
class ResetPasswordController extends Controller
|
||||
{
|
||||
/*
|
||||
|
@ -39,7 +39,36 @@ class ResetPasswordController extends Controller
|
|||
$this->middleware('guest');
|
||||
}
|
||||
|
||||
|
||||
protected function rules()
|
||||
{
|
||||
return [
|
||||
'token' => 'required',
|
||||
'username' => 'required',
|
||||
'password' => 'required|confirmed|min:6',
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
protected function credentials(Request $request)
|
||||
{
|
||||
return $request->only(
|
||||
'username', 'password', 'password_confirmation', 'token'
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
public function showResetForm(Request $request, $token = null)
|
||||
{
|
||||
return view('auth.passwords.reset')->with(
|
||||
['token' => $token, 'username' => $request->input('username')]
|
||||
);
|
||||
}
|
||||
|
||||
protected function sendResetFailedResponse(Request $request, $response)
|
||||
{
|
||||
return redirect()->back()
|
||||
->withInput(['username'=>$request->input('username')])
|
||||
->withErrors(['username' => trans($response)]);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
138
app/Http/Controllers/BulkAssetModelsController.php
Normal file
138
app/Http/Controllers/BulkAssetModelsController.php
Normal file
|
@ -0,0 +1,138 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\AssetModel;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Redirect;
|
||||
|
||||
class BulkAssetModelsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns a view that allows the user to bulk edit model attrbutes
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.7]
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit(Request $request)
|
||||
{
|
||||
$models_raw_array = Input::get('ids');
|
||||
|
||||
// Make sure some IDs have been selected
|
||||
if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) {
|
||||
|
||||
$models = AssetModel::whereIn('id', $models_raw_array)
|
||||
->withCount('assets as assets_count')
|
||||
->orderBy('assets_count', 'ASC')
|
||||
->get();
|
||||
|
||||
// If deleting....
|
||||
if ($request->input('bulk_actions')=='delete') {
|
||||
$valid_count = 0;
|
||||
foreach ($models as $model) {
|
||||
if ($model->assets_count == 0) {
|
||||
$valid_count++;
|
||||
}
|
||||
}
|
||||
return view('models/bulk-delete', compact('models'))->with('valid_count', $valid_count);
|
||||
|
||||
// Otherwise display the bulk edit screen
|
||||
}
|
||||
|
||||
$nochange = ['NC' => 'No Change'];
|
||||
return view('models/bulk-edit', compact('models'))
|
||||
->with('fieldset_list', $nochange + Helper::customFieldsetList())
|
||||
->with('depreciation_list', $nochange + Helper::depreciationList());
|
||||
}
|
||||
|
||||
return redirect()->route('models.index')
|
||||
->with('error', 'You must select at least one model to edit.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view that allows the user to bulk edit model attrbutes
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.7]
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function update(Request $request)
|
||||
{
|
||||
|
||||
$models_raw_array = Input::get('ids');
|
||||
$update_array = array();
|
||||
|
||||
if (($request->filled('manufacturer_id') && ($request->input('manufacturer_id')!='NC'))) {
|
||||
$update_array['manufacturer_id'] = $request->input('manufacturer_id');
|
||||
}
|
||||
if (($request->filled('category_id') && ($request->input('category_id')!='NC'))) {
|
||||
$update_array['category_id'] = $request->input('category_id');
|
||||
}
|
||||
if ($request->input('fieldset_id')!='NC') {
|
||||
$update_array['fieldset_id'] = $request->input('fieldset_id');
|
||||
}
|
||||
if ($request->input('depreciation_id')!='NC') {
|
||||
$update_array['depreciation_id'] = $request->input('depreciation_id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (count($update_array) > 0) {
|
||||
AssetModel::whereIn('id', $models_raw_array)->update($update_array);
|
||||
return redirect()->route('models.index')
|
||||
->with('success', trans('admin/models/message.bulkedit.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('models.index')
|
||||
->with('warning', trans('admin/models/message.bulkedit.error'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and delete the given Asset Models. An Asset Model
|
||||
* cannot be deleted if there are associated assets.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @return Redirect
|
||||
*/
|
||||
public function destroy()
|
||||
{
|
||||
$models_raw_array = Input::get('ids');
|
||||
|
||||
if ((is_array($models_raw_array)) && (count($models_raw_array) > 0)) {
|
||||
|
||||
$models = AssetModel::whereIn('id', $models_raw_array)->withCount('assets as assets_count')->get();
|
||||
|
||||
$del_error_count = 0;
|
||||
$del_count = 0;
|
||||
|
||||
foreach ($models as $model) {
|
||||
if ($model->assets_count > 0) {
|
||||
$del_error_count++;
|
||||
} else {
|
||||
$model->delete();
|
||||
$del_count++;
|
||||
}
|
||||
}
|
||||
|
||||
if ($del_error_count == 0) {
|
||||
return redirect()->route('models.index')
|
||||
->with('success', trans('admin/models/message.bulkdelete.success',['success_count'=> $del_count] ));
|
||||
}
|
||||
|
||||
return redirect()->route('models.index')
|
||||
->with('warning', trans('admin/models/message.bulkdelete.success_partial', ['fail_count'=>$del_error_count, 'success_count'=> $del_count]));
|
||||
}
|
||||
|
||||
return redirect()->route('models.index')
|
||||
->with('error', trans('admin/models/message.bulkdelete.error'));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -17,6 +17,7 @@ use Str;
|
|||
use View;
|
||||
use Image;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* This class controls all actions related to Categories for
|
||||
|
@ -29,13 +30,14 @@ class CategoriesController extends Controller
|
|||
{
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the categories listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see CategoriesController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the categories listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see CategoriesController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
@ -46,30 +48,32 @@ class CategoriesController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Returns a form view to create a new category.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see CategoriesController::store() method that stores the data
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a form view to create a new category.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see CategoriesController::store() method that stores the data
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
// Show the page
|
||||
$this->authorize('create', Category::class);
|
||||
$category_types= Helper::categoryTypeList();
|
||||
return view('categories/edit')->with('item', new Category)
|
||||
->with('category_types', $category_types);
|
||||
->with('category_types', Helper::categoryTypeList());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores the new category data.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see CategoriesController::create() method that makes the form.
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* Validates and stores the new category data.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see CategoriesController::create() method that makes the form.
|
||||
* @since [v1.0]
|
||||
* @param ImageUploadRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
|
@ -83,17 +87,7 @@ class CategoriesController extends Controller
|
|||
$category->checkin_email = $request->input('checkin_email', '0');
|
||||
$category->user_id = Auth::id();
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/categories/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$category->image = $file_name;
|
||||
}
|
||||
|
||||
$category = $request->handleImages($category);
|
||||
|
||||
if ($category->save()) {
|
||||
return redirect()->route('categories.index')->with('success', trans('admin/categories/message.create.success'));
|
||||
|
@ -103,13 +97,14 @@ class CategoriesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a view that makes a form to update a category.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see CategoriesController::postEdit() method saves the data
|
||||
* @param int $categoryId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a view that makes a form to update a category.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see CategoriesController::postEdit() method saves the data
|
||||
* @param int $categoryId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($categoryId = null)
|
||||
{
|
||||
|
@ -117,10 +112,8 @@ class CategoriesController extends Controller
|
|||
if (is_null($item = Category::find($categoryId))) {
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.does_not_exist'));
|
||||
}
|
||||
$category_types= Helper::categoryTypeList();
|
||||
|
||||
return view('categories/edit', compact('item'))
|
||||
->with('category_types', $category_types);
|
||||
->with('category_types', Helper::categoryTypeList());
|
||||
}
|
||||
|
||||
|
||||
|
@ -129,9 +122,10 @@ class CategoriesController extends Controller
|
|||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see CategoriesController::getEdit() method that makes the form.
|
||||
* @param Request $request
|
||||
* @param ImageUploadRequest $request
|
||||
* @param int $categoryId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $categoryId = null)
|
||||
|
@ -152,37 +146,7 @@ class CategoriesController extends Controller
|
|||
$category->require_acceptance = $request->input('require_acceptance', '0');
|
||||
$category->checkin_email = $request->input('checkin_email', '0');
|
||||
|
||||
$old_image = $category->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$category->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $category->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('categories_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('categories_upload_path'), $file_name);
|
||||
}
|
||||
$category->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('categories_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
}
|
||||
|
||||
$category = $request->handleImages($category);
|
||||
|
||||
if ($category->save()) {
|
||||
// Redirect to the new category page
|
||||
|
@ -193,31 +157,33 @@ class CategoriesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Validates and marks a category as deleted.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $categoryId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* Validates and marks a category as deleted.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $categoryId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($categoryId)
|
||||
{
|
||||
$this->authorize('delete', Category::class);
|
||||
// Check if the category exists
|
||||
if (is_null($category = Category::find($categoryId))) {
|
||||
if (is_null($category = Category::withCount('models as models_count', 'accessories as accessories_count','consumables as consumables_count','components as components_count')->findOrFail($categoryId))) {
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.not_found'));
|
||||
}
|
||||
|
||||
if ($category->has_models() > 0) {
|
||||
if ($category->models_count > 0) {
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'model']));
|
||||
} elseif ($category->accessories()->count() > 0) {
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory']));
|
||||
} elseif ($category->consumables()->count() > 0) {
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable']));
|
||||
} elseif ($category->components()->count() > 0) {
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'component']));
|
||||
} elseif ($category->accessories_count > 0) {
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'accessory']));
|
||||
} elseif ($category->consumables_count > 0) {
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'consumable']));
|
||||
} elseif ($category->components_count > 0) {
|
||||
return redirect()->route('categories.index')->with('error', trans('admin/categories/message.assoc_items', ['asset_type'=>'component']));
|
||||
}
|
||||
|
||||
Storage::disk('public')->delete('categories'.'/'.$category->image);
|
||||
$category->delete();
|
||||
// Redirect to the locations management page
|
||||
return redirect()->route('categories.index')->with('success', trans('admin/categories/message.delete.success'));
|
||||
|
@ -225,14 +191,15 @@ class CategoriesController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the categories detail view, which is generated in getDataView.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see CategoriesController::getDataView() method that generates the JSON response
|
||||
* @param int $categoryId
|
||||
* @since [v1.8]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the categories detail view, which is generated in getDataView.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see CategoriesController::getDataView() method that generates the JSON response
|
||||
* @param $id
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
|
@ -255,10 +222,8 @@ class CategoriesController extends Controller
|
|||
}
|
||||
|
||||
// Prepare the error message
|
||||
$error = trans('admin/categories/message.does_not_exist', compact('id'));
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('categories.index')->with('error', $error);
|
||||
return redirect()->route('categories.index')
|
||||
->with('error', trans('admin/categories/message.does_not_exist'));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
|
|
@ -4,6 +4,7 @@ namespace App\Http\Controllers;
|
|||
use App\Exceptions\CheckoutNotAllowed;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Location;
|
||||
use App\Models\SnipeModel;
|
||||
use App\Models\User;
|
||||
|
||||
trait CheckInOutRequest
|
||||
|
|
|
@ -2,13 +2,10 @@
|
|||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Models\Company;
|
||||
use Input;
|
||||
use Lang;
|
||||
use Redirect;
|
||||
use View;
|
||||
use Illuminate\Http\Request;
|
||||
use Image;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Companies for
|
||||
|
@ -21,11 +18,12 @@ final class CompaniesController extends Controller
|
|||
{
|
||||
|
||||
/**
|
||||
* Returns view to display listing of companies.
|
||||
*
|
||||
* @author [Abdullah Alansari] [<ahimta@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns view to display listing of companies.
|
||||
*
|
||||
* @author [Abdullah Alansari] [<ahimta@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
@ -35,11 +33,12 @@ final class CompaniesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns view to create a new company.
|
||||
*
|
||||
* @author [Abdullah Alansari] [<ahimta@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns view to create a new company.
|
||||
*
|
||||
* @author [Abdullah Alansari] [<ahimta@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
|
@ -55,6 +54,7 @@ final class CompaniesController extends Controller
|
|||
* @since [v1.8]
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
|
@ -63,16 +63,7 @@ final class CompaniesController extends Controller
|
|||
$company = new Company;
|
||||
$company->name = $request->input('name');
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/companies/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$company->image = $file_name;
|
||||
}
|
||||
$company = $request->handleImages($company);
|
||||
|
||||
if ($company->save()) {
|
||||
return redirect()->route('companies.index')
|
||||
|
@ -83,12 +74,13 @@ final class CompaniesController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Return form to edit existing company.
|
||||
*
|
||||
* @author [Abdullah Alansari] [<ahimta@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @param int $companyId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Return form to edit existing company.
|
||||
*
|
||||
* @author [Abdullah Alansari] [<ahimta@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @param int $companyId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($companyId)
|
||||
{
|
||||
|
@ -107,9 +99,10 @@ final class CompaniesController extends Controller
|
|||
*
|
||||
* @author [Abdullah Alansari] [<ahimta@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @param Request $request
|
||||
* @param ImageUploadRequest $request
|
||||
* @param int $companyId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $companyId)
|
||||
{
|
||||
|
@ -121,37 +114,7 @@ final class CompaniesController extends Controller
|
|||
|
||||
$company->name = $request->input('name');
|
||||
|
||||
$old_image = $company->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$company->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $company->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('companies_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('companies_upload_path'), $file_name);
|
||||
}
|
||||
$company->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('companies_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
}
|
||||
|
||||
$company = $request->handleImages($company);
|
||||
|
||||
if ($company->save()) {
|
||||
return redirect()->route('companies.index')
|
||||
|
@ -162,38 +125,47 @@ final class CompaniesController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Delete company
|
||||
*
|
||||
* @author [Abdullah Alansari] [<ahimta@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @param int $companyId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* Delete company
|
||||
*
|
||||
* @author [Abdullah Alansari] [<ahimta@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @param int $companyId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($companyId)
|
||||
{
|
||||
$this->authorize('delete', $company);
|
||||
|
||||
if (is_null($company = Company::find($companyId))) {
|
||||
return redirect()->route('companies.index')
|
||||
->with('error', trans('admin/companies/message.not_found'));
|
||||
} else {
|
||||
}
|
||||
|
||||
$this->authorize('delete', $company);
|
||||
try {
|
||||
|
||||
try {
|
||||
$company->delete();
|
||||
return redirect()->route('companies.index')
|
||||
->with('success', trans('admin/companies/message.delete.success'));
|
||||
} catch (\Illuminate\Database\QueryException $exception) {
|
||||
/*
|
||||
* NOTE: This happens when there's a foreign key constraint violation
|
||||
* For example when rows in other tables are referencing this company
|
||||
*/
|
||||
if ($exception->getCode() == 23000) {
|
||||
return redirect()->route('companies.index')
|
||||
->with('error', trans('admin/companies/message.assoc_users'));
|
||||
} else {
|
||||
throw $exception;
|
||||
if ($company->image) {
|
||||
try {
|
||||
Storage::disk('public')->delete('companies'.'/'.$company->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$company->delete();
|
||||
return redirect()->route('companies.index')
|
||||
->with('success', trans('admin/companies/message.delete.success'));
|
||||
} catch (\Illuminate\Database\QueryException $exception) {
|
||||
/*
|
||||
* NOTE: This happens when there's a foreign key constraint violation
|
||||
* For example when rows in other tables are referencing this company
|
||||
*/
|
||||
if ($exception->getCode() == 23000) {
|
||||
return redirect()->route('companies.index')
|
||||
->with('error', trans('admin/companies/message.assoc_users'));
|
||||
}
|
||||
|
||||
throw $exception;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -203,9 +175,8 @@ final class CompaniesController extends Controller
|
|||
if (is_null($company = Company::find($id))) {
|
||||
return redirect()->route('companies.index')
|
||||
->with('error', trans('admin/companies/message.not_found'));
|
||||
} else {
|
||||
return view('companies/view')->with('company',$company);
|
||||
}
|
||||
|
||||
return view('companies/view')->with('company',$company);
|
||||
}
|
||||
}
|
||||
|
|
108
app/Http/Controllers/Components/ComponentCheckinController.php
Normal file
108
app/Http/Controllers/Components/ComponentCheckinController.php
Normal file
|
@ -0,0 +1,108 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Components;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Events\ComponentCheckedIn;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Component;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class ComponentCheckinController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns a view that allows the checkin of a component from an asset.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentCheckinController::store() method that stores the data.
|
||||
* @since [v4.1.4]
|
||||
* @param $component_asset_id
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($component_asset_id)
|
||||
{
|
||||
|
||||
// This could probably be done more cleanly but I am very tired. - @snipe
|
||||
if ($component_assets = DB::table('components_assets')->find($component_asset_id)) {
|
||||
if (is_null($component = Component::find($component_assets->component_id))) {
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found'));
|
||||
}
|
||||
if (is_null($asset = Asset::find($component_assets->asset_id))) {
|
||||
return redirect()->route('components.index')->with('error',
|
||||
trans('admin/components/message.not_found'));
|
||||
}
|
||||
$this->authorize('checkin', $component);
|
||||
return view('components/checkin', compact('component_assets','component','asset'));
|
||||
}
|
||||
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate and store checkin data.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentCheckinController::create() method that returns the form.
|
||||
* @since [v4.1.4]
|
||||
* @param Request $request
|
||||
* @param $component_asset_id
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(Request $request, $component_asset_id)
|
||||
{
|
||||
if ($component_assets = DB::table('components_assets')->find($component_asset_id)) {
|
||||
if (is_null($component = Component::find($component_assets->component_id))) {
|
||||
return redirect()->route('components.index')->with('error',
|
||||
trans('admin/components/message.not_found'));
|
||||
}
|
||||
|
||||
|
||||
$this->authorize('checkin', $component);
|
||||
|
||||
$max_to_checkin = $component_assets->assigned_qty;
|
||||
$validator = Validator::make($request->all(), [
|
||||
"checkin_qty" => "required|numeric|between:1,$max_to_checkin"
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return redirect()->back()
|
||||
->withErrors($validator)
|
||||
->withInput();
|
||||
}
|
||||
|
||||
// Validation passed, so let's figure out what we have to do here.
|
||||
$qty_remaining_in_checkout = ($component_assets->assigned_qty - (int)$request->input('checkin_qty'));
|
||||
|
||||
// We have to modify the record to reflect the new qty that's
|
||||
// actually checked out.
|
||||
$component_assets->assigned_qty = $qty_remaining_in_checkout;
|
||||
DB::table('components_assets')->where('id',
|
||||
$component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]);
|
||||
|
||||
// If the checked-in qty is exactly the same as the assigned_qty,
|
||||
// we can simply delete the associated components_assets record
|
||||
if ($qty_remaining_in_checkout == 0) {
|
||||
DB::table('components_assets')->where('id', '=', $component_asset_id)->delete();
|
||||
}
|
||||
|
||||
$asset = Asset::find($component_assets->asset_id);
|
||||
|
||||
event(new CheckoutableCheckedIn($component, $asset, Auth::user(), $request->input('note')));
|
||||
|
||||
return redirect()->route('components.index')->with('success',
|
||||
trans('admin/components/message.checkout.success'));
|
||||
}
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found'));
|
||||
}
|
||||
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Components;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Events\ComponentCheckedOut;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Component;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class ComponentCheckoutController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns a view that allows the checkout of a component to an asset.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentCheckoutController::store() method that stores the data.
|
||||
* @since [v3.0]
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($componentId)
|
||||
{
|
||||
// Check if the component exists
|
||||
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'));
|
||||
}
|
||||
$this->authorize('checkout', $component);
|
||||
return view('components/checkout', compact('component'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and store checkout data.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentCheckoutController::create() method that returns the form.
|
||||
* @since [v3.0]
|
||||
* @param Request $request
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(Request $request, $componentId)
|
||||
{
|
||||
// Check if the component exists
|
||||
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'));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $component);
|
||||
|
||||
$max_to_checkout = $component->numRemaining();
|
||||
$validator = Validator::make($request->all(), [
|
||||
"asset_id" => "required",
|
||||
"assigned_qty" => "required|numeric|between:1,$max_to_checkout"
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return redirect()->back()
|
||||
->withErrors($validator)
|
||||
->withInput();
|
||||
}
|
||||
|
||||
$admin_user = Auth::user();
|
||||
$asset_id = e(Input::get('asset_id'));
|
||||
|
||||
// Check if the user exists
|
||||
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 = $asset_id;
|
||||
|
||||
$component->assets()->attach($component->id, [
|
||||
'component_id' => $component->id,
|
||||
'user_id' => $admin_user->id,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'assigned_qty' => Input::get('assigned_qty'),
|
||||
'asset_id' => $asset_id
|
||||
]);
|
||||
|
||||
event(new CheckoutableCheckedOut($component, $asset, Auth::user(), $request->input('note')));
|
||||
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success'));
|
||||
}
|
||||
}
|
199
app/Http/Controllers/Components/ComponentsController.php
Normal file
199
app/Http/Controllers/Components/ComponentsController.php
Normal file
|
@ -0,0 +1,199 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers\Components;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Company;
|
||||
use App\Models\Component;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* This class controls all actions related to Components for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class ComponentsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the components listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::getDatatable() method that generates the JSON response
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('view', Component::class);
|
||||
return view('components/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a form to create a new component.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::postCreate() method that stores the data
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', Component::class);
|
||||
return view('components/edit')->with('category_type', 'component')
|
||||
->with('item', new Component);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate and store data for new component.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::getCreate() method that generates the view
|
||||
* @since [v3.0]
|
||||
* @param ImageUploadRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize('create', Component::class);
|
||||
$component = new Component();
|
||||
$component->name = $request->input('name');
|
||||
$component->category_id = $request->input('category_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->qty = $request->input('qty');
|
||||
$component->user_id = Auth::id();
|
||||
|
||||
$component = $request->handleImages($component);
|
||||
|
||||
if ($component->save()) {
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.create.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($component->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a view to edit a component.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::postEdit() method that stores the data.
|
||||
* @since [v3.0]
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($componentId = null)
|
||||
{
|
||||
if ($item = Component::find($componentId)) {
|
||||
$this->authorize('update', $item);
|
||||
return view('components/edit', compact('item'))->with('category_type', 'component');
|
||||
}
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a view to edit a component.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::getEdit() method presents the form.
|
||||
* @param ImageUploadRequest $request
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v3.0]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $componentId = null)
|
||||
{
|
||||
if (is_null($component = Component::find($componentId))) {
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $component);
|
||||
|
||||
// Update the component data
|
||||
$component->name = Input::get('name');
|
||||
$component->category_id = Input::get('category_id');
|
||||
$component->location_id = Input::get('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
|
||||
$component->order_number = Input::get('order_number');
|
||||
$component->min_amt = Input::get('min_amt');
|
||||
$component->serial = Input::get('serial');
|
||||
$component->purchase_date = Input::get('purchase_date');
|
||||
$component->purchase_cost = request('purchase_cost');
|
||||
$component->qty = Input::get('qty');
|
||||
|
||||
$component = $request->handleImages($component);
|
||||
|
||||
if ($component->save()) {
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.update.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($component->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a component.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($componentId)
|
||||
{
|
||||
if (is_null($component = Component::find($componentId))) {
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('delete', $component);
|
||||
|
||||
// Remove the image if one exists
|
||||
if (Storage::disk('public')->exists('components/'.$component->image)) {
|
||||
try {
|
||||
Storage::disk('public')->delete('components/'.$component->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$component->delete();
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.delete.success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a view to display component information.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::getDataView() method that generates the JSON response
|
||||
* @since [v3.0]
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($componentId = null)
|
||||
{
|
||||
$component = Component::find($componentId);
|
||||
|
||||
if (isset($component->id)) {
|
||||
$this->authorize('view', $component);
|
||||
return view('components/view', compact('component'));
|
||||
}
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('components.index')
|
||||
->with('error', trans('admin/components/message.does_not_exist'));
|
||||
}
|
||||
}
|
|
@ -1,397 +0,0 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Company;
|
||||
use App\Models\Component;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Models\Asset;
|
||||
use Auth;
|
||||
use Config;
|
||||
use DB;
|
||||
use Input;
|
||||
use Lang;
|
||||
use Mail;
|
||||
use Redirect;
|
||||
use Slack;
|
||||
use Str;
|
||||
use View;
|
||||
use Validator;
|
||||
use Illuminate\Http\Request;
|
||||
use Gate;
|
||||
use Image;
|
||||
|
||||
/**
|
||||
* This class controls all actions related to Components for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class ComponentsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the components listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::getDatatable() method that generates the JSON response
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('view', Component::class);
|
||||
return view('components/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a form to create a new component.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::postCreate() method that stores the data
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', Component::class);
|
||||
$category_type = 'component';
|
||||
return view('components/edit')->with('category_type',$category_type)
|
||||
->with('item', new Component);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate and store data for new component.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::getCreate() method that generates the view
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize('create', Component::class);
|
||||
$component = new Component();
|
||||
$component->name = $request->input('name');
|
||||
$component->category_id = $request->input('category_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->qty = $request->input('qty');
|
||||
$component->user_id = Auth::id();
|
||||
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/components/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$component->image = $file_name;
|
||||
}
|
||||
|
||||
if ($component->save()) {
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.create.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($component->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a view to edit a component.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::postEdit() method that stores the data.
|
||||
* @since [v3.0]
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit($componentId = null)
|
||||
{
|
||||
|
||||
|
||||
if ($item = Component::find($componentId)) {
|
||||
$this->authorize('update', $item);
|
||||
$category_type = 'component';
|
||||
return view('components/edit', compact('item'))->with('category_type', $category_type);
|
||||
}
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
|
||||
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a view to edit a component.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::getEdit() method presents the form.
|
||||
* @param int $componentId
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $componentId = null)
|
||||
{
|
||||
if (is_null($component = Component::find($componentId))) {
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $component);
|
||||
|
||||
|
||||
// Update the component data
|
||||
$component->name = Input::get('name');
|
||||
$component->category_id = Input::get('category_id');
|
||||
$component->location_id = Input::get('location_id');
|
||||
$component->company_id = Company::getIdForCurrentUser(Input::get('company_id'));
|
||||
$component->order_number = Input::get('order_number');
|
||||
$component->min_amt = Input::get('min_amt');
|
||||
$component->serial = Input::get('serial');
|
||||
$component->purchase_date = Input::get('purchase_date');
|
||||
$component->purchase_cost = request('purchase_cost');
|
||||
$component->qty = Input::get('qty');
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/components/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$component->image = $file_name;
|
||||
} elseif ($request->input('image_delete')=='1') {
|
||||
$component->image = null;
|
||||
}
|
||||
|
||||
if ($component->save()) {
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.update.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($component->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a component.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy($componentId)
|
||||
{
|
||||
if (is_null($component = Component::find($componentId))) {
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('delete', $component);
|
||||
$component->delete();
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.delete.success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a view to display component information.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::getDataView() method that generates the JSON response
|
||||
* @since [v3.0]
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show($componentId = null)
|
||||
{
|
||||
$component = Component::find($componentId);
|
||||
|
||||
if (isset($component->id)) {
|
||||
$this->authorize('view', $component);
|
||||
return view('components/view', compact('component'));
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/components/message.does_not_exist', compact('id'));
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('components.index')->with('error', $error);
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view that allows the checkout of a component to an asset.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::postCheckout() method that stores the data.
|
||||
* @since [v3.0]
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function getCheckout($componentId)
|
||||
{
|
||||
// Check if the component exists
|
||||
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'));
|
||||
}
|
||||
$this->authorize('checkout', $component);
|
||||
return view('components/checkout', compact('component'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and store checkout data.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::getCheckout() method that returns the form.
|
||||
* @since [v3.0]
|
||||
* @param Request $request
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postCheckout(Request $request, $componentId)
|
||||
{
|
||||
// Check if the component exists
|
||||
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'));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $component);
|
||||
|
||||
$max_to_checkout = $component->numRemaining();
|
||||
$validator = Validator::make($request->all(), [
|
||||
"asset_id" => "required",
|
||||
"assigned_qty" => "required|numeric|between:1,$max_to_checkout"
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return redirect()->back()
|
||||
->withErrors($validator)
|
||||
->withInput();
|
||||
}
|
||||
|
||||
$admin_user = Auth::user();
|
||||
$asset_id = e(Input::get('asset_id'));
|
||||
|
||||
// Check if the user exists
|
||||
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 = $asset_id;
|
||||
|
||||
$component->assets()->attach($component->id, [
|
||||
'component_id' => $component->id,
|
||||
'user_id' => $admin_user->id,
|
||||
'created_at' => date('Y-m-d H:i:s'),
|
||||
'assigned_qty' => Input::get('assigned_qty'),
|
||||
'asset_id' => $asset_id
|
||||
]);
|
||||
|
||||
$component->logCheckout(e(Input::get('note')), $asset);
|
||||
return redirect()->route('components.index')->with('success', trans('admin/components/message.checkout.success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a view that allows the checkin of a component from an asset.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::postCheckout() method that stores the data.
|
||||
* @since [v4.1.4]
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function getCheckin($component_asset_id)
|
||||
{
|
||||
|
||||
// This could probably be done more cleanly but I am very tired. - @snipe
|
||||
if ($component_assets = DB::table('components_assets')->find($component_asset_id)) {
|
||||
if (is_null($component = Component::find($component_assets->component_id))) {
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found'));
|
||||
}
|
||||
if (is_null($asset = Asset::find($component_assets->asset_id))) {
|
||||
return redirect()->route('components.index')->with('error',
|
||||
trans('admin/components/message.not_found'));
|
||||
}
|
||||
$this->authorize('checkin', $component);
|
||||
return view('components/checkin', compact('component_assets','component','asset'));
|
||||
}
|
||||
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/messages.not_found'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Validate and store checkin data.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ComponentsController::getCheckout() method that returns the form.
|
||||
* @since [v4.1.4]
|
||||
* @param Request $request
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postCheckin(Request $request, $component_asset_id)
|
||||
{
|
||||
if ($component_assets = DB::table('components_assets')->find($component_asset_id)) {
|
||||
if (is_null($component = Component::find($component_assets->component_id))) {
|
||||
return redirect()->route('components.index')->with('error',
|
||||
trans('admin/components/message.not_found'));
|
||||
}
|
||||
|
||||
|
||||
$this->authorize('checkin', $component);
|
||||
|
||||
$max_to_checkin = $component_assets->assigned_qty;
|
||||
$validator = Validator::make($request->all(), [
|
||||
"checkin_qty" => "required|numeric|between:1,$max_to_checkin"
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return redirect()->back()
|
||||
->withErrors($validator)
|
||||
->withInput();
|
||||
}
|
||||
|
||||
// Validation passed, so let's figure out what we have to do here.
|
||||
$qty_remaining_in_checkout = ($component_assets->assigned_qty - (int)$request->input('checkin_qty'));
|
||||
|
||||
// We have to modify the record to reflect the new qty that's
|
||||
// actually checked out.
|
||||
$component_assets->assigned_qty = $qty_remaining_in_checkout;
|
||||
DB::table('components_assets')->where('id',
|
||||
$component_asset_id)->update(['assigned_qty' => $qty_remaining_in_checkout]);
|
||||
|
||||
$log = new Actionlog();
|
||||
$log->user_id = Auth::user()->id;
|
||||
$log->action_type = 'checkin from';
|
||||
$log->target_type = Asset::class;
|
||||
$log->target_id = $component_assets->asset_id;
|
||||
$log->item_id = $component_assets->component_id;
|
||||
$log->item_type = Component::class;
|
||||
$log->note = $request->input('note');
|
||||
$log->save();
|
||||
|
||||
// If the checked-in qty is exactly the same as the assigned_qty,
|
||||
// we can simply delete the associated components_assets record
|
||||
if ($qty_remaining_in_checkout == 0) {
|
||||
DB::table('components_assets')->where('id', '=', $component_asset_id)->delete();
|
||||
}
|
||||
|
||||
return redirect()->route('components.index')->with('success',
|
||||
trans('admin/components/message.checkout.success'));
|
||||
}
|
||||
return redirect()->route('components.index')->with('error', trans('admin/components/message.not_found'));
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -0,0 +1,77 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Consumables;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
|
||||
class ConsumableCheckoutController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Return a view to checkout a consumable to a user.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumableCheckoutController::store() method that stores the data.
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($consumableId)
|
||||
{
|
||||
if (is_null($consumable = Consumable::find($consumableId))) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
}
|
||||
$this->authorize('checkout', $consumable);
|
||||
return view('consumables/checkout', compact('consumable'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the checkout information
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumableCheckoutController::create() method that returns the form.
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(Request $request, $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);
|
||||
|
||||
$admin_user = Auth::user();
|
||||
$assigned_to = e(Input::get('assigned_to'));
|
||||
|
||||
// Check if the user exists
|
||||
if (is_null($user = User::find($assigned_to))) {
|
||||
// Redirect to the consumable management page with error
|
||||
return redirect()->route('checkout/consumable', $consumable)->with('error', trans('admin/consumables/message.checkout.user_does_not_exist'));
|
||||
}
|
||||
|
||||
// Update the consumable data
|
||||
$consumable->assigned_to = e(Input::get('assigned_to'));
|
||||
|
||||
$consumable->users()->attach($consumable->id, [
|
||||
'consumable_id' => $consumable->id,
|
||||
'user_id' => $admin_user->id,
|
||||
'assigned_to' => e(Input::get('assigned_to'))
|
||||
]);
|
||||
|
||||
event(new CheckoutableCheckedOut($consumable, $user, Auth::user(), $request->input('note')));
|
||||
|
||||
// Redirect to the new consumable page
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.checkout.success'));
|
||||
|
||||
}
|
||||
}
|
197
app/Http/Controllers/Consumables/ConsumablesController.php
Normal file
197
app/Http/Controllers/Consumables/ConsumablesController.php
Normal file
|
@ -0,0 +1,197 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Consumables;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Company;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Consumables for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class ConsumablesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Return a view to display component information.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('index', Consumable::class);
|
||||
return view('consumables/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a view to display the form view to create a new consumable
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::postCreate() method that stores the form data
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', Consumable::class);
|
||||
return view('consumables/edit')->with('category_type', 'consumable')
|
||||
->with('item', new Consumable);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate and store new consumable data.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::getCreate() method that returns the form view
|
||||
* @since [v1.0]
|
||||
* @param ImageUploadRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize('create', Consumable::class);
|
||||
$consumable = new Consumable();
|
||||
$consumable->name = $request->input('name');
|
||||
$consumable->category_id = $request->input('category_id');
|
||||
$consumable->location_id = $request->input('location_id');
|
||||
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$consumable->order_number = $request->input('order_number');
|
||||
$consumable->min_amt = $request->input('min_amt');
|
||||
$consumable->manufacturer_id = $request->input('manufacturer_id');
|
||||
$consumable->model_number = $request->input('model_number');
|
||||
$consumable->item_no = $request->input('item_no');
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = Helper::ParseFloat($request->input('purchase_cost'));
|
||||
$consumable->qty = $request->input('qty');
|
||||
$consumable->user_id = Auth::id();
|
||||
|
||||
|
||||
$consumable = $request->handleImages($consumable);
|
||||
|
||||
if ($consumable->save()) {
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.create.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($consumable->getErrors());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a form view to edit a consumable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $consumableId
|
||||
* @see ConsumablesController::postEdit() method that stores the form data.
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($consumableId = null)
|
||||
{
|
||||
if ($item = Consumable::find($consumableId)) {
|
||||
$this->authorize($item);
|
||||
return view('consumables/edit', compact('item'))->with('category_type', 'consumable');
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a form view to edit a consumable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param ImageUploadRequest $request
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @see ConsumablesController::getEdit() method that stores the form data.
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $consumableId = null)
|
||||
{
|
||||
if (is_null($consumable = Consumable::find($consumableId))) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize($consumable);
|
||||
|
||||
$consumable->name = $request->input('name');
|
||||
$consumable->category_id = $request->input('category_id');
|
||||
$consumable->location_id = $request->input('location_id');
|
||||
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$consumable->order_number = $request->input('order_number');
|
||||
$consumable->min_amt = $request->input('min_amt');
|
||||
$consumable->manufacturer_id = $request->input('manufacturer_id');
|
||||
$consumable->model_number = $request->input('model_number');
|
||||
$consumable->item_no = $request->input('item_no');
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = Helper::ParseFloat(Input::get('purchase_cost'));
|
||||
$consumable->qty = Helper::ParseFloat(Input::get('qty'));
|
||||
|
||||
$consumable = $request->handleImages($consumable);
|
||||
|
||||
if ($consumable->save()) {
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.update.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($consumable->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a consumable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $consumableId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($consumableId)
|
||||
{
|
||||
if (is_null($consumable = Consumable::find($consumableId))) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
|
||||
}
|
||||
$this->authorize($consumable);
|
||||
$consumable->delete();
|
||||
// Redirect to the locations management page
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.delete.success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a view to display component information.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::getDataView() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($consumableId = null)
|
||||
{
|
||||
$consumable = Consumable::find($consumableId);
|
||||
$this->authorize($consumable);
|
||||
if (isset($consumable->id)) {
|
||||
return view('consumables/view', compact('consumable'));
|
||||
}
|
||||
return redirect()->route('consumables.index')
|
||||
->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
}
|
||||
|
||||
}
|
|
@ -1,286 +0,0 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Company;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Auth;
|
||||
use Config;
|
||||
use DB;
|
||||
use Input;
|
||||
use Lang;
|
||||
use Redirect;
|
||||
use Slack;
|
||||
use Str;
|
||||
use View;
|
||||
use Gate;
|
||||
use Image;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Consumables for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class ConsumablesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Return a view to display component information.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('index', Consumable::class);
|
||||
return view('consumables/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Return a view to display the form view to create a new consumable
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::postCreate() method that stores the form data
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', Consumable::class);
|
||||
$category_type = 'consumable';
|
||||
return view('consumables/edit')->with('category_type', $category_type)
|
||||
->with('item', new Consumable);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validate and store new consumable data.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::getCreate() method that returns the form view
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize('create', Consumable::class);
|
||||
$consumable = new Consumable();
|
||||
$consumable->name = $request->input('name');
|
||||
$consumable->category_id = $request->input('category_id');
|
||||
$consumable->location_id = $request->input('location_id');
|
||||
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$consumable->order_number = $request->input('order_number');
|
||||
$consumable->min_amt = $request->input('min_amt');
|
||||
$consumable->manufacturer_id = $request->input('manufacturer_id');
|
||||
$consumable->model_number = $request->input('model_number');
|
||||
$consumable->item_no = $request->input('item_no');
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = Helper::ParseFloat($request->input('purchase_cost'));
|
||||
$consumable->qty = $request->input('qty');
|
||||
$consumable->user_id = Auth::id();
|
||||
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/consumables/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$consumable->image = $file_name;
|
||||
}
|
||||
|
||||
if ($consumable->save()) {
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.create.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($consumable->getErrors());
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a form view to edit a consumable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $consumableId
|
||||
* @see ConsumablesController::postEdit() method that stores the form data.
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit($consumableId = null)
|
||||
{
|
||||
if ($item = Consumable::find($consumableId)) {
|
||||
$this->authorize($item);
|
||||
$category_type = 'consumable';
|
||||
return view('consumables/edit', compact('item'))->with('category_type', $category_type);
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a form view to edit a consumable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $consumableId
|
||||
* @see ConsumablesController::getEdit() method that stores the form data.
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $consumableId = null)
|
||||
{
|
||||
if (is_null($consumable = Consumable::find($consumableId))) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize($consumable);
|
||||
|
||||
$consumable->name = $request->input('name');
|
||||
$consumable->category_id = $request->input('category_id');
|
||||
$consumable->location_id = $request->input('location_id');
|
||||
$consumable->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$consumable->order_number = $request->input('order_number');
|
||||
$consumable->min_amt = $request->input('min_amt');
|
||||
$consumable->manufacturer_id = $request->input('manufacturer_id');
|
||||
$consumable->model_number = $request->input('model_number');
|
||||
$consumable->item_no = $request->input('item_no');
|
||||
$consumable->purchase_date = $request->input('purchase_date');
|
||||
$consumable->purchase_cost = Helper::ParseFloat(Input::get('purchase_cost'));
|
||||
$consumable->qty = Helper::ParseFloat(Input::get('qty'));
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/consumables/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$consumable->image = $file_name;
|
||||
} elseif ($request->input('image_delete')=='1') {
|
||||
$consumable->image = null;
|
||||
}
|
||||
|
||||
if ($consumable->save()) {
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.update.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($consumable->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a consumable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $consumableId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy($consumableId)
|
||||
{
|
||||
if (is_null($consumable = Consumable::find($consumableId))) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.not_found'));
|
||||
}
|
||||
$this->authorize($consumable);
|
||||
$consumable->delete();
|
||||
// Redirect to the locations management page
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.delete.success'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a view to display component information.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::getDataView() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show($consumableId = null)
|
||||
{
|
||||
$consumable = Consumable::find($consumableId);
|
||||
$this->authorize($consumable);
|
||||
if (isset($consumable->id)) {
|
||||
return view('consumables/view', compact('consumable'));
|
||||
}
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist', compact('id')));
|
||||
}
|
||||
|
||||
/**
|
||||
* Return a view to checkout a consumable to a user.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::postCheckout() method that stores the data.
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function getCheckout($consumableId)
|
||||
{
|
||||
if (is_null($consumable = Consumable::find($consumableId))) {
|
||||
return redirect()->route('consumables.index')->with('error', trans('admin/consumables/message.does_not_exist'));
|
||||
}
|
||||
$this->authorize('checkout', $consumable);
|
||||
return view('consumables/checkout', compact('consumable'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Saves the checkout information
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ConsumablesController::getCheckout() method that returns the form.
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postCheckout($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);
|
||||
|
||||
$admin_user = Auth::user();
|
||||
$assigned_to = e(Input::get('assigned_to'));
|
||||
|
||||
// Check if the user exists
|
||||
if (is_null($user = User::find($assigned_to))) {
|
||||
// Redirect to the consumable management page with error
|
||||
return redirect()->route('checkout/consumable', $consumable)->with('error', trans('admin/consumables/message.checkout.user_does_not_exist'));
|
||||
}
|
||||
|
||||
// Update the consumable data
|
||||
$consumable->assigned_to = e(Input::get('assigned_to'));
|
||||
|
||||
$consumable->users()->attach($consumable->id, [
|
||||
'consumable_id' => $consumable->id,
|
||||
'user_id' => $admin_user->id,
|
||||
'assigned_to' => e(Input::get('assigned_to'))
|
||||
]);
|
||||
|
||||
$logaction = $consumable->logCheckout(e(Input::get('note')), $user);
|
||||
$data['log_id'] = $logaction->id;
|
||||
$data['eula'] = $consumable->getEula();
|
||||
$data['first_name'] = $user->first_name;
|
||||
$data['item_name'] = $consumable->name;
|
||||
$data['checkout_date'] = $logaction->created_at;
|
||||
$data['note'] = $logaction->note;
|
||||
$data['require_acceptance'] = $consumable->requireAcceptance();
|
||||
|
||||
|
||||
// Redirect to the new consumable page
|
||||
return redirect()->route('consumables.index')->with('success', trans('admin/consumables/message.checkout.success'));
|
||||
|
||||
}
|
||||
|
||||
}
|
|
@ -1,19 +1,14 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\CustomFieldRequest;
|
||||
use View;
|
||||
use App\Models\CustomFieldset;
|
||||
use App\Models\CustomField;
|
||||
use Input;
|
||||
use Validator;
|
||||
use Redirect;
|
||||
use App\Models\AssetModel;
|
||||
use Lang;
|
||||
use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Helpers\Helper;
|
||||
use Log;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CustomFieldset;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use App\Http\Requests\CustomFieldRequest;
|
||||
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Custom Asset Fields for
|
||||
|
@ -29,49 +24,53 @@ class CustomFieldsController extends Controller
|
|||
{
|
||||
|
||||
/**
|
||||
* Returns a view with a listing of custom fields.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
* Returns a view with a listing of custom fields.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return \Illuminate\Support\Facades\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('view', CustomField::class);
|
||||
|
||||
$fieldsets = CustomFieldset::with("fields", "models")->get();
|
||||
$fields = CustomField::with("fieldset")->get();
|
||||
|
||||
return view("custom_fields.index")->with("custom_fieldsets", $fieldsets)->with("custom_fields", $fields);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view with a form to create a new custom field.
|
||||
*
|
||||
* @see CustomFieldsController::storeField()
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
* Returns a view with a form to create a new custom field.
|
||||
*
|
||||
* @see CustomFieldsController::storeField()
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return \Illuminate\Support\Facades\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', CustomField::class);
|
||||
|
||||
return view("custom_fields.fields.edit")->with('field', new CustomField());
|
||||
return view("custom_fields.fields.edit",[
|
||||
'predefinedFormats' => Helper::predefined_formats(),
|
||||
'customFormat' => ''
|
||||
])->with('field', new CustomField());
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores a new custom field.
|
||||
*
|
||||
* @see CustomFieldsController::createField()
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return Redirect
|
||||
*/
|
||||
* Validates and stores a new custom field.
|
||||
*
|
||||
* @see CustomFieldsController::createField()
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(CustomFieldRequest $request)
|
||||
{
|
||||
$this->authorize('create', CustomField::class);
|
||||
|
@ -83,22 +82,24 @@ class CustomFieldsController extends Controller
|
|||
"field_values" => $request->get("field_values"),
|
||||
"field_encrypted" => $request->get("field_encrypted", 0),
|
||||
"show_in_email" => $request->get("show_in_email", 0),
|
||||
"user_id" => Auth::user()->id
|
||||
"user_id" => Auth::id()
|
||||
]);
|
||||
|
||||
|
||||
if ($request->has("custom_format")) {
|
||||
if ($request->filled("custom_format")) {
|
||||
$field->format = e($request->get("custom_format"));
|
||||
} else {
|
||||
$field->format = e($request->get("format"));
|
||||
}
|
||||
|
||||
if ($field->save()) {
|
||||
|
||||
return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.field.create.success'));
|
||||
} else {
|
||||
return redirect()->back()->withInput()->with('error', trans('admin/custom_fields/message.field.create.error'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()
|
||||
->with('error', trans('admin/custom_fields/message.field.create.error'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
@ -108,6 +109,7 @@ class CustomFieldsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function deleteFieldFromFieldset($field_id, $fieldset_id)
|
||||
{
|
||||
|
@ -116,19 +118,21 @@ class CustomFieldsController extends Controller
|
|||
$this->authorize('update', $field);
|
||||
|
||||
if ($field->fieldset()->detach($fieldset_id)) {
|
||||
return redirect()->route('fieldsets.show', ['fieldset' => $fieldset_id])->with("success", trans('admin/custom_fields/message.field.delete.success'));
|
||||
return redirect()->route('fieldsets.show', ['fieldset' => $fieldset_id])
|
||||
->with("success", trans('admin/custom_fields/message.field.delete.success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withErrors(['message' => "Field is in-use"]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete a custom field.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return Redirect
|
||||
*/
|
||||
* Delete a custom field.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($field_id)
|
||||
{
|
||||
$field = CustomField::find($field_id);
|
||||
|
@ -137,56 +141,66 @@ class CustomFieldsController extends Controller
|
|||
|
||||
if ($field->fieldset->count()>0) {
|
||||
return redirect()->back()->withErrors(['message' => "Field is in-use"]);
|
||||
} else {
|
||||
$field->delete();
|
||||
return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.field.delete.success'));
|
||||
}
|
||||
$field->delete();
|
||||
return redirect()->route("fields.index")
|
||||
->with("success", trans('admin/custom_fields/message.field.delete.success'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Return a view to edit a custom field
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $id
|
||||
* @since [v4.0]
|
||||
* @return View
|
||||
*/
|
||||
* Return a view to edit a custom field
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $id
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Support\Facades\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($id)
|
||||
{
|
||||
$field = CustomField::find($id);
|
||||
|
||||
$this->authorize('update', $field);
|
||||
|
||||
return view("custom_fields.fields.edit")->with('field', $field);
|
||||
$customFormat = '';
|
||||
if((stripos($field->format, 'regex') === 0) && ($field->format !== CustomField::PREDEFINED_FORMATS['MAC'])) {
|
||||
$customFormat = $field->format;
|
||||
}
|
||||
|
||||
return view("custom_fields.fields.edit",[
|
||||
'field' => $field,
|
||||
'customFormat' => $customFormat,
|
||||
'predefinedFormats' => Helper::predefined_formats()
|
||||
]);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Store the updated field
|
||||
*
|
||||
* @todo Allow encrypting/decrypting if encryption status changes
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $id
|
||||
* @since [v4.0]
|
||||
* @return Redirect
|
||||
*/
|
||||
* Store the updated field
|
||||
*
|
||||
* @todo Allow encrypting/decrypting if encryption status changes
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $id
|
||||
* @since [v4.0]
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(CustomFieldRequest $request, $id)
|
||||
{
|
||||
$field = CustomField::find($id);
|
||||
|
||||
|
||||
$this->authorize('update', $field);
|
||||
|
||||
$field->name = e($request->get("name"));
|
||||
$field->element = e($request->get("element"));
|
||||
$field->field_values = e($request->get("field_values"));
|
||||
$field->user_id = Auth::user()->id;
|
||||
$field->help_text = $request->get("help_text");
|
||||
$field->name = e($request->get("name"));
|
||||
$field->element = e($request->get("element"));
|
||||
$field->field_values = e($request->get("field_values"));
|
||||
$field->user_id = Auth::id();
|
||||
$field->help_text = $request->get("help_text");
|
||||
$field->show_in_email = $request->get("show_in_email", 0);
|
||||
|
||||
if (!in_array(Input::get('format'), array_keys(CustomField::$PredefinedFormats))) {
|
||||
if ($request->get('format') == 'CUSTOM REGEX') {
|
||||
$field->format = e($request->get("custom_format"));
|
||||
} else {
|
||||
$field->format = e($request->get("format"));
|
||||
|
|
|
@ -1,17 +1,14 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use View;
|
||||
use App\Models\CustomFieldset;
|
||||
use App\Models\CustomField;
|
||||
use Input;
|
||||
use Validator;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Redirect;
|
||||
use App\Models\AssetModel;
|
||||
use Lang;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use Log;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Custom Asset Fields for
|
||||
|
@ -26,48 +23,60 @@ use Log;
|
|||
class CustomFieldsetsController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Validates and stores a new custom field.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @param int $id
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
/**
|
||||
* Validates and stores a new custom field.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @param int $id
|
||||
* @return \Illuminate\Support\Facades\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v1.8]
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$cfset = CustomFieldset::with('fields')->where('id', '=', $id)->orderBy('id', 'ASC')->first();
|
||||
$cfset = CustomFieldset::with('fields')
|
||||
->where('id', '=', $id)->orderBy('id', 'ASC')->first();
|
||||
|
||||
$this->authorize('view', $cfset);
|
||||
|
||||
if ($cfset) {
|
||||
$custom_fields_list = ["" => "Add New Field to Fieldset"] + CustomField::pluck("name", "id")->toArray();
|
||||
|
||||
|
||||
$maxid = 0;
|
||||
foreach ($cfset->fields() as $field) {
|
||||
if ($field->pivot->order > $maxid) {
|
||||
$maxid=$field->pivot->order;
|
||||
}
|
||||
if (isset($custom_fields_list[$field->id])) {
|
||||
unset($custom_fields_list[$field->id]);
|
||||
|
||||
if ($field) {
|
||||
if ($field->pivot->order > $maxid) {
|
||||
$maxid=$field->pivot->order;
|
||||
}
|
||||
if (isset($custom_fields_list[$field->id])) {
|
||||
unset($custom_fields_list[$field->id]);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return view("custom_fields.fieldsets.view")->with("custom_fieldset", $cfset)->with("maxid", $maxid+1)->with("custom_fields_list", $custom_fields_list);
|
||||
return view("custom_fields.fieldsets.view")
|
||||
->with("custom_fieldset", $cfset)
|
||||
->with("maxid", $maxid+1)
|
||||
->with("custom_fields_list", $custom_fields_list);
|
||||
}
|
||||
|
||||
return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist'));
|
||||
return redirect()->route("fields.index")
|
||||
->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a view with a form for creating a new custom fieldset.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
* Returns a view with a form for creating a new custom fieldset.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return \Illuminate\Support\Facades\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', CustomFieldset::class);
|
||||
|
@ -77,29 +86,30 @@ class CustomFieldsetsController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Validates and stores a new custom fieldset.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return Redirect
|
||||
*/
|
||||
* Validates and stores a new custom fieldset.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @param Request $request
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('create', CustomFieldset::class);
|
||||
|
||||
$cfset = new CustomFieldset(
|
||||
[
|
||||
$cfset = new CustomFieldset([
|
||||
"name" => e($request->get("name")),
|
||||
"user_id" => Auth::user()->id]
|
||||
);
|
||||
"user_id" => Auth::user()->id
|
||||
]);
|
||||
|
||||
$validator = Validator::make(Input::all(), $cfset->rules);
|
||||
if ($validator->passes()) {
|
||||
$cfset->save();
|
||||
return redirect()->route("fieldsets.show", [$cfset->id])->with('success', trans('admin/custom_fields/message.fieldset.create.success'));
|
||||
} else {
|
||||
return redirect()->back()->withInput()->withErrors($validator);
|
||||
return redirect()->route("fieldsets.show", [$cfset->id])
|
||||
->with('success', trans('admin/custom_fields/message.fieldset.create.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($validator);
|
||||
}
|
||||
|
||||
|
||||
|
@ -136,13 +146,14 @@ class CustomFieldsetsController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Validates a custom fieldset and then deletes if it has no models associated.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @param int $id
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
* Validates a custom fieldset and then deletes if it has no models associated.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @param int $id
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
$fieldset = CustomFieldset::find($id);
|
||||
|
@ -154,9 +165,8 @@ class CustomFieldsetsController extends Controller
|
|||
if ($models->count() == 0) {
|
||||
$fieldset->delete();
|
||||
return redirect()->route("fields.index")->with("success", trans('admin/custom_fields/message.fieldset.delete.success'));
|
||||
} else {
|
||||
return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use'));
|
||||
}
|
||||
return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.delete.in_use'));
|
||||
}
|
||||
|
||||
return redirect()->route("fields.index")->with("error", trans('admin/custom_fields/message.fieldset.does_not_exist'));
|
||||
|
@ -166,12 +176,13 @@ class CustomFieldsetsController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Associate the custom field with a custom fieldset.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
*/
|
||||
* Associate the custom field with a custom fieldset.
|
||||
*
|
||||
* @author [Brady Wetherington] [<uberbrady@gmail.com>]
|
||||
* @since [v1.8]
|
||||
* @return View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function associate($id)
|
||||
{
|
||||
|
||||
|
|
|
@ -4,10 +4,10 @@ namespace App\Http\Controllers;
|
|||
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Department;
|
||||
use App\Helpers\Helper;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Image;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class DepartmentsController extends Controller
|
||||
{
|
||||
|
@ -24,13 +24,15 @@ class DepartmentsController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see AssetController::getDatatable() method that generates the JSON response
|
||||
* @since [v4.0]
|
||||
* @return View
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Support\Facades\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
$this->authorize('index', Department::class);
|
||||
$company = null;
|
||||
if ($request->has('company_id')) {
|
||||
if ($request->filled('company_id')) {
|
||||
$company = Company::find($request->input('company_id'));
|
||||
}
|
||||
return view('departments/index')->with('company', $company);
|
||||
|
@ -42,27 +44,19 @@ class DepartmentsController extends Controller
|
|||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param ImageUploadRequest $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize('create', Department::class);
|
||||
$department = new Department;
|
||||
$department->fill($request->all());
|
||||
$department->user_id = Auth::user()->id;
|
||||
$department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null);
|
||||
$department->user_id = Auth::id();
|
||||
$department->manager_id = $request->input('manager_id', null);
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/departments/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$department->image = $file_name;
|
||||
}
|
||||
$department = $request->handleImages($department);
|
||||
|
||||
if ($department->save()) {
|
||||
return redirect()->route("departments.index")->with('success', trans('admin/departments/message.create.success'));
|
||||
|
@ -78,6 +72,7 @@ class DepartmentsController extends Controller
|
|||
* @param int $id
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
|
@ -88,7 +83,7 @@ class DepartmentsController extends Controller
|
|||
if (isset($department->id)) {
|
||||
return view('departments/view', compact('department'));
|
||||
}
|
||||
return redirect()->route('departments.index')->with('error', trans('admin/departments/message.does_not_exist', compact('id')));
|
||||
return redirect()->route('departments.index')->with('error', trans('admin/departments/message.does_not_exist'));
|
||||
}
|
||||
|
||||
|
||||
|
@ -99,6 +94,7 @@ class DepartmentsController extends Controller
|
|||
* @see DepartmentsController::postCreate() method that validates and stores the data
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
|
@ -115,6 +111,7 @@ class DepartmentsController extends Controller
|
|||
* @param int $locationId
|
||||
* @since [v4.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($id)
|
||||
{
|
||||
|
@ -128,23 +125,32 @@ class DepartmentsController extends Controller
|
|||
return redirect()->to(route('departments.index'))->with('error', trans('admin/departments/message.assoc_users'));
|
||||
}
|
||||
|
||||
if ($department->image) {
|
||||
try {
|
||||
Storage::disk('public')->delete('departments'.'/'.$department->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
$department->delete();
|
||||
|
||||
return redirect()->back()->with('success', trans('admin/departments/message.delete.success'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes a form view to edit location information.
|
||||
* Makes a form view to edit Department information.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::postCreate() method that validates and stores
|
||||
* @param int $locationId
|
||||
* @param int $departmentId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($id = null)
|
||||
public function edit($departmentId = null)
|
||||
{
|
||||
if (is_null($item = Department::find($id))) {
|
||||
if (is_null($item = Department::find($departmentId))) {
|
||||
return redirect()->back()->with('error', trans('admin/locations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
|
@ -162,38 +168,9 @@ class DepartmentsController extends Controller
|
|||
$this->authorize('update', $department);
|
||||
|
||||
$department->fill($request->all());
|
||||
$department->manager_id = ($request->has('manager_id' ) ? $request->input('manager_id') : null);
|
||||
$department->manager_id = ($request->filled('manager_id' ) ? $request->input('manager_id') : null);
|
||||
|
||||
$old_image = $department->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$department->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $department->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('departments_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('departments_upload_path'), $file_name);
|
||||
}
|
||||
$department->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('departments_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
}
|
||||
$department = $request->handleImages($department);
|
||||
|
||||
if ($department->save()) {
|
||||
return redirect()->route("departments.index")->with('success', trans('admin/departments/message.update.success'));
|
||||
|
|
|
@ -1,15 +1,8 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use Lang;
|
||||
use App\Models\Depreciation;
|
||||
use Redirect;
|
||||
use App\Models\Setting;
|
||||
use DB;
|
||||
use Str;
|
||||
use View;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
|
@ -21,13 +14,14 @@ use Illuminate\Http\Request;
|
|||
class DepreciationsController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the depreciation listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net]
|
||||
* @see DepreciationsController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the depreciation listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net]
|
||||
* @see DepreciationsController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
@ -39,12 +33,13 @@ class DepreciationsController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Returns a view that displays a form to create a new depreciation.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net]
|
||||
* @see DepreciationsController::postCreate()
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a view that displays a form to create a new depreciation.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net]
|
||||
* @see DepreciationsController::postCreate()
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
|
@ -63,6 +58,7 @@ class DepreciationsController extends Controller
|
|||
* @since [v1.0]
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
|
@ -84,13 +80,14 @@ class DepreciationsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a view that displays a form to update a depreciation.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net]
|
||||
* @see DepreciationsController::postEdit()
|
||||
* @param int $depreciationId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a view that displays a form to update a depreciation.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net]
|
||||
* @see DepreciationsController::postEdit()
|
||||
* @param int $depreciationId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($depreciationId = null)
|
||||
{
|
||||
|
@ -115,6 +112,7 @@ class DepreciationsController extends Controller
|
|||
* @param int $depreciationId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @since [v1.0]
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(Request $request, $depreciationId = null)
|
||||
{
|
||||
|
@ -147,17 +145,18 @@ class DepreciationsController extends Controller
|
|||
* @since [v1.0]
|
||||
* @param integer $depreciationId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($depreciationId)
|
||||
{
|
||||
// Check if the depreciation exists
|
||||
if (is_null($depreciation = Depreciation::find($depreciationId))) {
|
||||
if (is_null($depreciation = Depreciation::withCount('models as models_count')->find($depreciationId))) {
|
||||
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.not_found'));
|
||||
}
|
||||
|
||||
$this->authorize('delete', $depreciation);
|
||||
|
||||
if ($depreciation->has_models() > 0) {
|
||||
if ($depreciation->models_count > 0) {
|
||||
// Redirect to the asset management page
|
||||
return redirect()->route('depreciations.index')->with('error', trans('admin/depreciations/message.assoc_users'));
|
||||
}
|
||||
|
@ -175,6 +174,7 @@ class DepreciationsController extends Controller
|
|||
* @param int $depreciationId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
|
|
|
@ -1,13 +1,7 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Config;
|
||||
use Input;
|
||||
use Lang;
|
||||
use Redirect;
|
||||
use App\Models\Setting;
|
||||
use Validator;
|
||||
use View;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use App\Models\Group;
|
||||
use App\Helpers\Helper;
|
||||
|
||||
|
@ -109,7 +103,6 @@ class GroupsController extends Controller
|
|||
*/
|
||||
public function update($id = null)
|
||||
{
|
||||
$permissions = config('permissions');
|
||||
if (!$group = Group::find($id)) {
|
||||
return redirect()->route('groups.index')->with('error', trans('admin/groups/message.group_not_found', compact('id')));
|
||||
}
|
||||
|
@ -126,13 +119,14 @@ class GroupsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Validates and deletes the User Group.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net]
|
||||
* @see GroupsController::getEdit()
|
||||
* @param int $id
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* Validates and deletes the User Group.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net]
|
||||
* @see GroupsController::getEdit()
|
||||
* @param int $id
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function destroy($id = null)
|
||||
{
|
||||
|
@ -152,9 +146,9 @@ class GroupsController extends Controller
|
|||
* the content for the group detail page.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $locationId
|
||||
* @since [v4.0.11]
|
||||
* @param $id
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @since [v4.0.11]
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
|
|
|
@ -4,17 +4,19 @@ namespace App\Http\Controllers;
|
|||
|
||||
use App\Http\Transformers\ImportsTransformer;
|
||||
use App\Models\Import;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Models\Asset;
|
||||
|
||||
|
||||
class ImportsController extends Controller
|
||||
{
|
||||
/**
|
||||
* @return \Illuminate\Contracts\View\Factory|\Illuminate\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('create', Asset::class);
|
||||
$imports = Import::latest()->get();
|
||||
$imports = (new ImportsTransformer)->transformImports($imports);
|
||||
$imports = (new ImportsTransformer)->transformImports(Import::latest()->get());
|
||||
return view('importer/import')->with('imports', $imports);
|
||||
}
|
||||
}
|
||||
|
|
106
app/Http/Controllers/Licenses/LicenseCheckinController.php
Normal file
106
app/Http/Controllers/Licenses/LicenseCheckinController.php
Normal file
|
@ -0,0 +1,106 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Licenses;
|
||||
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use App\Models\Asset;
|
||||
use App\Models\License;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class LicenseCheckinController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Makes the form view to check a license seat back into inventory.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $seatId
|
||||
* @param string $backTo
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($seatId = null, $backTo = null)
|
||||
{
|
||||
// Check if the asset exists
|
||||
if (is_null($licenseSeat = LicenseSeat::find($seatId)) || is_null($license = License::find($licenseSeat->license_id))) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
return view('licenses/checkin', compact('licenseSeat'))->with('backto', $backTo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores the license checkin action.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LicenseCheckinController::create() method that provides the form view
|
||||
* @since [v1.0]
|
||||
* @param int $seatId
|
||||
* @param string $backTo
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(Request $request, $seatId = null, $backTo = null)
|
||||
{
|
||||
// Check if the asset exists
|
||||
if (is_null($licenseSeat = LicenseSeat::find($seatId))) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
|
||||
$license = License::find($licenseSeat->license_id);
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
if (!$license->reassignable) {
|
||||
// Not allowed to checkin
|
||||
Session::flash('error', 'License not reassignable.');
|
||||
return redirect()->back()->withInput();
|
||||
}
|
||||
|
||||
// Declare the rules for the form validation
|
||||
$rules = [
|
||||
'note' => 'string',
|
||||
'notes' => 'string',
|
||||
];
|
||||
|
||||
// Create a new validator instance from our validation rules
|
||||
$validator = Validator::make(Input::all(), $rules);
|
||||
|
||||
// If validation fails, we'll exit the operation now.
|
||||
if ($validator->fails()) {
|
||||
// Ooops.. something went wrong
|
||||
return redirect()->back()->withInput()->withErrors($validator);
|
||||
}
|
||||
$return_to = User::find($licenseSeat->assigned_to);
|
||||
|
||||
// Update the asset data
|
||||
$licenseSeat->assigned_to = null;
|
||||
$licenseSeat->asset_id = null;
|
||||
|
||||
// Was the asset updated?
|
||||
if ($licenseSeat->save()) {
|
||||
|
||||
event(new CheckoutableCheckedIn($licenseSeat, $return_to, Auth::user(), $request->input('note')));
|
||||
|
||||
if ($backTo=='user') {
|
||||
return redirect()->route("users.show", $return_to->id)->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
}
|
||||
return redirect()->route("licenses.show", $licenseSeat->license_id)->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
}
|
||||
|
||||
// Redirect to the license page with error
|
||||
return redirect()->route("licenses.index")->with('error', trans('admin/licenses/message.checkin.error'));
|
||||
}
|
||||
|
||||
}
|
131
app/Http/Controllers/Licenses/LicenseCheckoutController.php
Normal file
131
app/Http/Controllers/Licenses/LicenseCheckoutController.php
Normal file
|
@ -0,0 +1,131 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Licenses;
|
||||
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Http\Requests\LicenseCheckoutRequest;
|
||||
use App\Models\Asset;
|
||||
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\Input;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
|
||||
class LicenseCheckoutController extends Controller
|
||||
{
|
||||
/**
|
||||
* Provides the form view for checking out a license to a user.
|
||||
* Here we pass the license seat ID instead of the license ID,
|
||||
* because licenses themselves are never checked out to anyone,
|
||||
* only the seats associated with them.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param $licenseId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create($licenseId)
|
||||
{
|
||||
// Check that the license is valid
|
||||
if ($license = License::find($licenseId)) {
|
||||
|
||||
// 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');
|
||||
}
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
return view('licenses/checkout', compact('license'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores the license checkout action.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param LicenseCheckoutRequest $request
|
||||
* @param $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
|
||||
public function store(LicenseCheckoutRequest $request, $licenseId, $seatId = null)
|
||||
{
|
||||
if (!$license = License::find($licenseId)) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
$licenseSeat = $this->findLicenseSeatToCheckout($license, $seatId);
|
||||
$licenseSeat->user_id = Auth::id();
|
||||
|
||||
$checkoutMethod = 'checkoutTo'.ucwords(request('checkout_to_type'));
|
||||
if ($this->$checkoutMethod($licenseSeat)) {
|
||||
return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.checkout.success'));
|
||||
}
|
||||
|
||||
return redirect()->route("licenses.index")->with('error', trans('Something went wrong handling this checkout.'));
|
||||
}
|
||||
|
||||
protected function findLicenseSeatToCheckout($license, $seatId)
|
||||
{
|
||||
$licenseSeat = LicenseSeat::find($seatId) ?? $license->freeSeat();
|
||||
|
||||
if (!$licenseSeat) {
|
||||
if ($seatId) {
|
||||
return redirect()->route('licenses.index')->with('error', 'This Seat is not available for checkout.');
|
||||
}
|
||||
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
|
||||
}
|
||||
|
||||
if(!$licenseSeat->license->is($license)) {
|
||||
return redirect()->route('licenses.index')->with('error', 'The license seat provided does not match the license.');
|
||||
}
|
||||
|
||||
return $licenseSeat;
|
||||
}
|
||||
|
||||
protected function checkoutToAsset($licenseSeat)
|
||||
{
|
||||
if (is_null($target = Asset::find(request('asset_id')))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.asset_does_not_exist'));
|
||||
}
|
||||
$licenseSeat->asset_id = request('asset_id');
|
||||
|
||||
// Override asset's assigned user if available
|
||||
if ($target->checkedOutToUser()) {
|
||||
$licenseSeat->assigned_to = $target->assigned_to;
|
||||
}
|
||||
if ($licenseSeat->save()) {
|
||||
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note')));
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
protected function checkoutToUser($licenseSeat)
|
||||
{
|
||||
// Fetch the target and set the license user
|
||||
if (is_null($target = User::find(request('assigned_to')))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.user_does_not_exist'));
|
||||
}
|
||||
$licenseSeat->assigned_to = request('assigned_to');
|
||||
|
||||
if ($licenseSeat->save()) {
|
||||
|
||||
event(new CheckoutableCheckedOut($licenseSeat, $target, Auth::user(), request('note')));
|
||||
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
154
app/Http/Controllers/Licenses/LicenseFilesController.php
Normal file
154
app/Http/Controllers/Licenses/LicenseFilesController.php
Normal file
|
@ -0,0 +1,154 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Licenses;
|
||||
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\License;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
class LicenseFilesController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Validates and stores files associated with a license.
|
||||
*
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param AssetFileRequest $request
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $licenseId = null)
|
||||
{
|
||||
$license = License::find($licenseId);
|
||||
// the license is valid
|
||||
$destinationPath = config('app.private_uploads').'/licenses';
|
||||
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('update', $license);
|
||||
|
||||
if (Input::hasFile('file')) {
|
||||
|
||||
if (!Storage::exists('private_uploads/licenses')) Storage::makeDirectory('private_uploads/licenses', 775);
|
||||
|
||||
$upload_success = false;
|
||||
foreach (Input::file('file') as $file) {
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'license-'.$license->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
$upload_success = Storage::put('private_uploads/licenses/'.$file_name, $file);
|
||||
|
||||
//Log the upload to the log
|
||||
$license->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
// This being called from a modal seems to confuse redirect()->back()
|
||||
// It thinks we should go to the dashboard. As this is only used
|
||||
// from the modal at present, hardcode the redirect. Longterm
|
||||
// maybe we evaluate something else.
|
||||
if ($upload_success) {
|
||||
return redirect()->route('licenses.show', $license->id)->with('success', trans('admin/licenses/message.upload.success'));
|
||||
}
|
||||
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.error'));
|
||||
}
|
||||
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.nofiles'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('licenses.index')
|
||||
->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes the selected license file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($licenseId = null, $fileId = null)
|
||||
{
|
||||
$license = License::find($licenseId);
|
||||
|
||||
// the asset is valid
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('update', $license);
|
||||
$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);
|
||||
}
|
||||
}
|
||||
|
||||
$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'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $licenseId
|
||||
* @param int $fileId
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($licenseId = null, $fileId = null, $download = true)
|
||||
{
|
||||
|
||||
$license = License::find($licenseId);
|
||||
|
||||
// the license is valid
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('view', $license);
|
||||
|
||||
if (!$log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
$file = 'private_uploads/licenses/'.$log->filename;
|
||||
\Log::debug('Checking for '.$file);
|
||||
|
||||
if (!Storage::exists($file)) {
|
||||
return response('File '.$file.' not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
if ($download != 'true') {
|
||||
if ($contents = file_get_contents(Storage::url($file))) {
|
||||
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
|
||||
}
|
||||
return JsonResponse::create(["error" => "Failed validation: "], 500);
|
||||
}
|
||||
return Storage::download($file);
|
||||
}
|
||||
return redirect()->route('hardware.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
273
app/Http/Controllers/Licenses/LicensesController.php
Executable file
273
app/Http/Controllers/Licenses/LicensesController.php
Executable file
|
@ -0,0 +1,273 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers\Licenses;
|
||||
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\License;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use App\Models\Company;
|
||||
use App\Helpers\Helper;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Licenses for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class LicensesController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the licenses listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LicensesController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('view', License::class);
|
||||
return view('licenses/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a form view that allows an admin to create a new licence.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see AccessoriesController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', License::class);
|
||||
$maintained_list = [
|
||||
'' => 'Maintained',
|
||||
'1' => 'Yes',
|
||||
'0' => 'No'
|
||||
];
|
||||
|
||||
return view('licenses/edit')
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('maintained_list', $maintained_list)
|
||||
->with('item', new License);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores the license form data submitted from the new
|
||||
* license form.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LicensesController::getCreate() method that provides the form view
|
||||
* @since [v1.0]
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('create', License::class);
|
||||
// create a new model instance
|
||||
$license = new License();
|
||||
// Save the license data
|
||||
$license->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$license->depreciation_id = $request->input('depreciation_id');
|
||||
$license->expiration_date = $request->input('expiration_date');
|
||||
$license->license_email = $request->input('license_email');
|
||||
$license->license_name = $request->input('license_name');
|
||||
$license->maintained = $request->input('maintained', 0);
|
||||
$license->manufacturer_id = $request->input('manufacturer_id');
|
||||
$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_date = $request->input('purchase_date');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->reassignable = $request->input('reassignable', 0);
|
||||
$license->seats = $request->input('seats');
|
||||
$license->serial = $request->input('serial');
|
||||
$license->supplier_id = $request->input('supplier_id');
|
||||
$license->category_id = $request->input('category_id');
|
||||
$license->termination_date = $request->input('termination_date');
|
||||
$license->user_id = Auth::id();
|
||||
|
||||
if ($license->save()) {
|
||||
return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.create.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($license->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a form with existing license data to allow an admin to
|
||||
* update license information.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($licenseId = null)
|
||||
{
|
||||
if (is_null($item = License::find($licenseId))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $item);
|
||||
|
||||
$maintained_list = [
|
||||
'' => 'Maintained',
|
||||
'1' => 'Yes',
|
||||
'0' => 'No'
|
||||
];
|
||||
|
||||
return view('licenses/edit', compact('item'))
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('maintained_list', $maintained_list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores the license form data submitted from the edit
|
||||
* license form.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LicensesController::getEdit() method that provides the form view
|
||||
* @since [v1.0]
|
||||
* @param Request $request
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(Request $request, $licenseId = null)
|
||||
{
|
||||
if (is_null($license = License::find($licenseId))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $license);
|
||||
|
||||
$license->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$license->depreciation_id = $request->input('depreciation_id');
|
||||
$license->expiration_date = $request->input('expiration_date');
|
||||
$license->license_email = $request->input('license_email');
|
||||
$license->license_name = $request->input('license_name');
|
||||
$license->maintained = $request->input('maintained',0);
|
||||
$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_date = $request->input('purchase_date');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->reassignable = $request->input('reassignable', 0);
|
||||
$license->serial = $request->input('serial');
|
||||
$license->termination_date = $request->input('termination_date');
|
||||
$license->seats = e($request->input('seats'));
|
||||
$license->manufacturer_id = $request->input('manufacturer_id');
|
||||
$license->supplier_id = $request->input('supplier_id');
|
||||
$license->category_id = $request->input('category_id');
|
||||
|
||||
if ($license->save()) {
|
||||
return redirect()->route('licenses.show', ['license' => $licenseId])->with('success', trans('admin/licenses/message.update.success'));
|
||||
}
|
||||
// If we can't adjust the number of seats, the error is flashed to the session by the event handler in License.php
|
||||
return redirect()->back()->withInput()->withErrors($license->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see whether the selected license can be deleted, and
|
||||
* if it can, marks it as deleted.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($licenseId)
|
||||
{
|
||||
// Check if the license exists
|
||||
if (is_null($license = License::find($licenseId))) {
|
||||
// Redirect to the license management page
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
|
||||
$this->authorize('delete', $license);
|
||||
|
||||
if ($license->assigned_seats_count == 0) {
|
||||
// Delete the license and the associated license seats
|
||||
DB::table('license_seats')
|
||||
->where('id', $license->id)
|
||||
->update(array('assigned_to' => null,'asset_id' => null));
|
||||
|
||||
$licenseSeats = $license->licenseseats();
|
||||
$licenseSeats->delete();
|
||||
$license->delete();
|
||||
|
||||
// Redirect to the licenses management page
|
||||
return redirect()->route('licenses.index')->with('success', trans('admin/licenses/message.delete.success'));
|
||||
// Redirect to the license management page
|
||||
}
|
||||
// There are still licenses in use.
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.assoc_users'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes the license detail page.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($licenseId = null)
|
||||
{
|
||||
|
||||
$license = License::with('assignedusers', 'licenseSeats.user', 'licenseSeats.asset')->find($licenseId);
|
||||
|
||||
if ($license) {
|
||||
$this->authorize('view', $license);
|
||||
return view('licenses/view', compact('license'));
|
||||
}
|
||||
return redirect()->route('licenses.index')
|
||||
->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
|
||||
public function getClone($licenseId = null)
|
||||
{
|
||||
if (is_null($license_to_clone = License::find($licenseId))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('create', License::class);
|
||||
|
||||
$maintained_list = [
|
||||
'' => 'Maintained',
|
||||
'1' => 'Yes',
|
||||
'0' => 'No'
|
||||
];
|
||||
//clone the orig
|
||||
$license = clone $license_to_clone;
|
||||
$license->id = null;
|
||||
$license->serial = null;
|
||||
|
||||
// Show the page
|
||||
return view('licenses/edit')
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('item', $license)
|
||||
->with('maintained_list', $maintained_list);
|
||||
}
|
||||
}
|
|
@ -1,649 +0,0 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use Assets;
|
||||
use Illuminate\Support\Facades\Session;
|
||||
use Input;
|
||||
use Lang;
|
||||
use App\Models\License;
|
||||
use App\Models\Asset;
|
||||
use App\Models\User;
|
||||
use App\Models\Actionlog;
|
||||
use DB;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\Company;
|
||||
use Validator;
|
||||
use View;
|
||||
use Response;
|
||||
use Slack;
|
||||
use Config;
|
||||
use App\Helpers\Helper;
|
||||
use Auth;
|
||||
use Gate;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Licenses for
|
||||
* the Snipe-IT Asset Management application.
|
||||
*
|
||||
* @version v1.0
|
||||
*/
|
||||
class LicensesController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the licenses listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LicensesController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
$this->authorize('view', License::class);
|
||||
return view('licenses/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a form view that allows an admin to create a new licence.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see AccessoriesController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('create', License::class);
|
||||
$maintained_list = [
|
||||
'' => 'Maintained',
|
||||
'1' => 'Yes',
|
||||
'0' => 'No'
|
||||
];
|
||||
|
||||
return view('licenses/edit')
|
||||
//->with('license_options',$license_options)
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('maintained_list', $maintained_list)
|
||||
->with('item', new License);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores the license form data submitted from the new
|
||||
* license form.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LicensesController::getCreate() method that provides the form view
|
||||
* @since [v1.0]
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
$this->authorize('create', License::class);
|
||||
// create a new model instance
|
||||
$license = new License();
|
||||
// Save the license data
|
||||
$license->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$license->depreciation_id = $request->input('depreciation_id');
|
||||
$license->expiration_date = $request->input('expiration_date');
|
||||
$license->license_email = $request->input('license_email');
|
||||
$license->license_name = $request->input('license_name');
|
||||
$license->maintained = $request->input('maintained', 0);
|
||||
$license->manufacturer_id = $request->input('manufacturer_id');
|
||||
$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_date = $request->input('purchase_date');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->reassignable = $request->input('reassignable', 0);
|
||||
$license->seats = $request->input('seats');
|
||||
$license->serial = $request->input('serial');
|
||||
$license->supplier_id = $request->input('supplier_id');
|
||||
$license->category_id = $request->input('category_id');
|
||||
$license->termination_date = $request->input('termination_date');
|
||||
$license->user_id = Auth::id();
|
||||
|
||||
if ($license->save()) {
|
||||
return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.create.success'));
|
||||
}
|
||||
return redirect()->back()->withInput()->withErrors($license->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns a form with existing license data to allow an admin to
|
||||
* update license information.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function edit($licenseId = null)
|
||||
{
|
||||
if (is_null($item = License::find($licenseId))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $item);
|
||||
|
||||
$maintained_list = [
|
||||
'' => 'Maintained',
|
||||
'1' => 'Yes',
|
||||
'0' => 'No'
|
||||
];
|
||||
|
||||
return view('licenses/edit', compact('item'))
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('maintained_list', $maintained_list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores the license form data submitted from the edit
|
||||
* license form.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LicensesController::getEdit() method that provides the form view
|
||||
* @since [v1.0]
|
||||
* @param Request $request
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function update(Request $request, $licenseId = null)
|
||||
{
|
||||
if (is_null($license = License::find($licenseId))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('update', $license);
|
||||
|
||||
$license->company_id = Company::getIdForCurrentUser($request->input('company_id'));
|
||||
$license->depreciation_id = $request->input('depreciation_id');
|
||||
$license->expiration_date = $request->input('expiration_date');
|
||||
$license->license_email = $request->input('license_email');
|
||||
$license->license_name = $request->input('license_name');
|
||||
$license->maintained = $request->input('maintained',0);
|
||||
$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_date = $request->input('purchase_date');
|
||||
$license->purchase_order = $request->input('purchase_order');
|
||||
$license->reassignable = $request->input('reassignable', 0);
|
||||
$license->serial = $request->input('serial');
|
||||
$license->termination_date = $request->input('termination_date');
|
||||
$license->seats = e($request->input('seats'));
|
||||
$license->manufacturer_id = $request->input('manufacturer_id');
|
||||
$license->supplier_id = $request->input('supplier_id');
|
||||
$license->category_id = $request->input('category_id');
|
||||
|
||||
if ($license->save()) {
|
||||
return redirect()->route('licenses.show', ['license' => $licenseId])->with('success', trans('admin/licenses/message.update.success'));
|
||||
}
|
||||
// If we can't adjust the number of seats, the error is flashed to the session by the event handler in License.php
|
||||
return redirect()->back()->withInput()->withErrors($license->getErrors());
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks to see whether the selected license can be deleted, and
|
||||
* if it can, marks it as deleted.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function destroy($licenseId)
|
||||
{
|
||||
// Check if the license exists
|
||||
if (is_null($license = License::find($licenseId))) {
|
||||
// Redirect to the license management page
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
|
||||
$this->authorize('delete', $license);
|
||||
|
||||
if ($license->assigned_seats_count == 0) {
|
||||
// Delete the license and the associated license seats
|
||||
DB::table('license_seats')
|
||||
->where('id', $license->id)
|
||||
->update(array('assigned_to' => null,'asset_id' => null));
|
||||
|
||||
$licenseSeats = $license->licenseseats();
|
||||
$licenseSeats->delete();
|
||||
$license->delete();
|
||||
|
||||
// Redirect to the licenses management page
|
||||
return redirect()->route('licenses.index')->with('success', trans('admin/licenses/message.delete.success'));
|
||||
// Redirect to the license management page
|
||||
}
|
||||
// There are still licenses in use.
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.assoc_users'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides the form view for checking out a license to a user.
|
||||
* Here we pass the license seat ID instead of the license ID,
|
||||
* because licenses themselves are never checked out to anyone,
|
||||
* only the seats associated with them.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $seatId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function getCheckout($licenceId)
|
||||
{
|
||||
// Check that the license is valid
|
||||
if ($license = License::where('id',$licenceId)->first()) {
|
||||
|
||||
// If the license is valid, check that there is an available seat
|
||||
if ($license->getAvailSeatsCountAttribute() < 1) {
|
||||
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
|
||||
}
|
||||
}
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
return view('licenses/checkout', compact('license'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores the license checkout action.
|
||||
*
|
||||
* @todo Switch to using a FormRequest for validation here.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param Request $request
|
||||
* @param int $licenseId
|
||||
* @param int $seatId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postCheckout(Request $request, $licenseId, $seatId = null)
|
||||
{
|
||||
|
||||
// Check that the license is valid
|
||||
if ($license = License::where('id', $licenseId)->first()) {
|
||||
|
||||
// If the license is valid, check that there is an available seat
|
||||
if ($license->getAvailSeatsCountAttribute() < 1) {
|
||||
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
|
||||
}
|
||||
if (!$seatId) {
|
||||
// Get the next available seat for this license
|
||||
$next = $license->freeSeat();
|
||||
if (!$next) {
|
||||
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
|
||||
}
|
||||
if (!$licenseSeat = LicenseSeat::where('id', '=', $next->id)->first()) {
|
||||
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
|
||||
}
|
||||
} else {
|
||||
$licenseSeat = LicenseSeat::where('id', '=', $seatId)->first();
|
||||
if (!$licenseSeat) {
|
||||
return redirect()->route('licenses.index')->with('error', 'License seat is not available for checkout');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
// Declare the rules for the form validation
|
||||
$rules = [
|
||||
'note' => 'string|nullable',
|
||||
'asset_id' => 'required_without:assigned_to',
|
||||
];
|
||||
|
||||
// Create a new validator instance from our validation rules
|
||||
$validator = Validator::make(Input::all(), $rules);
|
||||
|
||||
// If validation fails, we'll exit the operation now.
|
||||
if ($validator->fails()) {
|
||||
// Ooops.. something went wrong
|
||||
return redirect()->back()->withInput()->withErrors($validator);
|
||||
}
|
||||
$target = null;
|
||||
|
||||
|
||||
// This item is checked out to a an asset
|
||||
if (request('checkout_to_type')=='asset') {
|
||||
if (is_null($target = Asset::find(request('asset_id')))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.asset_does_not_exist'));
|
||||
}
|
||||
$licenseSeat->asset_id = $request->input('asset_id');
|
||||
|
||||
// Override asset's assigned user if available
|
||||
if ($target->checkedOutToUser()) {
|
||||
$licenseSeat->assigned_to = $target->assigned_to;
|
||||
}
|
||||
|
||||
} else {
|
||||
|
||||
// Fetch the target and set the license user
|
||||
if (is_null($target = User::find(request('assigned_to')))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.user_does_not_exist'));
|
||||
}
|
||||
$licenseSeat->assigned_to = request('assigned_to');
|
||||
}
|
||||
|
||||
$licenseSeat->user_id = Auth::user()->id;
|
||||
|
||||
|
||||
if ($licenseSeat->save()) {
|
||||
$licenseSeat->logCheckout($request->input('note'), $target);
|
||||
return redirect()->route("licenses.index")->with('success', trans('admin/licenses/message.checkout.success'));
|
||||
}
|
||||
|
||||
}
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
|
||||
|
||||
|
||||
|
||||
return redirect()->route("licenses.index")->with('error', trans('admin/licenses/message.checkout.error'));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Makes the form view to check a license seat back into inventory.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $seatId
|
||||
* @param string $backTo
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function getCheckin($seatId = null, $backTo = null)
|
||||
{
|
||||
// Check if the asset exists
|
||||
if (is_null($licenseSeat = LicenseSeat::find($seatId))) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
|
||||
if (is_null($license = License::find($licenseSeat->license_id))) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
|
||||
|
||||
$this->authorize('checkout', $license);
|
||||
return view('licenses/checkin', compact('licenseSeat'))->with('backto', $backTo);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores the license checkin action.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LicensesController::getCheckin() method that provides the form view
|
||||
* @since [v1.0]
|
||||
* @param int $seatId
|
||||
* @param string $backTo
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postCheckin($seatId = null, $backTo = null)
|
||||
{
|
||||
// Check if the asset exists
|
||||
if (is_null($licenseSeat = LicenseSeat::find($seatId))) {
|
||||
// Redirect to the asset management page with error
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
|
||||
$license = License::find($licenseSeat->license_id);
|
||||
$this->authorize('checkout', $license);
|
||||
|
||||
if (!$license->reassignable) {
|
||||
// Not allowed to checkin
|
||||
Session::flash('error', 'License not reassignable.');
|
||||
return redirect()->back()->withInput();
|
||||
}
|
||||
|
||||
// Declare the rules for the form validation
|
||||
$rules = array(
|
||||
'note' => 'string',
|
||||
'notes' => 'string',
|
||||
);
|
||||
|
||||
// Create a new validator instance from our validation rules
|
||||
$validator = Validator::make(Input::all(), $rules);
|
||||
|
||||
// If validation fails, we'll exit the operation now.
|
||||
if ($validator->fails()) {
|
||||
// Ooops.. something went wrong
|
||||
return redirect()->back()->withInput()->withErrors($validator);
|
||||
}
|
||||
$return_to = User::find($licenseSeat->assigned_to);
|
||||
if (!$return_to) {
|
||||
$return_to = Asset::find($licenseSeat->asset_id);
|
||||
}
|
||||
|
||||
// Update the asset data
|
||||
$licenseSeat->assigned_to = null;
|
||||
$licenseSeat->asset_id = null;
|
||||
|
||||
// Was the asset updated?
|
||||
if ($licenseSeat->save()) {
|
||||
$licenseSeat->logCheckin($return_to, e(request('note')));
|
||||
if ($backTo=='user') {
|
||||
return redirect()->route("users.show", $return_to->id)->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
}
|
||||
return redirect()->route("licenses.show", $licenseSeat->license_id)->with('success', trans('admin/licenses/message.checkin.success'));
|
||||
}
|
||||
|
||||
// Redirect to the license page with error
|
||||
return redirect()->route("licenses.index")->with('error', trans('admin/licenses/message.checkin.error'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Makes the license detail page.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show($licenseId = null)
|
||||
{
|
||||
|
||||
$license = License::with('assignedusers', 'licenseSeats.user', 'licenseSeats.asset')->find($licenseId);
|
||||
|
||||
if ($license) {
|
||||
$this->authorize('view', $license);
|
||||
return view('licenses/view', compact('license'));
|
||||
}
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', compact('id')));
|
||||
}
|
||||
|
||||
|
||||
public function getClone($licenseId = null)
|
||||
{
|
||||
if (is_null($license_to_clone = License::find($licenseId))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist'));
|
||||
}
|
||||
|
||||
$this->authorize('create', License::class);
|
||||
|
||||
$maintained_list = [
|
||||
'' => 'Maintained',
|
||||
'1' => 'Yes',
|
||||
'0' => 'No'
|
||||
];
|
||||
//clone the orig
|
||||
$license = clone $license_to_clone;
|
||||
$license->id = null;
|
||||
$license->serial = null;
|
||||
|
||||
// Show the page
|
||||
return view('licenses/edit')
|
||||
->with('depreciation_list', Helper::depreciationList())
|
||||
->with('item', $license)
|
||||
->with('maintained_list', $maintained_list);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Validates and stores files associated with a license.
|
||||
*
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postUpload(AssetFileRequest $request, $licenseId = null)
|
||||
{
|
||||
$license = License::find($licenseId);
|
||||
// the license is valid
|
||||
$destinationPath = config('app.private_uploads').'/licenses';
|
||||
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('update', $license);
|
||||
|
||||
if (Input::hasFile('file')) {
|
||||
|
||||
foreach (Input::file('file') as $file) {
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$filename = 'license-'.$license->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
$upload_success = $file->move($destinationPath, $filename);
|
||||
|
||||
//Log the upload to the log
|
||||
$license->logUpload($filename, e($request->input('notes')));
|
||||
}
|
||||
// This being called from a modal seems to confuse redirect()->back()
|
||||
// It thinks we should go to the dashboard. As this is only used
|
||||
// from the modal at present, hardcode the redirect. Longterm
|
||||
// maybe we evaluate something else.
|
||||
if ($upload_success) {
|
||||
return redirect()->route('licenses.show', $license->id)->with('success', trans('admin/licenses/message.upload.success'));
|
||||
}
|
||||
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.error'));
|
||||
}
|
||||
return redirect()->route('licenses.show', $license->id)->with('error', trans('admin/licenses/message.upload.nofiles'));
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/licenses/message.does_not_exist', compact('id'));
|
||||
return redirect()->route('licenses.index')->with('error', $error);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Deletes the selected license file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function getDeleteFile($licenseId = null, $fileId = null)
|
||||
{
|
||||
$license = License::find($licenseId);
|
||||
$destinationPath = config('app.private_uploads').'/licenses';
|
||||
|
||||
// the license is valid
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('edit', $license);
|
||||
$log = Actionlog::find($fileId);
|
||||
$full_filename = $destinationPath.'/'.$log->filename;
|
||||
if (file_exists($full_filename)) {
|
||||
unlink($destinationPath.'/'.$log->filename);
|
||||
}
|
||||
$log->delete();
|
||||
return redirect()->back()->with('success', trans('admin/licenses/message.deletefile.success'));
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/licenses/message.does_not_exist', compact('id'));
|
||||
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('licenses.index')->with('error', $error);
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $licenseId
|
||||
* @param int $fileId
|
||||
* @return \Symfony\Component\HttpFoundation\BinaryFileResponse
|
||||
*/
|
||||
public function displayFile($licenseId = null, $fileId = null, $download = true)
|
||||
{
|
||||
|
||||
$license = License::find($licenseId);
|
||||
|
||||
// the license is valid
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('view', $license);
|
||||
$log = Actionlog::find($fileId);
|
||||
$file = $log->get_src('licenses');
|
||||
|
||||
|
||||
if ($file =='') {
|
||||
return response('File not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
$mimetype = \File::mimeType($file);
|
||||
|
||||
|
||||
if (!file_exists($file)) {
|
||||
return response('File '.$file.' not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
if ($download != 'true') {
|
||||
if ($contents = file_get_contents($file)) {
|
||||
return Response::make($contents)->header('Content-Type', $mimetype);
|
||||
}
|
||||
return JsonResponse::create(["error" => "Failed validation: "], 500);
|
||||
}
|
||||
return Response::download($file);
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', compact('id')));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Generates the next free seat ID for checkout.
|
||||
*
|
||||
* @todo This is a dumb way to solve this problem.
|
||||
* Author should refactor. And go hide in a hole and
|
||||
* think about what she's done. And perhaps find a new
|
||||
* line of work. And get in the sea.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $licenseId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function getFreeLicense($licenseId)
|
||||
{
|
||||
$this->authorize('checkout', License::class);
|
||||
if (is_null($license = License::find($licenseId))) {
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.not_found'));
|
||||
}
|
||||
$seatId = $license->freeSeat($licenseId);
|
||||
return redirect()->route('licenses.checkout', $seatId);
|
||||
}
|
||||
}
|
|
@ -1,23 +1,12 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use Input;
|
||||
use Lang;
|
||||
|
||||
use App\Models\Location;
|
||||
use phpDocumentor\Reflection\Types\Array_;
|
||||
use Redirect;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Models\Asset;
|
||||
use DB;
|
||||
use Str;
|
||||
use Validator;
|
||||
use View;
|
||||
use Auth;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Image;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Locations for
|
||||
|
@ -29,32 +18,32 @@ class LocationsController extends Controller
|
|||
{
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the locations listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the locations listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::getDatatable() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
// Grab all the locations
|
||||
$this->authorize('view', Location::class);
|
||||
$locations = Location::orderBy('created_at', 'DESC')->with('parent', 'assets', 'assignedassets')->get();
|
||||
|
||||
// Show the page
|
||||
return view('locations/index');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a form view used to create a new location.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::postCreate() method that validates and stores the data
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a form view used to create a new location.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::postCreate() method that validates and stores the data
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
|
@ -72,13 +61,15 @@ class LocationsController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Validates and stores a new location.
|
||||
*
|
||||
* @todo Check if a Form Request would work better here.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::getCreate() method that makes the form
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* Validates and stores a new location.
|
||||
*
|
||||
* @todo Check if a Form Request would work better here.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::getCreate() method that makes the form
|
||||
* @since [v1.0]
|
||||
* @param ImageUploadRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
|
@ -97,16 +88,7 @@ class LocationsController extends Controller
|
|||
$location->manager_id = $request->input('manager_id');
|
||||
$location->user_id = Auth::id();
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/locations/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(600, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$location->image = $file_name;
|
||||
}
|
||||
$location = $request->handleImages($location, 'public/uploads/locations');
|
||||
|
||||
if ($location->save()) {
|
||||
return redirect()->route("locations.index")->with('success', trans('admin/locations/message.create.success'));
|
||||
|
@ -116,13 +98,14 @@ class LocationsController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Makes a form view to edit location information.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::postCreate() method that validates and stores
|
||||
* @param int $locationId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Makes a form view to edit location information.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::postCreate() method that validates and stores
|
||||
* @param int $locationId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($locationId = null)
|
||||
{
|
||||
|
@ -144,13 +127,15 @@ class LocationsController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Validates and stores updated location data from edit form.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::getEdit() method that makes the form view
|
||||
* @param int $locationId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* Validates and stores updated location data from edit form.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see LocationsController::getEdit() method that makes the form view
|
||||
* @param ImageUploadRequest $request
|
||||
* @param int $locationId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v1.0]
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $locationId = null)
|
||||
{
|
||||
|
@ -173,36 +158,7 @@ class LocationsController extends Controller
|
|||
$location->ldap_ou = $request->input('ldap_ou');
|
||||
$location->manager_id = $request->input('manager_id');
|
||||
|
||||
$old_image = $location->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$location->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $location->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(600, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('locations_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('locations_upload_path'), $file_name);
|
||||
}
|
||||
$location->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('locations_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
}
|
||||
$location = $request->handleImages($location, 'public/uploads/locations');
|
||||
|
||||
|
||||
if ($location->save()) {
|
||||
|
@ -212,12 +168,13 @@ class LocationsController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Validates and deletes selected location.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $locationId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* Validates and deletes selected location.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $locationId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($locationId)
|
||||
{
|
||||
|
@ -226,22 +183,29 @@ class LocationsController extends Controller
|
|||
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.not_found'));
|
||||
}
|
||||
|
||||
if ($location->users->count() > 0) {
|
||||
if ($location->users()->count() > 0) {
|
||||
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_users'));
|
||||
|
||||
} elseif ($location->childLocations->count() > 0) {
|
||||
} elseif ($location->childLocations()->count() > 0) {
|
||||
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_child_loc'));
|
||||
|
||||
} elseif ($location->assets->count() > 0) {
|
||||
} elseif ($location->assets()->count() > 0) {
|
||||
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_assets'));
|
||||
|
||||
} elseif ($location->assignedassets->count() > 0) {
|
||||
} elseif ($location->assignedassets()->count() > 0) {
|
||||
return redirect()->to(route('locations.index'))->with('error', trans('admin/locations/message.assoc_assets'));
|
||||
|
||||
} else {
|
||||
$location->delete();
|
||||
return redirect()->to(route('locations.index'))->with('success', trans('admin/locations/message.delete.success'));
|
||||
}
|
||||
|
||||
if ($location->image) {
|
||||
try {
|
||||
Storage::disk('public')->delete('locations/'.$location->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
}
|
||||
$location->delete();
|
||||
return redirect()->to(route('locations.index'))->with('success', trans('admin/locations/message.delete.success'));
|
||||
}
|
||||
|
||||
|
||||
|
@ -250,19 +214,19 @@ class LocationsController extends Controller
|
|||
* the content for the locations detail page.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $locationId
|
||||
* @param int $id
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*/
|
||||
public function show($locationId = null)
|
||||
public function show($id = null)
|
||||
{
|
||||
$location = Location::find($locationId);
|
||||
$location = Location::find($id);
|
||||
|
||||
if (isset($location->id)) {
|
||||
return view('locations/view', compact('location'));
|
||||
}
|
||||
|
||||
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist', compact('id')));
|
||||
return redirect()->route('locations.index')->with('error', trans('admin/locations/message.does_not_exist'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -1,20 +1,13 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\Manufacturer;
|
||||
use Auth;
|
||||
use Exception;
|
||||
use Gate;
|
||||
use Input;
|
||||
use Lang;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Redirect;
|
||||
use Str;
|
||||
use View;
|
||||
use Illuminate\Http\Request;
|
||||
use Image;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Manufacturers for
|
||||
|
@ -25,13 +18,14 @@ use Image;
|
|||
class ManufacturersController extends Controller
|
||||
{
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the manufacturers listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see Api\ManufacturersController::index() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the manufacturers listing, which is generated in getDatatable.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see Api\ManufacturersController::index() method that generates the JSON response
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
@ -41,12 +35,13 @@ class ManufacturersController extends Controller
|
|||
|
||||
|
||||
/**
|
||||
* Returns a view that displays a form to create a new manufacturer.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ManufacturersController::store()
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a view that displays a form to create a new manufacturer.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ManufacturersController::store()
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
|
@ -61,32 +56,24 @@ class ManufacturersController extends Controller
|
|||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ManufacturersController::create()
|
||||
* @since [v1.0]
|
||||
* @param Request $request
|
||||
* @param ImageUploadRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
|
||||
$this->authorize('create', Manufacturer::class);
|
||||
$manufacturer = new Manufacturer;
|
||||
$manufacturer->name = $request->input('name');
|
||||
$manufacturer->user_id = Auth::user()->id;
|
||||
$manufacturer->url = $request->input('url');
|
||||
$manufacturer->support_url = $request->input('support_url');
|
||||
$manufacturer->name = $request->input('name');
|
||||
$manufacturer->user_id = Auth::id();
|
||||
$manufacturer->url = $request->input('url');
|
||||
$manufacturer->support_url = $request->input('support_url');
|
||||
$manufacturer->support_phone = $request->input('support_phone');
|
||||
$manufacturer->support_email = $request->input('support_email');
|
||||
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_slug($image->getClientOriginalName()).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/manufacturers/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$manufacturer->image = $file_name;
|
||||
}
|
||||
$manufacturer = $request->handleImages($manufacturer,'manufacturers');
|
||||
|
||||
|
||||
|
||||
|
@ -97,19 +84,20 @@ class ManufacturersController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a view that displays a form to edit a manufacturer.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ManufacturersController::update()
|
||||
* @param int $manufacturerId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a view that displays a form to edit a manufacturer.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @see ManufacturersController::update()
|
||||
* @param int $manufacturerId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($id = null)
|
||||
public function edit($manufacturerId = null)
|
||||
{
|
||||
$this->authorize('edit', Manufacturer::class);
|
||||
// Check if the manufacturer exists
|
||||
if (is_null($item = Manufacturer::find($id))) {
|
||||
if (is_null($item = Manufacturer::find($manufacturerId))) {
|
||||
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.does_not_exist'));
|
||||
}
|
||||
// Show the page
|
||||
|
@ -126,6 +114,7 @@ class ManufacturersController extends Controller
|
|||
* @param int $manufacturerId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @since [v1.0]
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(ImageUploadRequest $request, $manufacturerId = null)
|
||||
{
|
||||
|
@ -137,42 +126,13 @@ class ManufacturersController extends Controller
|
|||
}
|
||||
|
||||
// Save the data
|
||||
$manufacturer->name = $request->input('name');
|
||||
$manufacturer->url = $request->input('url');
|
||||
$manufacturer->support_url = $request->input('support_url');
|
||||
$manufacturer->name = $request->input('name');
|
||||
$manufacturer->url = $request->input('url');
|
||||
$manufacturer->support_url = $request->input('support_url');
|
||||
$manufacturer->support_phone = $request->input('support_phone');
|
||||
$manufacturer->support_email = $request->input('support_email');
|
||||
|
||||
$old_image = $manufacturer->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$manufacturer->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $manufacturer->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('manufacturers_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('manufacturers_upload_path'), $file_name);
|
||||
}
|
||||
$manufacturer->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('manufacturers_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
}
|
||||
$manufacturer = $request->handleImages($manufacturer);
|
||||
|
||||
|
||||
if ($manufacturer->save()) {
|
||||
|
@ -182,30 +142,28 @@ class ManufacturersController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Deletes a manufacturer.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $manufacturerId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* Deletes a manufacturer.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $manufacturerId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($manufacturerId)
|
||||
{
|
||||
$this->authorize('delete', Manufacturer::class);
|
||||
// Check if the manufacturer exists
|
||||
if (is_null($manufacturer = Manufacturer::find($manufacturerId))) {
|
||||
// Redirect to the manufacturers page
|
||||
if (is_null($manufacturer = Manufacturer::withCount('models as models_count')->find($manufacturerId))) {
|
||||
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.not_found'));
|
||||
}
|
||||
|
||||
if ($manufacturer->has_models() > 0) {
|
||||
// Redirect to the asset management page
|
||||
if ($manufacturer->models_count > 0) {
|
||||
return redirect()->route('manufacturers.index')->with('error', trans('admin/manufacturers/message.assoc_users'));
|
||||
}
|
||||
|
||||
if ($manufacturer->image) {
|
||||
try {
|
||||
unlink(public_path().'/uploads/manufacturers/'.$manufacturer->image);
|
||||
Storage::disk('public')->delete('manufacturers/'.$manufacturer->image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
|
@ -219,14 +177,15 @@ class ManufacturersController extends Controller
|
|||
}
|
||||
|
||||
/**
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the manufacturers detail listing, which is generated via API.
|
||||
* This data contains a listing of all assets that belong to that manufacturer.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $manufacturerId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* Returns a view that invokes the ajax tables which actually contains
|
||||
* the content for the manufacturers detail listing, which is generated via API.
|
||||
* This data contains a listing of all assets that belong to that manufacturer.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $manufacturerId
|
||||
* @since [v1.0]
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($manufacturerId = null)
|
||||
{
|
||||
|
@ -249,6 +208,7 @@ class ManufacturersController extends Controller
|
|||
* @since [v4.1.15]
|
||||
* @param int $manufacturers_id
|
||||
* @return Redirect
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function restore($manufacturers_id)
|
||||
{
|
||||
|
|
|
@ -12,6 +12,7 @@ use Gate;
|
|||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Hash;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to User Profiles for
|
||||
|
@ -61,18 +62,38 @@ class ProfileController extends Controller
|
|||
if (Gate::allows('self.edit_location') && (!config('app.lock_passwords'))) {
|
||||
$user->location_id = $request->input('location_id');
|
||||
}
|
||||
|
||||
if (Input::file('avatar')) {
|
||||
$image = Input::file('avatar');
|
||||
$file_name = str_slug($user->first_name."-".$user->last_name).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/avatars/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(84, 84)->save($path);
|
||||
|
||||
|
||||
if ($request->input('avatar_delete') == 1) {
|
||||
$user->avatar = null;
|
||||
}
|
||||
|
||||
|
||||
if ($request->hasFile('avatar')) {
|
||||
$path = 'avatars';
|
||||
|
||||
if(!Storage::disk('public')->exists($path)) Storage::disk('public')->makeDirectory($path, 775);
|
||||
|
||||
$upload = $image = $request->file('avatar');
|
||||
$ext = $image->getClientOriginalExtension();
|
||||
$file_name = 'avatar-'.str_random(18).'.'.$ext;
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
$upload = Image::make($image->getRealPath())->resize(84, 84);
|
||||
}
|
||||
|
||||
// This requires a string instead of an object, so we use ($string)
|
||||
Storage::disk('public')->put($path.'/'.$file_name, (string)$upload->encode());
|
||||
|
||||
// Remove Current image if exists
|
||||
if (($user->avatar) && (Storage::disk('public')->exists($path.'/'.$user->avatar))) {
|
||||
Storage::disk('public')->delete($path.'/'.$user->avatar);
|
||||
}
|
||||
|
||||
$user->avatar = $file_name;
|
||||
}
|
||||
|
||||
if (Input::get('avatar_delete') == 1 && Input::file('avatar') == "") {
|
||||
$user->avatar = null;
|
||||
}
|
||||
|
||||
|
||||
if ($user->save()) {
|
||||
return redirect()->route('profile')->with('success', 'Account successfully updated');
|
||||
|
|
|
@ -7,6 +7,7 @@ use App\Models\Actionlog;
|
|||
use App\Models\Asset;
|
||||
use App\Models\AssetMaintenance;
|
||||
use App\Models\CustomField;
|
||||
use App\Models\CheckoutAcceptance;
|
||||
use App\Models\Depreciation;
|
||||
use App\Models\License;
|
||||
use App\Models\Setting;
|
||||
|
@ -31,8 +32,6 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function __construct() {
|
||||
parent::__construct();
|
||||
|
||||
$this->authorize('reports.view');
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -44,6 +43,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function getAccessoryReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
$accessories = Accessory::orderBy('created_at', 'DESC')->with('company')->get();
|
||||
return view('reports/accessories', compact('accessories'));
|
||||
}
|
||||
|
@ -59,6 +59,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function exportAccessoryReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
$accessories = Accessory::orderBy('created_at', 'DESC')->get();
|
||||
|
||||
$rows = array();
|
||||
|
@ -99,7 +100,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function getDeprecationReport()
|
||||
{
|
||||
|
||||
$this->authorize('reports.view');
|
||||
$depreciations = Depreciation::get();
|
||||
// Grab all the assets
|
||||
$assets = Asset::with( 'assignedTo', 'assetstatus', 'defaultLoc', 'location', 'assetlog', 'company', 'model.category', 'model.depreciation')
|
||||
|
@ -118,7 +119,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function exportDeprecationReport()
|
||||
{
|
||||
|
||||
$this->authorize('reports.view');
|
||||
// Grab all the assets
|
||||
$assets = Asset::with('model', 'assignedTo', 'assetstatus', 'defaultLoc', 'assetlog')
|
||||
->orderBy('created_at', 'DESC')->get();
|
||||
|
@ -172,7 +173,7 @@ class ReportsController extends Controller
|
|||
if ($asset->location) {
|
||||
$currency = e($asset->location->currency);
|
||||
} else {
|
||||
$currency = e(Setting::first()->default_currency);
|
||||
$currency = e(Setting::getSettings()->default_currency);
|
||||
}
|
||||
|
||||
$row[] = $asset->purchase_date;
|
||||
|
@ -197,6 +198,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function audit()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
return view('reports/audit');
|
||||
}
|
||||
|
||||
|
@ -210,7 +212,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function getActivityReport()
|
||||
{
|
||||
|
||||
$this->authorize('reports.view');
|
||||
return view('reports/activity');
|
||||
}
|
||||
|
||||
|
@ -224,7 +226,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function getLicenseReport()
|
||||
{
|
||||
|
||||
$this->authorize('reports.view');
|
||||
$licenses = License::with('depreciation')->orderBy('created_at', 'DESC')
|
||||
->with('company')
|
||||
->get();
|
||||
|
@ -242,6 +244,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function exportLicenseReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
$licenses = License::orderBy('created_at', 'DESC')->get();
|
||||
|
||||
$rows = [ ];
|
||||
|
@ -292,6 +295,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function getCustomReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
$customfields = CustomField::get();
|
||||
return view('reports/custom')->with('customfields', $customfields);
|
||||
}
|
||||
|
@ -306,7 +310,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function postCustom(Request $request)
|
||||
{
|
||||
|
||||
$this->authorize('reports.view');
|
||||
\Debugbar::disable();
|
||||
$customfields = CustomField::get();
|
||||
$response = new StreamedResponse(function () use ($customfields, $request) {
|
||||
|
@ -314,65 +318,65 @@ class ReportsController extends Controller
|
|||
// Open output stream
|
||||
$handle = fopen('php://output', 'w');
|
||||
|
||||
if ($request->has('use_bom')) {
|
||||
if ($request->filled('use_bom')) {
|
||||
fprintf($handle, chr(0xEF) . chr(0xBB) . chr(0xBF));
|
||||
}
|
||||
|
||||
$header = [];
|
||||
|
||||
|
||||
if ($request->has('company')) {
|
||||
if ($request->filled('company')) {
|
||||
$header[] = trans('general.company');
|
||||
}
|
||||
|
||||
if ($request->has('asset_name')) {
|
||||
if ($request->filled('asset_name')) {
|
||||
$header[] = trans('admin/hardware/form.name');
|
||||
}
|
||||
|
||||
if ($request->has('asset_tag')) {
|
||||
if ($request->filled('asset_tag')) {
|
||||
$header[] = trans('admin/hardware/table.asset_tag');
|
||||
}
|
||||
|
||||
if ($request->has('model')) {
|
||||
if ($request->filled('model')) {
|
||||
$header[] = trans('admin/hardware/form.model');
|
||||
$header[] = trans('general.model_no');
|
||||
}
|
||||
|
||||
if ($request->has('category')) {
|
||||
if ($request->filled('category')) {
|
||||
$header[] = trans('general.category');
|
||||
}
|
||||
|
||||
if ($request->has('manufacturer')) {
|
||||
if ($request->filled('manufacturer')) {
|
||||
$header[] = trans('admin/hardware/form.manufacturer');
|
||||
}
|
||||
|
||||
if ($request->has('serial')) {
|
||||
if ($request->filled('serial')) {
|
||||
$header[] = trans('admin/hardware/table.serial');
|
||||
}
|
||||
if ($request->has('purchase_date')) {
|
||||
if ($request->filled('purchase_date')) {
|
||||
$header[] = trans('admin/hardware/table.purchase_date');
|
||||
}
|
||||
|
||||
if (($request->has('purchase_cost')) || ($request->has('depreciation'))) {
|
||||
if (($request->filled('purchase_cost')) || ($request->filled('depreciation'))) {
|
||||
$header[] = trans('admin/hardware/table.purchase_cost');
|
||||
}
|
||||
|
||||
if ($request->has('eol')) {
|
||||
if ($request->filled('eol')) {
|
||||
$header[] = trans('admin/hardware/table.eol');
|
||||
}
|
||||
|
||||
if ($request->has('order')) {
|
||||
if ($request->filled('order')) {
|
||||
$header[] = trans('admin/hardware/form.order');
|
||||
}
|
||||
|
||||
if ($request->has('supplier')) {
|
||||
if ($request->filled('supplier')) {
|
||||
$header[] = trans('general.supplier');
|
||||
}
|
||||
|
||||
if ($request->has('location')) {
|
||||
if ($request->filled('location')) {
|
||||
$header[] = trans('admin/hardware/table.location');
|
||||
}
|
||||
if ($request->has('location_address')) {
|
||||
if ($request->filled('location_address')) {
|
||||
$header[] = trans('general.address');
|
||||
$header[] = trans('general.address');
|
||||
$header[] = trans('general.city');
|
||||
|
@ -381,11 +385,11 @@ class ReportsController extends Controller
|
|||
$header[] = trans('general.zip');
|
||||
}
|
||||
|
||||
if ($request->has('rtd_location')) {
|
||||
if ($request->filled('rtd_location')) {
|
||||
$header[] = trans('admin/hardware/form.default_location');
|
||||
}
|
||||
|
||||
if ($request->has('rtd_location_address')) {
|
||||
if ($request->filled('rtd_location_address')) {
|
||||
$header[] = trans('general.address');
|
||||
$header[] = trans('general.address');
|
||||
$header[] = trans('general.city');
|
||||
|
@ -395,65 +399,66 @@ class ReportsController extends Controller
|
|||
}
|
||||
|
||||
|
||||
if ($request->has('assigned_to')) {
|
||||
if ($request->filled('assigned_to')) {
|
||||
$header[] = trans('admin/hardware/table.checkoutto');
|
||||
$header[] = trans('general.type');
|
||||
}
|
||||
|
||||
if ($request->has('username')) {
|
||||
if ($request->filled('username')) {
|
||||
$header[] = 'Username';
|
||||
}
|
||||
|
||||
if ($request->has('employee_num')) {
|
||||
if ($request->filled('employee_num')) {
|
||||
$header[] = 'Employee No.';
|
||||
}
|
||||
|
||||
if ($request->has('manager')) {
|
||||
if ($request->filled('manager')) {
|
||||
$header[] = trans('admin/users/table.manager');
|
||||
}
|
||||
|
||||
if ($request->has('department')) {
|
||||
if ($request->filled('department')) {
|
||||
$header[] = trans('general.department');
|
||||
}
|
||||
|
||||
if ($request->has('status')) {
|
||||
if ($request->filled('status')) {
|
||||
$header[] = trans('general.status');
|
||||
}
|
||||
|
||||
if ($request->has('warranty')) {
|
||||
if ($request->filled('warranty')) {
|
||||
$header[] = 'Warranty';
|
||||
$header[] = 'Warranty Expires';
|
||||
}
|
||||
if ($request->has('depreciation')) {
|
||||
if ($request->filled('depreciation')) {
|
||||
$header[] = 'Value';
|
||||
$header[] = 'Diff';
|
||||
$header[] = 'Fully Depreciated';
|
||||
}
|
||||
|
||||
if ($request->has('checkout_date')) {
|
||||
if ($request->filled('checkout_date')) {
|
||||
$header[] = trans('admin/hardware/table.checkout_date');
|
||||
}
|
||||
|
||||
if ($request->has('expected_checkin')) {
|
||||
if ($request->filled('expected_checkin')) {
|
||||
$header[] = trans('admin/hardware/form.expected_checkin');
|
||||
}
|
||||
|
||||
if ($request->has('created_at')) {
|
||||
if ($request->filled('created_at')) {
|
||||
$header[] = trans('general.created_at');
|
||||
}
|
||||
|
||||
if ($request->has('updated_at')) {
|
||||
if ($request->filled('updated_at')) {
|
||||
$header[] = trans('general.updated_at');
|
||||
}
|
||||
|
||||
if ($request->has('last_audit_date')) {
|
||||
if ($request->filled('last_audit_date')) {
|
||||
$header[] = trans('general.last_audit');
|
||||
}
|
||||
|
||||
if ($request->has('next_audit_date')) {
|
||||
if ($request->filled('next_audit_date')) {
|
||||
$header[] = trans('general.next_audit_date');
|
||||
}
|
||||
|
||||
if ($request->has('notes')) {
|
||||
if ($request->filled('notes')) {
|
||||
$header[] = trans('general.notes');
|
||||
}
|
||||
|
||||
|
@ -471,52 +476,57 @@ class ReportsController extends Controller
|
|||
'location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
|
||||
'model.category', 'model.manufacturer','supplier');
|
||||
|
||||
if ($request->has('by_location_id')) {
|
||||
if ($request->filled('by_location_id')) {
|
||||
$assets->where('assets.location_id', $request->input('by_location_id'));
|
||||
}
|
||||
|
||||
if ($request->has('by_rtd_location_id')) {
|
||||
if ($request->filled('by_rtd_location_id')) {
|
||||
\Log::debug('RTD location should match: '.$request->input('by_rtd_location_id'));
|
||||
$assets->where('assets.rtd_location_id', $request->input('by_rtd_location_id'));
|
||||
}
|
||||
|
||||
if ($request->has('by_supplier_id')) {
|
||||
if ($request->filled('by_supplier_id')) {
|
||||
$assets->where('assets.supplier_id', $request->input('by_supplier_id'));
|
||||
}
|
||||
|
||||
if ($request->has('by_company_id')) {
|
||||
if ($request->filled('by_company_id')) {
|
||||
$assets->where('assets.company_id', $request->input('by_company_id'));
|
||||
}
|
||||
|
||||
if ($request->has('by_model_id')) {
|
||||
if ($request->filled('by_model_id')) {
|
||||
$assets->where('assets.model_id', $request->input('by_model_id'));
|
||||
}
|
||||
|
||||
if ($request->has('by_category_id')) {
|
||||
if ($request->filled('by_category_id')) {
|
||||
$assets->InCategory($request->input('by_category_id'));
|
||||
}
|
||||
|
||||
if ($request->has('by_manufacturer_id')) {
|
||||
if ($request->filled('by_dept_id')) {
|
||||
\Log::debug('Only users in dept '.$request->input('by_dept_id'));
|
||||
$assets->CheckedOutToTargetInDepartment($request->input('by_dept_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('by_manufacturer_id')) {
|
||||
$assets->ByManufacturer($request->input('by_manufacturer_id'));
|
||||
}
|
||||
|
||||
if ($request->has('by_order_number')) {
|
||||
if ($request->filled('by_order_number')) {
|
||||
$assets->where('assets.order_number', $request->input('by_order_number'));
|
||||
}
|
||||
|
||||
if ($request->has('by_status_id')) {
|
||||
if ($request->filled('by_status_id')) {
|
||||
$assets->where('assets.status_id', $request->input('by_status_id'));
|
||||
}
|
||||
|
||||
if (($request->has('purchase_start')) && ($request->has('purchase_end'))) {
|
||||
if (($request->filled('purchase_start')) && ($request->filled('purchase_end'))) {
|
||||
$assets->whereBetween('assets.purchase_date', [$request->input('purchase_start'), $request->input('purchase_end')]);
|
||||
}
|
||||
|
||||
if (($request->has('created_start')) && ($request->has('created_end'))) {
|
||||
if (($request->filled('created_start')) && ($request->filled('created_end'))) {
|
||||
$assets->whereBetween('assets.created_at', [$request->input('created_start'), $request->input('created_end')]);
|
||||
}
|
||||
|
||||
if (($request->has('expected_checkin_start')) && ($request->has('expected_checkin_end'))) {
|
||||
if (($request->filled('expected_checkin_start')) && ($request->filled('expected_checkin_end'))) {
|
||||
$assets->whereBetween('assets.expected_checkin', [$request->input('expected_checkin_start'), $request->input('expected_checkin_end')]);
|
||||
}
|
||||
|
||||
|
@ -525,61 +535,61 @@ class ReportsController extends Controller
|
|||
foreach ($assets as $asset) {
|
||||
$row = [];
|
||||
|
||||
if ($request->has('company')) {
|
||||
if ($request->filled('company')) {
|
||||
$row[] = ($asset->company) ? $asset->company->name : '';
|
||||
}
|
||||
|
||||
if ($request->has('asset_name')) {
|
||||
if ($request->filled('asset_name')) {
|
||||
$row[] = ($asset->name) ? $asset->name : '';
|
||||
}
|
||||
|
||||
if ($request->has('asset_tag')) {
|
||||
if ($request->filled('asset_tag')) {
|
||||
$row[] = ($asset->asset_tag) ? $asset->asset_tag : '';
|
||||
}
|
||||
|
||||
if ($request->has('model')) {
|
||||
if ($request->filled('model')) {
|
||||
$row[] = ($asset->model) ? $asset->model->name : '';
|
||||
$row[] = ($asset->model) ? $asset->model->model_number : '';
|
||||
}
|
||||
|
||||
if ($request->has('category')) {
|
||||
if ($request->filled('category')) {
|
||||
$row[] = (($asset->model) && ($asset->model->category)) ? $asset->model->category->name : '';
|
||||
}
|
||||
|
||||
if ($request->has('manufacturer')) {
|
||||
if ($request->filled('manufacturer')) {
|
||||
$row[] = ($asset->model && $asset->model->manufacturer) ? $asset->model->manufacturer->name : '';
|
||||
}
|
||||
|
||||
if ($request->has('serial')) {
|
||||
if ($request->filled('serial')) {
|
||||
$row[] = ($asset->serial) ? $asset->serial : '';
|
||||
}
|
||||
|
||||
if ($request->has('purchase_date')) {
|
||||
if ($request->filled('purchase_date')) {
|
||||
$row[] = ($asset->purchase_date) ? $asset->purchase_date : '';
|
||||
}
|
||||
|
||||
if ($request->has('purchase_cost')) {
|
||||
if ($request->filled('purchase_cost')) {
|
||||
$row[] = ($asset->purchase_cost) ? Helper::formatCurrencyOutput($asset->purchase_cost) : '';
|
||||
}
|
||||
|
||||
if ($request->has('eol')) {
|
||||
if ($request->filled('eol')) {
|
||||
$row[] = ($asset->purchase_date!='') ? $asset->present()->eol_date() : '';
|
||||
}
|
||||
|
||||
if ($request->has('order')) {
|
||||
if ($request->filled('order')) {
|
||||
$row[] = ($asset->order_number) ? $asset->order_number : '';
|
||||
}
|
||||
|
||||
if ($request->has('supplier')) {
|
||||
if ($request->filled('supplier')) {
|
||||
$row[] = ($asset->supplier) ? $asset->supplier->name : '';
|
||||
}
|
||||
|
||||
|
||||
if ($request->has('location')) {
|
||||
if ($request->filled('location')) {
|
||||
$row[] = ($asset->location) ? $asset->location->present()->name() : '';
|
||||
}
|
||||
|
||||
if ($request->has('location_address')) {
|
||||
if ($request->filled('location_address')) {
|
||||
$row[] = ($asset->location) ? $asset->location->address : '';
|
||||
$row[] = ($asset->location) ? $asset->location->address2 : '';
|
||||
$row[] = ($asset->location) ? $asset->location->city : '';
|
||||
|
@ -588,11 +598,11 @@ class ReportsController extends Controller
|
|||
$row[] = ($asset->location) ? $asset->location->zip : '';
|
||||
}
|
||||
|
||||
if ($request->has('rtd_location')) {
|
||||
if ($request->filled('rtd_location')) {
|
||||
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->present()->name() : '';
|
||||
}
|
||||
|
||||
if ($request->has('rtd_location_address')) {
|
||||
if ($request->filled('rtd_location_address')) {
|
||||
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->address : '';
|
||||
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->address2 : '';
|
||||
$row[] = ($asset->defaultLoc) ? $asset->defaultLoc->city : '';
|
||||
|
@ -602,12 +612,12 @@ class ReportsController extends Controller
|
|||
}
|
||||
|
||||
|
||||
if ($request->has('assigned_to')) {
|
||||
if ($request->filled('assigned_to')) {
|
||||
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? $asset->assigned->getFullNameAttribute() : ($asset->assigned ? $asset->assigned->display_name : '');
|
||||
$row[] = ($asset->checkedOutToUser() && $asset->assigned) ? 'user' : $asset->assignedType();
|
||||
}
|
||||
|
||||
if ($request->has('username')) {
|
||||
if ($request->filled('username')) {
|
||||
// Only works if we're checked out to a user, not anything else.
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->username : '';
|
||||
|
@ -616,7 +626,7 @@ class ReportsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
if ($request->has('employee_num')) {
|
||||
if ($request->filled('employee_num')) {
|
||||
// Only works if we're checked out to a user, not anything else.
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = ($asset->assignedto) ? $asset->assignedto->employee_num : '';
|
||||
|
@ -625,7 +635,7 @@ class ReportsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
if ($request->has('manager')) {
|
||||
if ($request->filled('manager')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = (($asset->assignedto) && ($asset->assignedto->manager)) ? $asset->assignedto->manager->present()->fullName : '';
|
||||
} else {
|
||||
|
@ -634,7 +644,7 @@ class ReportsController extends Controller
|
|||
}
|
||||
|
||||
|
||||
if ($request->has('department')) {
|
||||
if ($request->filled('department')) {
|
||||
if ($asset->checkedOutToUser()) {
|
||||
$row[] = (($asset->assignedto) && ($asset->assignedto->department)) ? $asset->assignedto->department->name : '';
|
||||
} else {
|
||||
|
@ -642,55 +652,56 @@ class ReportsController extends Controller
|
|||
}
|
||||
}
|
||||
|
||||
if ($request->has('status')) {
|
||||
if ($request->filled('status')) {
|
||||
$row[] = ($asset->assetstatus) ? $asset->assetstatus->name.' ('.$asset->present()->statusMeta.')' : '';
|
||||
}
|
||||
|
||||
|
||||
if ($request->has('warranty')) {
|
||||
if ($request->filled('warranty')) {
|
||||
$row[] = ($asset->warranty_months) ? $asset->warranty_months : '';
|
||||
$row[] = $asset->present()->warrantee_expires();
|
||||
}
|
||||
|
||||
|
||||
if ($request->has('depreciation')) {
|
||||
if ($request->filled('depreciation')) {
|
||||
$depreciation = $asset->getDepreciatedValue();
|
||||
$diff = ($asset->purchase_cost - $depreciation);
|
||||
$row[] = Helper::formatCurrencyOutput($depreciation);
|
||||
$row[] = Helper::formatCurrencyOutput($diff);
|
||||
$row[] = ($asset->depreciated_date()!='') ? $asset->depreciated_date()->format('Y-m-d') : '';
|
||||
}
|
||||
|
||||
if ($request->has('checkout_date')) {
|
||||
if ($request->filled('checkout_date')) {
|
||||
$row[] = ($asset->last_checkout) ? $asset->last_checkout : '';
|
||||
}
|
||||
|
||||
if ($request->has('expected_checkin')) {
|
||||
if ($request->filled('expected_checkin')) {
|
||||
$row[] = ($asset->expected_checkin) ? $asset->expected_checkin : '';
|
||||
}
|
||||
|
||||
if ($request->has('created_at')) {
|
||||
if ($request->filled('created_at')) {
|
||||
$row[] = ($asset->created_at) ? $asset->created_at : '';
|
||||
}
|
||||
|
||||
if ($request->has('updated_at')) {
|
||||
if ($request->filled('updated_at')) {
|
||||
$row[] = ($asset->updated_at) ? $asset->updated_at : '';
|
||||
}
|
||||
|
||||
if ($request->has('last_audit_date')) {
|
||||
if ($request->filled('last_audit_date')) {
|
||||
$row[] = ($asset->last_audit_date) ? $asset->last_audit_date : '';
|
||||
}
|
||||
|
||||
if ($request->has('next_audit_date')) {
|
||||
if ($request->filled('next_audit_date')) {
|
||||
$row[] = ($asset->next_audit_date) ? $asset->next_audit_date : '';
|
||||
}
|
||||
|
||||
if ($request->has('notes')) {
|
||||
if ($request->filled('notes')) {
|
||||
$row[] = ($asset->notes) ? $asset->notes : '';
|
||||
}
|
||||
|
||||
foreach ($customfields as $customfield) {
|
||||
$column_name = $customfield->db_column_name();
|
||||
if ($request->has($customfield->db_column_name())) {
|
||||
if ($request->filled($customfield->db_column_name())) {
|
||||
$row[] = $asset->$column_name;
|
||||
}
|
||||
}
|
||||
|
@ -721,6 +732,7 @@ 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')
|
||||
|
@ -739,6 +751,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function exportAssetMaintenancesReport()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
// Grab all the improvements
|
||||
$assetMaintenances = AssetMaintenance::with('asset', 'supplier')
|
||||
->orderBy('created_at', 'DESC')
|
||||
|
@ -799,7 +812,21 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function getAssetAcceptanceReport()
|
||||
{
|
||||
$assetsForReport = Asset::notYetAccepted()->with('company')->get();
|
||||
$this->authorize('reports.view');
|
||||
|
||||
/**
|
||||
* Get all assets with pending checkout acceptances
|
||||
*/
|
||||
|
||||
$acceptances = CheckoutAcceptance::pending()->get();
|
||||
|
||||
$assetsForReport = $acceptances
|
||||
->filter(function($acceptance) {
|
||||
return $acceptance->checkoutable_type == 'App\Models\Asset';
|
||||
})
|
||||
->map(function($acceptance) {
|
||||
return $acceptance->checkoutable;
|
||||
});
|
||||
|
||||
return view('reports/unaccepted_assets', compact('assetsForReport'));
|
||||
}
|
||||
|
@ -813,7 +840,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
public function exportAssetAcceptanceReport()
|
||||
{
|
||||
|
||||
$this->authorize('reports.view');
|
||||
// Grab all the improvements
|
||||
$assetsForReport = Actionlog::whereIn('id', $this->getAssetsNotAcceptedYet())
|
||||
->get();
|
||||
|
@ -862,6 +889,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
protected function getCheckedOutAssetsRequiringAcceptance($modelsInCategoriesThatRequireAcceptance)
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
$assets = Asset::deployed()
|
||||
->inModelList($modelsInCategoriesThatRequireAcceptance)
|
||||
->select('id')
|
||||
|
@ -881,7 +909,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
protected function getModelsInCategoriesThatRequireAcceptance($assetCategoriesRequiringAcceptance)
|
||||
{
|
||||
|
||||
$this->authorize('reports.view');
|
||||
return array_pluck(Model::inCategory($assetCategoriesRequiringAcceptance)
|
||||
->select('id')
|
||||
->get()
|
||||
|
@ -897,7 +925,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
protected function getCategoriesThatRequireAcceptance()
|
||||
{
|
||||
|
||||
$this->authorize('reports.view');
|
||||
return array_pluck(Category::requiresAcceptance()
|
||||
->select('id')
|
||||
->get()
|
||||
|
@ -913,7 +941,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
protected function getAssetsCheckedOutRequiringAcceptance()
|
||||
{
|
||||
|
||||
$this->authorize('reports.view');
|
||||
return $this->getCheckedOutAssetsRequiringAcceptance(
|
||||
$this->getModelsInCategoriesThatRequireAcceptance($this->getCategoriesThatRequireAcceptance())
|
||||
);
|
||||
|
@ -928,6 +956,7 @@ class ReportsController extends Controller
|
|||
*/
|
||||
protected function getAssetsNotAcceptedYet()
|
||||
{
|
||||
$this->authorize('reports.view');
|
||||
return Asset::unaccepted();
|
||||
}
|
||||
}
|
||||
|
|
File diff suppressed because it is too large
Load diff
|
@ -1,21 +1,12 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use Input;
|
||||
use Lang;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\Asset;
|
||||
use Redirect;
|
||||
use DB;
|
||||
use App\Models\Setting;
|
||||
use Str;
|
||||
use View;
|
||||
use App\Helpers\Helper;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Status Labels for
|
||||
* the Snipe-IT Asset Management application.
|
||||
|
@ -28,6 +19,7 @@ class StatuslabelsController extends Controller
|
|||
* Show a list of all the statuslabels.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
|
||||
public function index()
|
||||
|
@ -43,25 +35,25 @@ class StatuslabelsController extends Controller
|
|||
return view('statuslabels.view')->with('statuslabel', $statuslabel);
|
||||
}
|
||||
|
||||
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist', compact('id')));
|
||||
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist'));
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Statuslabel create.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
// Show the page
|
||||
$this->authorize('create', Statuslabel::class);
|
||||
$item = new Statuslabel;
|
||||
$use_statuslabel_type = $item->getStatuslabelType();
|
||||
$statuslabel_types = Helper::statusTypeList();
|
||||
|
||||
return view('statuslabels/edit', compact('statuslabel_types', 'item'))->with('use_statuslabel_type', $use_statuslabel_type);
|
||||
return view('statuslabels/edit')
|
||||
->with('item', new Statuslabel)
|
||||
->with('statuslabel_types', Helper::statusTypeList())
|
||||
->with('use_statuslabel_type', (new Statuslabel)->getStatuslabelType());
|
||||
}
|
||||
|
||||
|
||||
|
@ -70,6 +62,7 @@ class StatuslabelsController extends Controller
|
|||
*
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
|
@ -78,7 +71,7 @@ class StatuslabelsController extends Controller
|
|||
// create a new model instance
|
||||
$statusLabel = new Statuslabel();
|
||||
|
||||
if (!$request->has('statuslabel_types')) {
|
||||
if (!$request->filled('statuslabel_types')) {
|
||||
return redirect()->back()->withInput()->withErrors(['statuslabel_types' => trans('validation.statuslabel_type')]);
|
||||
}
|
||||
|
||||
|
@ -106,8 +99,9 @@ class StatuslabelsController extends Controller
|
|||
/**
|
||||
* Statuslabel update.
|
||||
*
|
||||
* @param int $statuslabelId
|
||||
* @param int $statuslabelId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($statuslabelId = null)
|
||||
{
|
||||
|
@ -129,8 +123,9 @@ class StatuslabelsController extends Controller
|
|||
/**
|
||||
* Statuslabel update form processing page.
|
||||
*
|
||||
* @param int $statuslabelId
|
||||
* @param int $statuslabelId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update(Request $request, $statuslabelId = null)
|
||||
{
|
||||
|
@ -141,7 +136,7 @@ class StatuslabelsController extends Controller
|
|||
return redirect()->route('statuslabels.index')->with('error', trans('admin/statuslabels/message.does_not_exist'));
|
||||
}
|
||||
|
||||
if (!$request->has('statuslabel_types')) {
|
||||
if (!$request->filled('statuslabel_types')) {
|
||||
return redirect()->back()->withInput()->withErrors(['statuslabel_types' => trans('validation.statuslabel_type')]);
|
||||
}
|
||||
|
||||
|
@ -169,8 +164,9 @@ class StatuslabelsController extends Controller
|
|||
/**
|
||||
* Delete the given Statuslabel.
|
||||
*
|
||||
* @param int $statuslabelId
|
||||
* @param int $statuslabelId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($statuslabelId)
|
||||
{
|
||||
|
|
|
@ -1,21 +1,12 @@
|
|||
<?php
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use Image;
|
||||
use App\Models\AssetMaintenance;
|
||||
use Input;
|
||||
use Lang;
|
||||
use App\Models\Supplier;
|
||||
use Redirect;
|
||||
use App\Models\Setting;
|
||||
use Str;
|
||||
use View;
|
||||
use Auth;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Suppliers for
|
||||
|
@ -29,6 +20,7 @@ class SuppliersController extends Controller
|
|||
* Show a list of all suppliers
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function index()
|
||||
{
|
||||
|
@ -44,6 +36,7 @@ class SuppliersController extends Controller
|
|||
* Supplier create.
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
|
@ -55,8 +48,9 @@ class SuppliersController extends Controller
|
|||
/**
|
||||
* Supplier create form processing.
|
||||
*
|
||||
* @param Request $request
|
||||
* @param ImageUploadRequest $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(ImageUploadRequest $request)
|
||||
{
|
||||
|
@ -79,16 +73,7 @@ class SuppliersController extends Controller
|
|||
$supplier->url = $supplier->addhttp(request('url'));
|
||||
$supplier->user_id = Auth::id();
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = str_random(25).".".$image->getClientOriginalExtension();
|
||||
$path = public_path('uploads/suppliers/'.$file_name);
|
||||
Image::make($image->getRealPath())->resize(200, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save($path);
|
||||
$supplier->image = $file_name;
|
||||
}
|
||||
$supplier = $request->handleImages($supplier);
|
||||
|
||||
if ($supplier->save()) {
|
||||
return redirect()->route('suppliers.index')->with('success', trans('admin/suppliers/message.create.success'));
|
||||
|
@ -99,8 +84,9 @@ class SuppliersController extends Controller
|
|||
/**
|
||||
* Supplier update.
|
||||
*
|
||||
* @param int $supplierId
|
||||
* @param int $supplierId
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit($supplierId = null)
|
||||
{
|
||||
|
@ -119,8 +105,9 @@ class SuppliersController extends Controller
|
|||
/**
|
||||
* Supplier update form processing page.
|
||||
*
|
||||
* @param int $supplierId
|
||||
* @param int $supplierId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function update($supplierId = null, ImageUploadRequest $request)
|
||||
{
|
||||
|
@ -146,37 +133,7 @@ class SuppliersController extends Controller
|
|||
$supplier->url = $supplier->addhttp(request('url'));
|
||||
$supplier->notes = request('notes');
|
||||
|
||||
|
||||
$old_image = $supplier->image;
|
||||
|
||||
// Set the model's image property to null if the image is being deleted
|
||||
if ($request->input('image_delete') == 1) {
|
||||
$supplier->image = null;
|
||||
}
|
||||
|
||||
if ($request->file('image')) {
|
||||
$image = $request->file('image');
|
||||
$file_name = $supplier->id.'-'.str_slug($image->getClientOriginalName()) . "." . $image->getClientOriginalExtension();
|
||||
|
||||
if ($image->getClientOriginalExtension()!='svg') {
|
||||
Image::make($image->getRealPath())->resize(500, null, function ($constraint) {
|
||||
$constraint->aspectRatio();
|
||||
$constraint->upsize();
|
||||
})->save(app('suppliers_upload_path').$file_name);
|
||||
} else {
|
||||
$image->move(app('suppliers_upload_path'), $file_name);
|
||||
}
|
||||
$supplier->image = $file_name;
|
||||
|
||||
}
|
||||
|
||||
if ((($request->file('image')) && (isset($old_image)) && ($old_image!='')) || ($request->input('image_delete') == 1)) {
|
||||
try {
|
||||
unlink(app('suppliers_upload_path').$old_image);
|
||||
} catch (\Exception $e) {
|
||||
\Log::error($e);
|
||||
}
|
||||
}
|
||||
$supplier = $request->handleImages($supplier);
|
||||
|
||||
|
||||
if ($supplier->save()) {
|
||||
|
@ -190,13 +147,14 @@ class SuppliersController extends Controller
|
|||
/**
|
||||
* Delete the given supplier.
|
||||
*
|
||||
* @param int $supplierId
|
||||
* @param int $supplierId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($supplierId)
|
||||
{
|
||||
$this->authorize('delete', Supplier::class);
|
||||
if (is_null($supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances','assets','licenses')->find($supplierId))) {
|
||||
if (is_null($supplier = Supplier::with('asset_maintenances', 'assets', 'licenses')->withCount('asset_maintenances as asset_maintenances_count','assets as assets_count','licenses as licenses_count')->find($supplierId))) {
|
||||
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.not_found'));
|
||||
}
|
||||
|
||||
|
@ -236,11 +194,8 @@ class SuppliersController extends Controller
|
|||
if (isset($supplier->id)) {
|
||||
return view('suppliers/view', compact('supplier'));
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/suppliers/message.does_not_exist', compact('id'));
|
||||
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('suppliers.index')->with('error', $error);
|
||||
return redirect()->route('suppliers.index')->with('error', trans('admin/suppliers/message.does_not_exist'));
|
||||
}
|
||||
|
||||
}
|
||||
|
|
229
app/Http/Controllers/Users/BulkUsersController.php
Normal file
229
app/Http/Controllers/Users/BulkUsersController.php
Normal file
|
@ -0,0 +1,229 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Group;
|
||||
use App\Models\LicenseSeat;
|
||||
use App\Models\User;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
|
||||
class BulkUsersController extends Controller
|
||||
{
|
||||
|
||||
/**
|
||||
* Returns a view that confirms the user's a bulk delete will be applied to.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.7]
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function edit(Request $request)
|
||||
{
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
// Make sure there were users selected
|
||||
if (($request->filled('ids')) && (count($request->input('ids')) > 0)) {
|
||||
|
||||
$statuslabel_list = Helper::statusLabelList();
|
||||
|
||||
// Get the list of affected users
|
||||
$users = User::whereIn('id', array_keys(request('ids')))
|
||||
->with('groups', 'assets', 'licenses', 'accessories')->get();
|
||||
|
||||
if ($request->input('bulk_actions') == 'edit') {
|
||||
return view('users/bulk-edit', compact('users'))
|
||||
->with('groups', Group::pluck('name', 'id'));
|
||||
|
||||
} elseif ($request->input('bulk_actions') == 'delete') {
|
||||
return view('users/confirm-bulk-delete', compact('users', 'statuslabel_list'));
|
||||
|
||||
} elseif ($request->input('bulk_actions') == 'bulkpasswordreset') {
|
||||
if ($users) {
|
||||
foreach ($users as $user) {
|
||||
if (($user->activated=='1') && ($user->email!='')) {
|
||||
$credentials = ['email' => $user->email];
|
||||
Password::sendResetLink($credentials, function (Message $message) {
|
||||
$message->subject($this->getEmailSubject());
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
return redirect()->back()->with('success', trans('admin/users/message.password_resets_sent'));
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', 'No users selected');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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 update(Request $request)
|
||||
{
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
if((!$request->filled('ids')) || $request->input('ids') <= 0) {
|
||||
return redirect()->back()->with('error', 'No users selected');
|
||||
}
|
||||
$user_raw_array = $request->input('ids');
|
||||
|
||||
// Remove the user from any updates.
|
||||
$user_raw_array = array_diff($user_raw_array, [Auth::id()]);
|
||||
$manager_conflict = false;
|
||||
$users = User::whereIn('id', $user_raw_array)->where('id', '!=', Auth::user()->id)->get();
|
||||
|
||||
$return_array = [
|
||||
'success' => trans('admin/users/message.success.update_bulk')
|
||||
];
|
||||
|
||||
|
||||
$this->conditionallyAddItem('location_id')
|
||||
->conditionallyAddItem('department_id')
|
||||
->conditionallyAddItem('company_id')
|
||||
->conditionallyAddItem('locale')
|
||||
->conditionallyAddItem('activated')
|
||||
;
|
||||
// If the manager_id is one of the users being updated, generate a warning.
|
||||
if (array_search($request->input('manager_id'), $user_raw_array)) {
|
||||
$manager_conflict = true;
|
||||
$return_array = [
|
||||
'warning' => trans('admin/users/message.bulk_manager_warn')
|
||||
];
|
||||
}
|
||||
if (!$manager_conflict) {
|
||||
$this->conditionallyAddItem('manager_id');
|
||||
}
|
||||
|
||||
|
||||
// Save the updated info
|
||||
User::whereIn('id', $user_raw_array)
|
||||
->where('id', '!=', Auth::id())->update($this->update_array);
|
||||
|
||||
// Only sync groups if groups were selected
|
||||
if ($request->filled('groups')) {
|
||||
foreach ($users as $user) {
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')
|
||||
->with($return_array);
|
||||
}
|
||||
|
||||
/**
|
||||
* Array to store update data per item
|
||||
* @var Array
|
||||
*/
|
||||
private $update_array = [];
|
||||
|
||||
/**
|
||||
* Adds parameter to update array for an item if it exists in request
|
||||
* @param String $field field name
|
||||
* @return BulkUsersController Model for Chaining
|
||||
*/
|
||||
protected function conditionallyAddItem($field)
|
||||
{
|
||||
if(request()->filled($field)) {
|
||||
$this->update_array[$field] = request()->input($field);
|
||||
}
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* Soft-delete bulk users
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param Request $request
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy(Request $request)
|
||||
{
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
if ((!$request->filled('ids')) || (count($request->input('ids')) == 0)) {
|
||||
return redirect()->back()->with('error', 'No users selected');
|
||||
}
|
||||
if ((!$request->filled('status_id')) || ($request->input('status_id')=='')) {
|
||||
return redirect()->route('users.index')->with('error', 'No status selected');
|
||||
}
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('users.index')->with('error', 'Bulk delete is not enabled in this installation');
|
||||
}
|
||||
$user_raw_array = request('ids');
|
||||
|
||||
if (($key = array_search(Auth::id(), $user_raw_array)) !== false) {
|
||||
unset($user_raw_array[$key]);
|
||||
}
|
||||
|
||||
$users = User::whereIn('id', $user_raw_array)->get();
|
||||
$assets = Asset::whereIn('assigned_to', $user_raw_array)->get();
|
||||
$accessories = DB::table('accessories_users')->whereIn('assigned_to', $user_raw_array)->get();
|
||||
$licenses = DB::table('license_seats')->whereIn('assigned_to', $user_raw_array)->get();
|
||||
|
||||
|
||||
$this->logItemCheckinAndDelete($assets, Asset::class);
|
||||
$this->logItemCheckinAndDelete($accessories, Accessory::class);
|
||||
$this->logItemCheckinAndDelete($licenses, LicenseSeat::class);
|
||||
|
||||
Asset::whereIn('id', $assets->pluck('id'))->update([
|
||||
'status_id' => e(request('status_id')),
|
||||
'assigned_to' => null,
|
||||
'assigned_type' => null,
|
||||
]);
|
||||
|
||||
|
||||
LicenseSeat::whereIn('id', $licenses->pluck('id'))->update(['assigned_to' => null]);
|
||||
|
||||
foreach ($users as $user) {
|
||||
$user->accessories()->sync([]);
|
||||
$user->delete();
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')->with('success', 'Your selected users have been deleted and their assets have been updated.');
|
||||
}
|
||||
|
||||
/**
|
||||
* Generate an action log entry for each of a group of items.
|
||||
* @param $items
|
||||
* @param $itemType string name of items being passed.
|
||||
*/
|
||||
protected function logItemCheckinAndDelete($items, $itemType) {
|
||||
|
||||
foreach($items as $item) {
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $item->id;
|
||||
// We can't rely on get_class here because the licenses/accessories fetched above are not eloquent models, but simply arrays.
|
||||
$logAction->item_type = $itemType;
|
||||
$logAction->target_id = $item->assigned_to;
|
||||
$logAction->target_type = User::class;
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->note = 'Bulk checkin items and delete user';
|
||||
$logAction->logaction('checkin from');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
85
app/Http/Controllers/Users/LDAPImportController.php
Normal file
85
app/Http/Controllers/Users/LDAPImportController.php
Normal file
|
@ -0,0 +1,85 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Models\Ldap;
|
||||
use App\Services\LdapAd;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Controllers\Controller;
|
||||
use Illuminate\Support\Facades\Artisan;
|
||||
|
||||
class LDAPImportController extends Controller
|
||||
{
|
||||
/**
|
||||
* An Ldap instance.
|
||||
*
|
||||
* @var LdapAd
|
||||
*/
|
||||
protected $ldap;
|
||||
|
||||
/**
|
||||
* __construct.
|
||||
*
|
||||
* @param LdapAd $ldap
|
||||
*/
|
||||
public function __construct(LdapAd $ldap)
|
||||
{
|
||||
parent::__construct();
|
||||
$this->ldap = $ldap;
|
||||
$this->ldap->init();
|
||||
}
|
||||
|
||||
/**
|
||||
* Return view for LDAP import.
|
||||
*
|
||||
* @author Aladin Alaily
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return \Illuminate\Contracts\View\View
|
||||
*
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function create()
|
||||
{
|
||||
$this->authorize('update', User::class);
|
||||
try {
|
||||
$this->ldap->testLdapAdUserConnection();
|
||||
} catch (\Exception $e) {
|
||||
return redirect()->route('users.index')->with('error', $e->getMessage());
|
||||
}
|
||||
|
||||
return view('users/ldap');
|
||||
}
|
||||
|
||||
/**
|
||||
* LDAP form processing.
|
||||
*
|
||||
* @author Aladin Alaily
|
||||
* @author Wes Hulette <jwhulette@gmail.com>
|
||||
*
|
||||
* @since 5.0.0
|
||||
*
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function store(Request $request)
|
||||
{
|
||||
// Call Artisan LDAP import command.
|
||||
$location_id = $request->input('location_id');
|
||||
Artisan::call('snipeit:ldap-sync', ['--location_id' => $location_id, '--json_summary' => true]);
|
||||
|
||||
// Collect and parse JSON summary.
|
||||
$ldap_results_json = Artisan::output();
|
||||
$ldap_results = json_decode($ldap_results_json, true);
|
||||
|
||||
// Direct user to appropriate status page.
|
||||
if ($ldap_results['error']) {
|
||||
return redirect()->back()->withInput()->with('error', $ldap_results['error_message']);
|
||||
}
|
||||
|
||||
return redirect()->route('ldap/user')
|
||||
->with('success', 'LDAP Import successful.')
|
||||
->with('summary', $ldap_results['summary']);
|
||||
}
|
||||
}
|
130
app/Http/Controllers/Users/UserFilesController.php
Normal file
130
app/Http/Controllers/Users/UserFilesController.php
Normal file
|
@ -0,0 +1,130 @@
|
|||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Input;
|
||||
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
|
||||
class UserFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Return JSON response with a list of user details for the getIndex() view.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
* @param AssetFileRequest $request
|
||||
* @param int $userId
|
||||
* @return string JSON
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $userId = null)
|
||||
{
|
||||
$user = User::find($userId);
|
||||
$destinationPath = config('app.private_uploads') . '/users';
|
||||
|
||||
if (isset($user->id)) {
|
||||
$this->authorize('update', $user);
|
||||
|
||||
$logActions = [];
|
||||
$files = $request->file('file');
|
||||
foreach($files as $file) {
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$filename = 'user-' . $user->id . '-' . str_random(8);
|
||||
$filename .= '-' . str_slug($file->getClientOriginalName()) . '.' . $extension;
|
||||
if (!$file->move($destinationPath, $filename)) {
|
||||
return JsonResponse::create(["error" => "Unabled to move file"], 500);
|
||||
}
|
||||
//Log the uploaded file to the log
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $user->id;
|
||||
$logAction->item_type = User::class;
|
||||
$logAction->user_id = Auth::id();
|
||||
$logAction->note = e(Input::get('notes'));
|
||||
$logAction->target_id = null;
|
||||
$logAction->created_at = date("Y-m-d H:i:s");
|
||||
$logAction->filename = $filename;
|
||||
$logAction->action_type = 'uploaded';
|
||||
|
||||
if (!$logAction->save()) {
|
||||
return JsonResponse::create(["error" => "Failed validation: " . print_r($logAction->getErrors(), true)], 500);
|
||||
|
||||
}
|
||||
$logActions[] = $logAction;
|
||||
}
|
||||
// dd($logActions);
|
||||
return JsonResponse::create($logActions);
|
||||
}
|
||||
return JsonResponse::create(["error" => "No User associated with this request"], 500);
|
||||
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Delete file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
* @param int $userId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($userId = null, $fileId = null)
|
||||
{
|
||||
$user = User::find($userId);
|
||||
$destinationPath = config('app.private_uploads').'/users';
|
||||
|
||||
if (isset($user->id)) {
|
||||
$this->authorize('update', $user);
|
||||
$log = Actionlog::find($fileId);
|
||||
$full_filename = $destinationPath . '/' . $log->filename;
|
||||
if (file_exists($full_filename)) {
|
||||
unlink($destinationPath . '/' . $log->filename);
|
||||
}
|
||||
$log->delete();
|
||||
return redirect()->back()->with('success', trans('admin/users/message.deletefile.success'));
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/users/message.user_not_found', ['id' => $userId]);
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('users.index')->with('error', $error);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Display/download the uploaded file
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.6]
|
||||
* @param int $userId
|
||||
* @param int $fileId
|
||||
* @return mixed
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($userId = null, $fileId = null)
|
||||
{
|
||||
$user = User::find($userId);
|
||||
|
||||
// the license is valid
|
||||
if (isset($user->id)) {
|
||||
$this->authorize('view', $user);
|
||||
|
||||
$log = Actionlog::find($fileId);
|
||||
$file = $log->get_src('users');
|
||||
return Response::download($file);
|
||||
}
|
||||
// Prepare the error message
|
||||
$error = trans('admin/users/message.user_not_found', ['id' => $userId]);
|
||||
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('users.index')->with('error', $error);
|
||||
}
|
||||
|
||||
}
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Reference in a new issue