Merge branch 'develop' into remove_old_ldap

Had to re-do the composer install because the conflicts were too complicated.
This commit is contained in:
Brady Wetherington 2022-01-03 12:56:58 -08:00
commit 3c7f2e89ec
542 changed files with 8155 additions and 8050 deletions

View file

@ -2478,6 +2478,42 @@
"code"
]
},
{
"login": "leitwerk-ag",
"name": "LEITWERK AG",
"avatar_url": "https://avatars.githubusercontent.com/u/24418301?v=4",
"profile": "https://www.leitwerk.de/",
"contributions": [
"code"
]
},
{
"login": "adamboutcher",
"name": "Adam",
"avatar_url": "https://avatars.githubusercontent.com/u/1911435?v=4",
"profile": "http://www.aboutcher.co.uk",
"contributions": [
"code"
]
},
{
"login": "sneak-it",
"name": "Ian",
"avatar_url": "https://avatars.githubusercontent.com/u/16104273?v=4",
"profile": "https://snksrv.com",
"contributions": [
"code"
]
},
{
"login": "bestlong",
"name": "Shao Yu-Lung (Allen)",
"avatar_url": "https://avatars.githubusercontent.com/u/4023909?v=4",
"profile": "http://blog.bestlong.idv.tw/",
"contributions": [
"code"
]
},
{
"login": "PlaneNuts",
"name": "PlaneNuts",
@ -2486,6 +2522,24 @@
"contributions": [
"code"
]
},
{
"login": "exula",
"name": "Bradley Coudriet",
"avatar_url": "https://avatars.githubusercontent.com/u/3842948?v=4",
"profile": "http://bjcpgd.cias.rit.edu",
"contributions": [
"code"
]
},
{
"login": "adagioajanes",
"name": "Alex Janes",
"avatar_url": "https://avatars.githubusercontent.com/u/38761237?v=4",
"profile": "https://adagiohealth.org",
"contributions": [
"code"
]
}
]
}

105
.env.dusk.local Normal file
View file

@ -0,0 +1,105 @@
# --------------------------------------------
# REQUIRED: BASIC APP SETTINGS
# --------------------------------------------
APP_ENV=local
APP_DEBUG=false
APP_KEY=base64:hTUIUh9CP6dQx+6EjSlfWTgbaMaaRvlpEwk45vp+xmk=
APP_URL=http://127.0.0.1:8000
APP_TIMEZONE='US/Eastern'
APP_LOCALE=en
APP_LOCKED=false
MAX_RESULTS=200
# --------------------------------------------
# REQUIRED: UPLOADED FILE STORAGE SETTINGS
# --------------------------------------------
PRIVATE_FILESYSTEM_DISK=local
PUBLIC_FILESYSTEM_DISK=local_public
# --------------------------------------------
# REQUIRED: DATABASE SETTINGS
# --------------------------------------------
DB_CONNECTION=mysql
DB_HOST=localhost
DB_DATABASE=snipeit-local
DB_USERNAME=snipeit-local
DB_PASSWORD=snipeit-local
DB_PREFIX=null
DB_DUMP_PATH='/Applications/MAMP/Library/bin'
# --------------------------------------------
# OPTIONAL: SSL DATABASE SETTINGS
# --------------------------------------------
DB_SSL=false
DB_SSL_KEY_PATH=null
DB_SSL_CERT_PATH=null
DB_SSL_CA_PATH=null
DB_SSL_CIPHER=null
# --------------------------------------------
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
MAIL_DRIVER="log"
# --------------------------------------------
# REQUIRED: IMAGE LIBRARY
# This should be gd or imagick
# --------------------------------------------
IMAGE_LIB=gd
# --------------------------------------------
# OPTIONAL: SESSION SETTINGS
# --------------------------------------------
SESSION_LIFETIME=12000
EXPIRE_ON_CLOSE=false
ENCRYPT=true
COOKIE_NAME=snipeit_v5_local
SECURE_COOKIES=true
# --------------------------------------------
# OPTIONAL: SECURITY HEADER SETTINGS
# --------------------------------------------
REFERRER_POLICY=same-origin
ENABLE_CSP=true
CORS_ALLOWED_ORIGINS="*"
# --------------------------------------------
# OPTIONAL: CACHE SETTINGS
# --------------------------------------------
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
# --------------------------------------------
# OPTIONAL: LOGIN THROTTLING
# --------------------------------------------
LOGIN_MAX_ATTEMPTS=50000
LOGIN_LOCKOUT_DURATION=1000
RESET_PASSWORD_LINK_EXPIRES=15
# --------------------------------------------
# OPTIONAL: API
# --------------------------------------------
API_MAX_REQUESTS_PER_HOUR=200
# --------------------------------------------
# OPTIONAL: SAML SETTINGS
# --------------------------------------------
DISABLE_NOSAML_LOCAL_LOGIN=true
# --------------------------------------------
# OPTIONAL: MISC
# --------------------------------------------
APP_LOG=single
LOG_LEVEL=debug
LOG_CHANNEL=stack
LOG_SLACK_WEBHOOK_URL=null
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
ALLOW_IFRAMING=true
ENABLE_HSTS=false
WARN_DEBUG=false
APP_CIPHER=AES-256-CBC

View file

@ -1,10 +1,10 @@
# --------------------------------------------
# REQUIRED: BASIC APP SETTINGS
# --------------------------------------------
APP_ENV=testing-ci
APP_ENV='testing-ci'
APP_DEBUG=false
APP_KEY=ChangeMe
APP_URL=http://localhost:8000
APP_KEY='base64:glJpcM7BYwWiBggp3SQ/+NlRkqsBQMaGEOjemXqJzOU='
APP_URL='http://localhost:8000'
APP_TIMEZONE='US/Pacific'
APP_LOCALE=en
FILESYSTEM_DISK=local
@ -12,9 +12,9 @@ FILESYSTEM_DISK=local
# --------------------------------------------
# REQUIRED: DATABASE SETTINGS
# --------------------------------------------
DB_CONNECTION=mysql
DB_CONNECTION=sqlite
DB_HOST=localhost
DB_DATABASE=snipeit_unit
DB_DATABASE='sqlite_testing'
DB_USERNAME=root
DB_PASSWORD=null
@ -22,13 +22,7 @@ DB_PASSWORD=null
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
# --------------------------------------------
MAIL_DRIVER=log
MAIL_HOST=email-smtp.us-west-2.amazonaws.com
MAIL_PORT=587
MAIL_USERNAME=YOURUSERNAME
MAIL_PASSWORD=YOURPASSWORD
MAIL_ENCRYPTION=null
MAIL_FROM_ADDR=you@example.com
MAIL_FROM_NAME=Snipe-IT
# --------------------------------------------
# REQUIRED: IMAGE LIBRARY
@ -37,37 +31,7 @@ MAIL_FROM_NAME=Snipe-IT
IMAGE_LIB=gd
# --------------------------------------------
# OPTIONAL: AWS S3 SETTINGS
# --------------------------------------------
AWS_SECRET_ACCESS_KEY=null
AWS_ACCESS_KEY_ID=null
AWS_DEFAULT_REGION=null
AWS_BUCKET=null
AWS_BUCKET_ROOT=null
AWS_URL=null
# --------------------------------------------
# OPTIONAL: CACHE SETTINGS
# --------------------------------------------
CACHE_DRIVER=file
SESSION_DRIVER=file
QUEUE_DRIVER=sync
# --------------------------------------------
# OPTIONAL: SESSION SETTINGS
# --------------------------------------------
SESSION_LIFETIME=12000
EXPIRE_ON_CLOSE=false
ENCRYPT=false
COOKIE_NAME=snipeittest_session
COOKIE_DOMAIN=null
SECURE_COOKIES=false
# --------------------------------------------
# OPTIONAL: APP LOG FORMAT
# --------------------------------------------
APP_LOG=single
APP_LOG=single

82
.github/workflows/docker-alpine.yml vendored Normal file
View file

@ -0,0 +1,82 @@
# Snipe-IT (Alpine) Docker image build for hub.docker.com
name: Docker images (Alpine)
# Run this Build for all pushes to 'master' or develop branch, or tagged releases.
# Also run for PRs to ensure PR doesn't break Docker build process
on:
push:
branches:
- master
- develop
tags:
- 'v**'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
pull_request:
jobs:
docker:
# Ensure this job never runs on forked repos. It's only executed for 'snipe/snipe-it'
if: github.repository == 'snipe/snipe-it'
runs-on: ubuntu-latest
env:
# Define tags to use for Docker images based on Git tags/branches (for docker/metadata-action)
# For a new commit on default branch (master), use the literal tag 'latest' on Docker image.
# For a new commit on other branches, use the branch name as the tag for Docker image.
# For a new tag, copy that tag name as the tag for Docker image.
IMAGE_TAGS: |
type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }},suffix=-alpine
type=ref,event=branch,enable=${{ !endsWith(github.ref, github.event.repository.default_branch) }},suffix=-alpine
type=ref,event=tag,suffix=-alpine
# Define default tag "flavor" for docker/metadata-action per
# https://github.com/docker/metadata-action#flavor-input
# We turn off 'latest' tag by default.
TAGS_FLAVOR: |
latest=false
steps:
# https://github.com/actions/checkout
- name: Checkout codebase
uses: actions/checkout@v2
# https://github.com/docker/setup-buildx-action
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v1
# https://github.com/docker/login-action
- name: Login to DockerHub
# Only login if not a PR, as PRs only trigger a Docker build and not a push
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
###############################################
# Build/Push the 'snipe/snipe-it' image
###############################################
# https://github.com/docker/metadata-action
# Get Metadata for docker_build step below
- name: Sync metadata (tags, labels) from GitHub to Docker for 'snipe-it' image
id: meta_build
uses: docker/metadata-action@v3
with:
images: snipe/snipe-it
tags: ${{ env.IMAGE_TAGS }}
flavor: ${{ env.TAGS_FLAVOR }}
# https://github.com/docker/build-push-action
- name: Build and push 'snipe-it' image
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile.alpine
platforms: linux/amd64
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
# but we ONLY do an image push to DockerHub if it's NOT a PR
push: ${{ github.event_name != 'pull_request' }}
# Use tags / labels provided by 'docker/metadata-action' above
tags: ${{ steps.meta_build.outputs.tags }}
labels: ${{ steps.meta_build.outputs.labels }}

82
.github/workflows/docker.yml vendored Normal file
View file

@ -0,0 +1,82 @@
# Snipe-IT Docker image build for hub.docker.com
name: Docker images
# Run this Build for all pushes to 'master' or develop branch, or tagged releases.
# Also run for PRs to ensure PR doesn't break Docker build process
on:
push:
branches:
- master
- develop
tags:
- 'v**'
# Allows you to run this workflow manually from the Actions tab
workflow_dispatch:
pull_request:
jobs:
docker:
# Ensure this job never runs on forked repos. It's only executed for 'snipe/snipe-it'
if: github.repository == 'snipe/snipe-it'
runs-on: ubuntu-latest
env:
# Define tags to use for Docker images based on Git tags/branches (for docker/metadata-action)
# For a new commit on default branch (master), use the literal tag 'latest' on Docker image.
# For a new commit on other branches, use the branch name as the tag for Docker image.
# For a new tag, copy that tag name as the tag for Docker image.
IMAGE_TAGS: |
type=raw,value=latest,enable=${{ endsWith(github.ref, github.event.repository.default_branch) }}
type=ref,event=branch,enable=${{ !endsWith(github.ref, github.event.repository.default_branch) }}
type=ref,event=tag
# Define default tag "flavor" for docker/metadata-action per
# https://github.com/docker/metadata-action#flavor-input
# We turn off 'latest' tag by default.
TAGS_FLAVOR: |
latest=false
steps:
# https://github.com/actions/checkout
- name: Checkout codebase
uses: actions/checkout@v2
# https://github.com/docker/setup-buildx-action
- name: Setup Docker Buildx
uses: docker/setup-buildx-action@v1
# https://github.com/docker/login-action
- name: Login to DockerHub
# Only login if not a PR, as PRs only trigger a Docker build and not a push
if: github.event_name != 'pull_request'
uses: docker/login-action@v1
with:
username: ${{ secrets.DOCKER_USERNAME }}
password: ${{ secrets.DOCKER_ACCESS_TOKEN }}
###############################################
# Build/Push the 'snipe/snipe-it' image
###############################################
# https://github.com/docker/metadata-action
# Get Metadata for docker_build step below
- name: Sync metadata (tags, labels) from GitHub to Docker for 'snipe-it' image
id: meta_build
uses: docker/metadata-action@v3
with:
images: snipe/snipe-it
tags: ${{ env.IMAGE_TAGS }}
flavor: ${{ env.TAGS_FLAVOR }}
# https://github.com/docker/build-push-action
- name: Build and push 'snipe-it' image
id: docker_build
uses: docker/build-push-action@v2
with:
context: .
file: ./Dockerfile
platforms: linux/amd64
# For pull requests, we run the Docker build (to ensure no PR changes break the build),
# but we ONLY do an image push to DockerHub if it's NOT a PR
push: ${{ github.event_name != 'pull_request' }}
# Use tags / labels provided by 'docker/metadata-action' above
tags: ${{ steps.meta_build.outputs.tags }}
labels: ${{ steps.meta_build.outputs.labels }}

View file

@ -96,6 +96,8 @@ RUN \
&& 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" \
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.cert" "/var/www/html/storage/ldap_client_tls.cert" \
&& ln -fs "/var/lib/snipeit/keys/ldap_client_tls.key" "/var/www/html/storage/ldap_client_tls.key" \
&& chown docker "/var/lib/snipeit/keys/" \
&& chown -h docker "/var/www/html/storage/" \
&& chmod +x /var/www/html/artisan \

View file

@ -1,5 +1,5 @@
![Build Status](https://app.chipperci.com/projects/0e5f8979-31eb-4ee6-9abf-050b76ab0383/status/master) [![Crowdin](https://d322cqt584bo4o.cloudfront.net/snipe-it/localized.svg)](https://crowdin.com/project/snipe-it) [![Docker Pulls](https://img.shields.io/docker/pulls/snipe/snipe-it.svg)](https://hub.docker.com/r/snipe/snipe-it/) [![Twitter Follow](https://img.shields.io/twitter/follow/snipeitapp.svg?style=social)](https://twitter.com/snipeitapp) [![Codacy Badge](https://api.codacy.com/project/badge/Grade/553ce52037fc43ea99149785afcfe641)](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
[![All Contributors](https://img.shields.io/badge/all_contributors-273-orange.svg?style=flat-square)](#contributors) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk) [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev)
[![All Contributors](https://img.shields.io/badge/all_contributors-279-orange.svg?style=flat-square)](#contributors) [![Discord](https://badgen.net/badge/icon/discord?icon=discord&label)](https://discord.gg/yZFtShAcKk) [![huntr](https://cdn.huntr.dev/huntr_security_badge_mono.svg)](https://huntr.dev)
## Snipe-IT - Open Source Asset Management System
@ -129,7 +129,8 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
| [<img src="https://avatars.githubusercontent.com/u/36065681?v=4" width="110px;"/><br /><sub>David Valin Alonso</sub>](https://github.com/deivishome)<br />[💻](https://github.com/snipe/snipe-it/commits?author=deivishome "Code") | [<img src="https://avatars.githubusercontent.com/u/8290389?v=4" width="110px;"/><br /><sub>andreaci</sub>](https://github.com/andreaci)<br />[💻](https://github.com/snipe/snipe-it/commits?author=andreaci "Code") | [<img src="https://avatars.githubusercontent.com/u/1828542?v=4" width="110px;"/><br /><sub>Jelle Sebreghts</sub>](http://www.jellesebreghts.be)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Jelle-S "Code") | [<img src="https://avatars.githubusercontent.com/u/11180862?v=4" width="110px;"/><br /><sub>Michael Pietsch</sub>](https://github.com/Skywalker-11)<br /> | [<img src="https://avatars.githubusercontent.com/u/22068886?v=4" width="110px;"/><br /><sub>Masudul Haque Shihab</sub>](https://github.com/sh1hab)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sh1hab "Code") | [<img src="https://avatars.githubusercontent.com/u/16099942?v=4" width="110px;"/><br /><sub>Supapong Areeprasertkul</sub>](http://www.freedomdive.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=zybersup "Code") | [<img src="https://avatars.githubusercontent.com/u/207358?v=4" width="110px;"/><br /><sub>Peter Sarossy</sub>](https://github.com/psarossy)<br />[💻](https://github.com/snipe/snipe-it/commits?author=psarossy "Code") |
| [<img src="https://avatars.githubusercontent.com/u/11823649?v=4" width="110px;"/><br /><sub>Renee Margaret McConahy</sub>](https://github.com/nepella)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nepella "Code") | [<img src="https://avatars.githubusercontent.com/u/5553884?v=4" width="110px;"/><br /><sub>JohnnyPicnic</sub>](https://github.com/JohnnyPicnic)<br />[💻](https://github.com/snipe/snipe-it/commits?author=JohnnyPicnic "Code") | [<img src="https://avatars.githubusercontent.com/u/8799594?v=4" width="110px;"/><br /><sub>markbrule</sub>](https://github.com/markbrule)<br />[💻](https://github.com/snipe/snipe-it/commits?author=markbrule "Code") | [<img src="https://avatars.githubusercontent.com/u/1962801?v=4" width="110px;"/><br /><sub>Mike Campbell</sub>](https://github.com/mikecmpbll)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mikecmpbll "Code") | [<img src="https://avatars.githubusercontent.com/u/11973217?v=4" width="110px;"/><br /><sub>tbrconnect</sub>](https://github.com/tbrconnect)<br />[💻](https://github.com/snipe/snipe-it/commits?author=tbrconnect "Code") | [<img src="https://avatars.githubusercontent.com/u/12447225?v=4" width="110px;"/><br /><sub>kcoyo</sub>](https://github.com/kcoyo)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kcoyo "Code") | [<img src="https://avatars.githubusercontent.com/u/494017?v=4" width="110px;"/><br /><sub>Travis Miller</sub>](https://travismiller.com/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=travismiller "Code") |
| [<img src="https://avatars.githubusercontent.com/u/1975640?v=4" width="110px;"/><br /><sub>Evan Taylor</sub>](https://github.com/Delta5)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Delta5 "Code") | [<img src="https://avatars.githubusercontent.com/u/8735148?v=4" width="110px;"/><br /><sub>Petri Asikainen</sub>](https://github.com/PetriAsi)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PetriAsi "Code") | [<img src="https://avatars.githubusercontent.com/u/11424540?v=4" width="110px;"/><br /><sub>derdeagle</sub>](https://github.com/derdeagle)<br />[💻](https://github.com/snipe/snipe-it/commits?author=derdeagle "Code") | [<img src="https://avatars.githubusercontent.com/u/176950?v=4" width="110px;"/><br /><sub>Mike Frysinger</sub>](https://wh0rd.org/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vapier "Code") | [<img src="https://avatars.githubusercontent.com/u/22044358?v=4" width="110px;"/><br /><sub>ALPHA</sub>](https://github.com/AL4AL)<br />[💻](https://github.com/snipe/snipe-it/commits?author=AL4AL "Code") | [<img src="https://avatars.githubusercontent.com/u/1042587?v=4" width="110px;"/><br /><sub>FliegenKLATSCH</sub>](https://www.ifern.de)<br />[💻](https://github.com/snipe/snipe-it/commits?author=FliegenKLATSCH "Code") | [<img src="https://avatars.githubusercontent.com/u/442138?v=4" width="110px;"/><br /><sub>Jeremy Price</sub>](https://github.com/jerm)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jerm "Code") |
| [<img src="https://avatars.githubusercontent.com/u/84392209?v=4" width="110px;"/><br /><sub>Toreg87</sub>](https://github.com/Toreg87)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Toreg87 "Code") | [<img src="https://avatars.githubusercontent.com/u/67638596?v=4" width="110px;"/><br /><sub>Matthew Nickson</sub>](https://github.com/Computroniks)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Computroniks "Code") | [<img src="https://avatars.githubusercontent.com/u/1646397?v=4" width="110px;"/><br /><sub>Jethro Nederhof</sub>](https://jethron.id.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jethron "Code") | [<img src="https://avatars.githubusercontent.com/u/23289826?v=4" width="110px;"/><br /><sub>Oskar Stenberg</sub>](https://github.com/01ste02)<br />[💻](https://github.com/snipe/snipe-it/commits?author=01ste02 "Code") | [<img src="https://avatars.githubusercontent.com/u/82208283?v=4" width="110px;"/><br /><sub>Robert-Azelis</sub>](https://github.com/Robert-Azelis)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Robert-Azelis "Code") | [<img src="https://avatars.githubusercontent.com/u/60648387?v=4" width="110px;"/><br /><sub>Alexander William Smith</sub>](https://github.com/alwism)<br />[💻](https://github.com/snipe/snipe-it/commits?author=alwism "Code") | [<img src="https://avatars.githubusercontent.com/u/88776392?v=4" width="110px;"/><br /><sub>PlaneNuts</sub>](https://github.com/PlaneNuts)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PlaneNuts "Code") |
| [<img src="https://avatars.githubusercontent.com/u/84392209?v=4" width="110px;"/><br /><sub>Toreg87</sub>](https://github.com/Toreg87)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Toreg87 "Code") | [<img src="https://avatars.githubusercontent.com/u/67638596?v=4" width="110px;"/><br /><sub>Matthew Nickson</sub>](https://github.com/Computroniks)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Computroniks "Code") | [<img src="https://avatars.githubusercontent.com/u/1646397?v=4" width="110px;"/><br /><sub>Jethro Nederhof</sub>](https://jethron.id.au)<br />[💻](https://github.com/snipe/snipe-it/commits?author=jethron "Code") | [<img src="https://avatars.githubusercontent.com/u/23289826?v=4" width="110px;"/><br /><sub>Oskar Stenberg</sub>](https://github.com/01ste02)<br />[💻](https://github.com/snipe/snipe-it/commits?author=01ste02 "Code") | [<img src="https://avatars.githubusercontent.com/u/82208283?v=4" width="110px;"/><br /><sub>Robert-Azelis</sub>](https://github.com/Robert-Azelis)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Robert-Azelis "Code") | [<img src="https://avatars.githubusercontent.com/u/60648387?v=4" width="110px;"/><br /><sub>Alexander William Smith</sub>](https://github.com/alwism)<br />[💻](https://github.com/snipe/snipe-it/commits?author=alwism "Code") | [<img src="https://avatars.githubusercontent.com/u/24418301?v=4" width="110px;"/><br /><sub>LEITWERK AG</sub>](https://www.leitwerk.de/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=leitwerk-ag "Code") |
| [<img src="https://avatars.githubusercontent.com/u/1911435?v=4" width="110px;"/><br /><sub>Adam</sub>](http://www.aboutcher.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=adamboutcher "Code") | [<img src="https://avatars.githubusercontent.com/u/16104273?v=4" width="110px;"/><br /><sub>Ian</sub>](https://snksrv.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sneak-it "Code") | [<img src="https://avatars.githubusercontent.com/u/4023909?v=4" width="110px;"/><br /><sub>Shao Yu-Lung (Allen)</sub>](http://blog.bestlong.idv.tw/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bestlong "Code") | [<img src="https://avatars.githubusercontent.com/u/88776392?v=4" width="110px;"/><br /><sub>PlaneNuts</sub>](https://github.com/PlaneNuts)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PlaneNuts "Code") | [<img src="https://avatars.githubusercontent.com/u/3842948?v=4" width="110px;"/><br /><sub>Bradley Coudriet</sub>](http://bjcpgd.cias.rit.edu)<br />[💻](https://github.com/snipe/snipe-it/commits?author=exula "Code") | [<img src="https://avatars.githubusercontent.com/u/38761237?v=4" width="110px;"/><br /><sub>Alex Janes</sub>](https://adagiohealth.org)<br />[💻](https://github.com/snipe/snipe-it/commits?author=adagioajanes "Code") |
<!-- ALL-CONTRIBUTORS-LIST:END -->
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!

View file

@ -14,7 +14,7 @@ class RestoreFromBackup extends Command
*/
protected $signature = 'snipeit:restore
{--force : Skip the danger prompt; assuming you hit "y"}
{filename : The zip file to be migrated}
{filename : The full path of the .zip file to be migrated}
{--no-progress : Don\'t show a progress bar}';
/**
@ -22,7 +22,7 @@ class RestoreFromBackup extends Command
*
* @var string
*/
protected $description = 'Restore from a previously created backup';
protected $description = 'Restore from a previously created Snipe-IT backup file';
/**
* Create a new command instance.
@ -34,6 +34,8 @@ class RestoreFromBackup extends Command
parent::__construct();
}
public static $buffer_size = 1024 * 1024; // use a 1MB buffer, ought to work fine for most cases?
/**
* Execute the console command.
*
@ -42,7 +44,10 @@ class RestoreFromBackup extends Command
public function handle()
{
$dir = getcwd();
echo "Current working directory is: $dir\n";
if( $dir != base_path() ) { // usually only the case when running via webserver, not via command-line
\Log::debug("Current working directory is: $dir, changing directory to: ".base_path());
chdir(base_path()); // TODO - is this *safe* to change on a running script?!
}
//
$filename = $this->argument('filename');
@ -67,7 +72,7 @@ class RestoreFromBackup extends Command
ZipArchive::ER_INCONS => 'Zip archive inconsistent.',
ZipArchive::ER_INVAL => 'Invalid argument.',
ZipArchive::ER_MEMORY => 'Malloc failure.',
ZipArchive::ER_NOENT => 'No such file.',
ZipArchive::ER_NOENT => 'No such file ('.$filename.') in directory '.$dir.'.',
ZipArchive::ER_NOZIP => 'Not a zip archive.',
ZipArchive::ER_OPEN => "Can't open file.",
ZipArchive::ER_READ => 'Read error.',
@ -144,7 +149,7 @@ class RestoreFromBackup extends Command
continue;
}
if (@pathinfo($raw_path)['extension'] == 'sql') {
echo "Found a sql file!\n";
\Log::debug("Found a sql file!");
$sqlfiles[] = $raw_path;
$sqlfile_indices[] = $i;
continue;
@ -206,7 +211,13 @@ class RestoreFromBackup extends Command
$env_vars = getenv();
$env_vars['MYSQL_PWD'] = config('database.connections.mysql.password');
$proc_results = proc_open('mysql -h '.escapeshellarg(config('database.connections.mysql.host')).' -u '.escapeshellarg(config('database.connections.mysql.username')).' '.escapeshellarg(config('database.connections.mysql.database')), // yanked -p since we pass via ENV
// TODO notes: we are stealing the dump_binary_path (which *probably* also has your copy of the mysql binary in it. But it might not, so we might need to extend this)
// we unilaterally prepend a slash to the `mysql` command. This might mean your path could look like /blah/blah/blah//mysql - which should be fine. But maybe in some environments it isn't?
$mysql_binary = config('database.connections.mysql.dump.dump_binary_path').'/mysql';
if( ! file_exists($mysql_binary) ) {
return $this->error("mysql tool at: '$mysql_binary' does not exist, cannot restore. Please edit DB_DUMP_PATH in your .env to point to a directory that contains the mysqldump and mysql binary");
}
$proc_results = proc_open("$mysql_binary -h ".escapeshellarg(config('database.connections.mysql.host')).' -u '.escapeshellarg(config('database.connections.mysql.username')).' '.escapeshellarg(config('database.connections.mysql.database')), // yanked -p since we pass via ENV
[0 => ['pipe', 'r'], 1 => ['pipe', 'w'], 2 => ['pipe', 'w']],
$pipes,
null,
@ -233,9 +244,10 @@ class RestoreFromBackup extends Command
return false;
}
while (($buffer = fgets($sql_contents)) !== false) {
//$this->info("Buffer is: '$buffer'");
$bytes_read = 0;
while (($buffer = fgets($sql_contents, self::$buffer_size)) !== false) {
$bytes_read += strlen($buffer);
// \Log::debug("Buffer is: '$buffer'");
$bytes_written = fwrite($pipes[0], $buffer);
if ($bytes_written === false) {
$stdout = fgets($pipes[1]);
@ -246,6 +258,10 @@ class RestoreFromBackup extends Command
return false;
}
}
if (!feof($sql_contents) || $bytes_read == 0) {
return $this->error("Not at end of file for sql file, or zero bytes read. aborting!");
}
fclose($pipes[0]);
fclose($sql_contents);
@ -273,7 +289,7 @@ class RestoreFromBackup extends Command
$fp = $za->getStream($ugly_file_name);
//$this->info("Weird problem, here are file details? ".print_r($file_details,true));
$migrated_file = fopen($file_details['dest'].'/'.basename($pretty_file_name), 'w');
while (($buffer = fgets($fp)) !== false) {
while (($buffer = fgets($fp, self::$buffer_size)) !== false) {
fwrite($migrated_file, $buffer);
}
fclose($migrated_file);

View file

@ -114,8 +114,9 @@ class AssetsController extends Controller
}
$assets = Company::scopeCompanyables(Asset::select('assets.*'), 'company_id', 'assets')
->with('location', 'assetstatus', 'assetlog', 'company', 'defaultLoc','assignedTo',
'model.category', 'model.manufacturer', 'model.fieldset', 'supplier');
->with('location', 'assetstatus', 'company', 'defaultLoc','assignedTo',
'model.category', 'model.manufacturer', 'model.fieldset','supplier'); //it might be tempting to add 'assetlog' here, but don't. It blows up update-heavy users.
// These are used by the API to query against specific ID numbers.
// They are also used by the individual searches on detail pages like
@ -171,6 +172,7 @@ class AssetsController extends Controller
// case we override with the actual count, so we should return 0 items.
$offset = (($assets) && ($request->get('offset') > $assets->count())) ? $assets->count() : $request->get('offset', 0);
// Check to make sure the limit is not higher than the max allowed
((config('app.max_results') >= $request->input('limit')) && ($request->filled('limit'))) ? $limit = $request->input('limit') : $limit = config('app.max_results');
@ -336,6 +338,7 @@ class AssetsController extends Controller
return (new $transformer)->transformAssets($assets, $total, $request);
}
/**
* Returns JSON with information about an asset (by tag) for detail view.
*
@ -373,9 +376,19 @@ class AssetsController extends Controller
}
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
$assets = Asset::with('assetstatus')->with('assignedTo');
if ($request->input('deleted', 'false') === 'true') {
$assets = $assets->withTrashed();
}
$assets = $assets->where('serial', $serial)->get();
if ($assets) {
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
} else {
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
}
}
/**
* Returns JSON with information about an asset for detail view.
@ -677,6 +690,8 @@ class AssetsController extends Controller
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
}
/**
* Restore a soft-deleted asset.
*
@ -899,7 +914,7 @@ class AssetsController extends Controller
}
}
return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag'=> e($request->input('asset_tag'))], 'Asset with tag '.$request->input('asset_tag').' not found'));
return response()->json(Helper::formatStandardApiResponse('error', ['asset_tag'=> e($request->input('asset_tag'))], 'Asset with tag '.e($request->input('asset_tag')).' not found'));

View file

@ -12,6 +12,15 @@ use App\Notifications\SlackTest;
use Notification;
use App\Notifications\MailTest;
use GuzzleHttp\Client;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Response;
use Illuminate\Support\Facades\DB;
use Illuminate\Support\Facades\Log;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Storage;
use Illuminate\Support\Facades\Validator;
use App\Http\Requests\SlackSettingsRequest;
class SettingsController extends Controller
{
@ -80,7 +89,7 @@ class SettingsController extends Controller
public function ldaptestlogin(Request $request)
{
if (Setting::getSettings()->ldap_enabled!='1') {
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);
}
@ -99,6 +108,7 @@ class SettingsController extends Controller
}
\Log::debug('Preparing to test LDAP login');
try {
$connection = Ldap::connectToLdap();
@ -131,32 +141,43 @@ class SettingsController extends Controller
}
public function slacktest(Request $request)
public function slacktest(SlackSettingsRequest $request)
{
$slack = new Client([
'base_url' => e($request->input('slack_endpoint')),
'defaults' => [
'exceptions' => false,
],
$validator = Validator::make($request->all(), [
'slack_endpoint' => 'url|required_with:slack_channel|starts_with:https://hooks.slack.com/|nullable',
'slack_channel' => 'required_with:slack_endpoint|starts_with:#|nullable',
]);
$payload = json_encode(
[
'channel' => e($request->input('slack_channel')),
'text' => trans('general.slack_test_msg'),
'username' => e($request->input('slack_botname')),
'icon_emoji' => ':heart:',
]);
try {
$slack->post($request->input('slack_endpoint'), ['body' => $payload]);
return response()->json(['message' => 'Success'], 200);
} catch (\Exception $e) {
return response()->json(['message' => 'Oops! Please check the channel name and webhook endpoint URL. Slack responded with: '.$e->getMessage()], 400);
if ($validator->fails()) {
return response()->json(['message' => 'Validation failed', 'errors' => $validator->errors()], 422);
}
// If validation passes, continue to the curl request
$slack = new Client([
'base_url' => e($request->input('slack_endpoint')),
'defaults' => [
'exceptions' => false,
],
]);
$payload = json_encode(
[
'channel' => e($request->input('slack_channel')),
'text' => trans('general.slack_test_msg'),
'username' => e($request->input('slack_botname')),
'icon_emoji' => ':heart:',
]);
try {
$slack->post($request->input('slack_endpoint'), ['body' => $payload]);
return response()->json(['message' => 'Success'], 200);
} catch (\Exception $e) {
return response()->json(['message' => 'Please check the channel name and webhook endpoint URL ('.e($request->input('slack_endpoint')).'). Slack responded with: '.$e->getMessage()], 400);
}
//}
return response()->json(['message' => 'Something went wrong :( '], 400);
}
@ -205,6 +226,7 @@ class SettingsController extends Controller
if ($extension == 'png') {
\Log::debug('Deleting: '.$file);
try {
Storage::disk('public')->delete($file);
\Log::debug('Deleting: '.$file);
@ -218,6 +240,10 @@ class SettingsController extends Controller
return response()->json(['message' => 'Deleted '.$file_count.' barcodes'], 200);
}
/**
* Get a list of login attempts
*

View file

@ -266,6 +266,7 @@ class AssetModelsController extends Controller
*/
public function getClone($modelId = null)
{
$this->authorize('create', AssetModel::class);
// Check if the model exists
if (is_null($model_to_clone = AssetModel::find($modelId))) {
return redirect()->route('models.index')->with('error', trans('admin/models/message.does_not_exist'));

View file

@ -197,7 +197,7 @@ class AssetsController extends Controller
}
if (isset($target)) {
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), $request->input('expected_checkin', null), 'Checked out on asset creation', e($request->get('name')), $location);
$asset->checkOut($target, Auth::user(), date('Y-m-d H:i:s'), $request->input('expected_checkin', null), 'Checked out on asset creation', $request->get('name'), $location);
}
$success = true;

View file

@ -86,13 +86,13 @@ class CustomFieldsController extends Controller
$this->authorize('create', CustomField::class);
$field = new CustomField([
'name' => $request->get('name'),
'element' => $request->get('element'),
'help_text' => $request->get('help_text'),
'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::id(),
"name" => trim($request->get("name")),
"element" => $request->get("element"),
"help_text" => $request->get("help_text"),
"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::id()
]);
if ($request->filled('custom_format')) {
@ -109,6 +109,7 @@ class CustomFieldsController extends Controller
->with('error', trans('admin/custom_fields/message.field.create.error'));
}
/**
* Detach a custom field from a fieldset.
*
@ -148,9 +149,8 @@ class CustomFieldsController extends Controller
return redirect()->back()->withErrors(['message' => 'Field is in-use']);
}
$field->delete();
return redirect()->route('fields.index')
->with('success', trans('admin/custom_fields/message.field.delete.success'));
return redirect()->route("fields.index")
->with("success", trans('admin/custom_fields/message.field.delete.success'));
}
return redirect()->back()->withErrors(['message' => 'Field does not exist']);
@ -200,12 +200,12 @@ class CustomFieldsController extends Controller
$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::id();
$field->help_text = $request->get('help_text');
$field->show_in_email = $request->get('show_in_email', 0);
$field->name = trim(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 ($request->get('format') == 'CUSTOM REGEX') {
$field->format = e($request->get('custom_format'));

View file

@ -513,6 +513,10 @@ class ReportsController extends Controller
$header[] = trans('general.department');
}
if ($request->filled('title')) {
$header[] = trans('admin/users/table.title');
}
if ($request->filled('status')) {
$header[] = trans('general.status');
}
@ -756,6 +760,14 @@ class ReportsController extends Controller
}
}
if ($request->filled('title')) {
if ($asset->checkedOutToUser()) {
$row[] = ($asset->assignedto) ? $asset->assignedto->jobtitle : '';
} else {
$row[] = ''; // Empty string if unassigned
}
}
if ($request->filled('status')) {
$row[] = ($asset->assetstatus) ? $asset->assetstatus->name.' ('.$asset->present()->statusMeta.')' : '';
}

View file

@ -11,7 +11,6 @@ use App\Models\Setting;
use App\Models\User;
use App\Notifications\FirstAdminNotification;
use App\Notifications\MailTest;
use Artisan;
use Auth;
use Crypt;
use DB;
@ -22,6 +21,9 @@ use Image;
use Input;
use Redirect;
use Response;
use App\Http\Requests\SlackSettingsRequest;
use Illuminate\Support\Str;
use Illuminate\Support\Facades\Artisan;
/**
* This controller handles all actions related to Settings for
@ -426,8 +428,10 @@ class SettingsController extends Controller
// If they are uploading an image, validate it and upload it
}
$setting = $request->handleImages($setting, 600, 'label_logo', '', 'label_logo');
if ('1' == $request->input('clear_label_logo')) {
Storage::disk('public')->delete($setting->label_logo);
$setting->label_logo = null;
@ -658,21 +662,15 @@ class SettingsController extends Controller
*
* @return View
*/
public function postSlack(Request $request)
public function postSlack(SlackSettingsRequest $request)
{
if (is_null($setting = Setting::getSettings())) {
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
}
$validatedData = $request->validate([
'slack_channel' => 'regex:/(?<!\w)#\w+/|required_with:slack_endpoint|nullable',
]);
if ($validatedData) {
$setting->slack_endpoint = $request->input('slack_endpoint');
$setting->slack_channel = $request->input('slack_channel');
$setting->slack_botname = $request->input('slack_botname');
}
$setting->slack_endpoint = $request->input('slack_endpoint');
$setting->slack_channel = $request->input('slack_channel');
$setting->slack_botname = $request->input('slack_botname');
if ($setting->save()) {
return redirect()->route('settings.index')
@ -836,6 +834,8 @@ class SettingsController extends Controller
$setting->labels_display_company_name = $request->input('labels_display_company_name', '0');
$setting->labels_display_company_name = $request->input('labels_display_company_name', '0');
if ($request->filled('labels_display_name')) {
$setting->labels_display_name = 1;
} else {
@ -1014,6 +1014,7 @@ class SettingsController extends Controller
*/
public function getBackups()
{
$path = 'app/backups';
$backup_files = Storage::files($path);
$files_raw = [];
@ -1023,12 +1024,20 @@ class SettingsController extends Controller
// Skip dotfiles like .gitignore and .DS_STORE
if ((substr(basename($backup_files[$f]), 0, 1) != '.')) {
//$lastmodified = Carbon::parse(Storage::lastModified($backup_files[$f]))->toDatetimeString();
$file_timestamp = Storage::lastModified($backup_files[$f]);
$files_raw[] = [
'filename' => basename($backup_files[$f]),
'filesize' => Setting::fileSizeConvert(Storage::size($backup_files[$f])),
'modified' => Storage::lastModified($backup_files[$f]),
'modified_value' => $file_timestamp,
'modified_display' => Helper::getFormattedDateObject($file_timestamp, $type = 'datetime', false),
];
}
}
}
@ -1128,6 +1137,115 @@ class SettingsController extends Controller
}
}
/**
* Uploads a backup file
*
* @author [A. Gianotto] [<snipe@snipe.net>]
*
* @since [v6.0]
*
* @return Redirect
*/
public function postUploadBackup(Request $request) {
if (! config('app.lock_passwords')) {
if (!$request->hasFile('file')) {
return redirect()->route('settings.backups.index')->with('error', 'No file uploaded');
} else {
$max_file_size = Helper::file_upload_max_size();
$rules = [
'file' => 'required|mimes:zip|max:'.$max_file_size,
];
$validator = \Validator::make($request->all(), $rules);
if ($validator->passes()) {
$upload_filename = 'uploaded-'.date('U').'-'.Str::slug(pathinfo($request->file('file')->getClientOriginalName(), PATHINFO_FILENAME)).'.zip';
Storage::putFileAs('app/backups', $request->file('file'), $upload_filename);
return redirect()->route('settings.backups.index')->with('success', 'File uploaded');
} else {
return redirect()->route('settings.backups.index')->withErrors($request->getErrors());
}
}
} else {
return redirect()->route('settings.backups.index')->with('error', trans('general.feature_disabled'));
}
}
/**
* Restore the backup file.
*
* @author [A. Gianotto] [<snipe@snipe.net>]
*
* @since [v6.0]
*
* @return View
*/
public function postRestore($filename = null)
{
if (! config('app.lock_passwords')) {
$path = 'app/backups';
if (Storage::exists($path.'/'.$filename)) {
// grab the user's info so we can make sure they exist in the system
$user = User::find(Auth::user()->id);
// TODO: run a backup
// TODO: add db:wipe
// run the restore command
Artisan::call('snipeit:restore',
[
'--force' => true,
'--no-progress' => true,
'filename' => storage_path($path).'/'.$filename
]);
$output = Artisan::output();
// If it's greater than 300, it probably worked
if (strlen($output) > 300) {
\Auth::logout();
return redirect()->route('login')->with('success', 'Your system has been restored. Please login again.');
} else {
return redirect()->route('settings.backups.index')->with('error', $output);
}
//dd($output);
// TODO: insert the user if they are not there in the old one
// log the user out
} else {
return redirect()->route('settings.backups.index')->with('error', trans('admin/settings/message.backup.file_not_found'));
}
} else {
return redirect()->route('settings.backups.index')->with('error', trans('general.feature_disabled'));
}
}
/**
* Return a form to allow a super admin to update settings.
*

View file

@ -19,13 +19,22 @@ class CustomFieldSetDefaultValuesForModel extends Component
{
$this->model = AssetModel::find($this->model_id); // It's possible to do some clever route-model binding here, but let's keep it simple, shall we?
$this->fieldset_id = $this->model->fieldset_id;
$this->fields = CustomFieldset::find($this->fieldset_id)->fields;
$this->add_default_values = ( $this->model->defaultValues->count() > 0);
$this->fields = null;
if ($fieldset = CustomFieldset::find($this->fieldset_id)) {
$this->fields = CustomFieldset::find($this->fieldset_id)->fields;
}
$this->add_default_values = ($this->model->defaultValues->count() > 0);
}
public function updatedFieldsetId()
{
$this->fields = CustomFieldset::find($this->fieldset_id)->fields;
if (CustomFieldset::find($this->fieldset_id)) {
$this->fields = CustomFieldset::find($this->fieldset_id)->fields;
}
}
public function render()

View file

@ -21,7 +21,7 @@ class AssetFileRequest extends Request
*/
public function rules()
{
$max_file_size = Helper::file_upload_max_size();
$max_file_size = \App\Helpers\Helper::file_upload_max_size();
return [
'file.*' => 'required|mimes:png,gif,jpg,svg,jpeg,doc,docx,pdf,txt,zip,rar,xls,xlsx,lic,xml,rtf,webp|max:'.$max_file_size,

View file

@ -90,11 +90,6 @@ class ImageUploadRequest extends Request
$use_db_field = $db_fieldname;
}
\Log::info('Image path is: '.$path);
\Log::debug('Type is: '.$type);
\Log::debug('Form fieldname is: '.$form_fieldname);
\Log::debug('DB fieldname is: '.$use_db_field);
\Log::debug('Trying to upload to '. $path);
// ConvertBase64ToFiles just changes object type,
// as it cannot currently insert files to $this->files

View file

@ -0,0 +1,33 @@
<?php
namespace App\Http\Requests;
class SlackSettingsRequest extends Request
{
/**
* Determine if the user is authorized to make this request.
*
* @return bool
*/
public function authorize()
{
return true;
}
/**
* Get the validation rules that apply to the request.
*
* @return array
*/
public function rules()
{
return [
'slack_endpoint' => 'url|required_with:slack_channel|starts_with:"https://hooks.slack.com"|nullable',
'slack_channel' => 'required_with:slack_endpoint|starts_with:#|nullable',
'slack_botname' => 'string|nullable',
];
}
}

View file

@ -79,7 +79,7 @@ class AccessoriesTransformer
'first_name'=> e($user->first_name),
'last_name'=> e($user->last_name),
'employee_number' => e($user->employee_num),
'checkout_notes' => $user->pivot->note,
'checkout_notes' => e($user->pivot->note),
'last_checkout' => Helper::getFormattedDateObject($user->pivot->created_at, 'datetime'),
'type' => 'user',
'available_actions' => ['checkin' => true],

View file

@ -93,15 +93,15 @@ class AssetsTransformer
$value = (Gate::allows('superadmin')) ? $decrypted : strtoupper(trans('admin/custom_fields/general.encrypted'));
$fields_array[$field->name] = [
'field' => $field->convertUnicodeDbSlug(),
'value' => $value,
'field' => e($field->convertUnicodeDbSlug()),
'value' => e($value),
'field_format' => $field->format,
];
} else {
$fields_array[$field->name] = [
'field' => $field->convertUnicodeDbSlug(),
'value' => $asset->{$field->convertUnicodeDbSlug()},
'field' => e($field->convertUnicodeDbSlug()),
'value' => e($asset->{$field->convertUnicodeDbSlug()}),
'field_format' => $field->format,
];
@ -114,24 +114,13 @@ class AssetsTransformer
}
$permissions_array['available_actions'] = [
'checkout' => Gate::allows('checkout', Asset::class),
'checkin' => Gate::allows('checkin', Asset::class),
'clone' => false,
'restore' => false,
'update' => (bool) Gate::allows('update', Asset::class),
'delete' => ($asset->assigned_to == '' && Gate::allows('delete', Asset::class)),
];
if ($asset->deleted_at != '') {
$permissions_array['available_actions'] = [
'checkout' => true,
'checkin' => false,
'clone' => Gate::allows('create', Asset::class),
'restore' => Gate::allows('create', Asset::class),
'update' => false,
'delete' => false,
];
}
'checkout' => ($asset->deleted_at=='' && Gate::allows('checkout', Asset::class)) ? true : false,
'checkin' => ($asset->deleted_at=='' && Gate::allows('checkin', Asset::class)) ? true : false,
'clone' => Gate::allows('create', Asset::class) ? true : false,
'restore' => ($asset->deleted_at!='' && Gate::allows('create', Asset::class)) ? true : false,
'update' => ($asset->deleted_at=='' && Gate::allows('update', Asset::class)) ? true : false,
'delete' => ($asset->deleted_at=='' && $asset->assigned_to =='' && Gate::allows('delete', Asset::class)) ? true : false,
];
if (request('components')=='true') {
@ -144,7 +133,7 @@ class AssetsTransformer
'id' => $component->id,
'pivot_id' => $component->pivot->id,
'name' => $component->name,
'name' => e($component->name),
'qty' => $component->pivot->assigned_qty,
'price_cost' => $component->purchase_cost,
'purchase_total' => $component->purchase_cost * $component->pivot->assigned_qty,
@ -182,8 +171,8 @@ class AssetsTransformer
return $asset->assigned ? [
'id' => $asset->assigned->id,
'name' => $asset->assigned->display_name,
'type' => $asset->assignedType(),
'name' => e($asset->assigned->display_name),
'type' => $asset->assignedType()
] : null;
}

View file

@ -76,6 +76,7 @@ abstract class Importer
'department' => 'department',
'manager_first_name' => 'manager first name',
'manager_last_name' => 'manager last name',
'min_amt' => 'minimum quantity',
];
/**
* Map of item fields->csv names
@ -196,11 +197,11 @@ abstract class Importer
$val = $default;
$key = $this->lookupCustomKey($key);
// $this->log("Custom Key: ${key}");
$this->log("Custom Key: ${key}");
if (array_key_exists($key, $array)) {
$val = Encoding::toUTF8(trim($array[$key]));
}
// $this->log("${key}: ${val}");
$this->log("${key}: ${val}");
return $val;
}

View file

@ -29,6 +29,7 @@
| serial number | serial | Asset, license |
| status | status | Asset ? All |
| supplier | supplier | Asset ? All |
| minimum quantity | min_amt | Consumable |
| termination date | termination_date | License |
| warranty months | warranty_months | Asset |
| User Related Fields | assigned_to | Asset |

View file

@ -135,7 +135,7 @@ class CheckoutableListener
/**
* Notify Admin users if the settings is activated
*/
if (Setting::getSettings()->admin_cc_email != '') {
if ((Setting::getSettings()) && (Setting::getSettings()->admin_cc_email != '')) {
$notifiables->push(new AdminRecipient());
}

View file

@ -114,6 +114,7 @@ class Asset extends Depreciable
'purchase_cost' => 'numeric|nullable',
'next_audit_date' => 'date|nullable',
'last_audit_date' => 'date|nullable',
'supplier_id' => 'exists:suppliers,id|nullable',
];
/**

View file

@ -30,7 +30,7 @@ class AssetModel extends SnipeModel
'name' => 'required|min:1|max:255',
'model_number' => 'max:255|nullable',
'category_id' => 'required|integer|exists:categories,id',
'manufacturer_id' => 'required|integer|exists:manufacturers,id',
'manufacturer_id' => 'integer|exists:manufacturers,id|nullable',
'eol' => 'integer:min:0|max:240|nullable',
];

View file

@ -68,6 +68,7 @@ class Consumable extends SnipeModel
'purchase_cost',
'purchase_date',
'qty',
'min_amt',
'requestable',
];
@ -185,6 +186,7 @@ class Consumable extends SnipeModel
return $this->belongsTo(\App\Models\Category::class, 'category_id');
}
/**
* Establishes the component -> action logs relationship
*
@ -209,8 +211,8 @@ class Consumable extends SnipeModel
if ($this->image) {
return Storage::disk('public')->url(app('consumables_upload_path').$this->image);
}
return false;
}
/**
@ -225,6 +227,7 @@ class Consumable extends SnipeModel
return $this->belongsToMany(\App\Models\User::class, 'consumables_users', 'consumable_id', 'assigned_to')->withPivot('user_id')->withTrashed()->withTimestamps();
}
/**
* Determine whether to send a checkin/checkout email based on
* asset model category

View file

@ -54,10 +54,7 @@ class Setting extends Model
'admin_cc_email' => 'email|nullable',
'default_currency' => 'required',
'locale' => 'required',
'slack_endpoint' => 'url|required_with:slack_channel|nullable',
'labels_per_page' => 'numeric',
'slack_channel' => 'regex:/^[\#\@]?\w+/|required_with:slack_endpoint|nullable',
'slack_botname' => 'string|nullable',
'labels_width' => 'numeric',
'labels_height' => 'numeric',
'labels_pmargin_left' => 'numeric|nullable',

View file

@ -17,8 +17,8 @@ class Supplier extends SnipeModel
protected $rules = [
'name' => 'required|min:1|max:255|unique_undeleted',
'address' => 'max:50|nullable',
'address2' => 'max:50|nullable',
'address' => 'max:250|nullable',
'address2' => 'max:250|nullable',
'city' => 'max:255|nullable',
'state' => 'max:32|nullable',
'country' => 'max:3|nullable',

View file

@ -53,7 +53,7 @@ class CheckoutAssetNotification extends Notification
{
$notifyBy = [];
if (Setting::getSettings()->slack_endpoint != '') {
if ((Setting::getSettings()) && (Setting::getSettings()->slack_endpoint != '')) {
\Log::debug('use slack');
$notifyBy[] = 'slack';
}

View file

@ -102,7 +102,8 @@ class AccessoryPresenter extends Presenter
'searchable' => true,
'sortable' => true,
'title' => trans('general.purchase_cost'),
'footerFormatter' => 'sumFormatter',
'footerFormatter' => 'sumFormatterQuantity',
'class' => 'text-right',
], [
'field' => 'order_number',
'searchable' => true,

View file

@ -130,6 +130,7 @@ class AssetAuditPresenter extends Presenter
'visible' => false,
'title' => trans('general.purchase_cost'),
'footerFormatter' => 'sumFormatter',
'class' => 'text-right',
], [
'field' => 'order_number',
'searchable' => true,

View file

@ -100,6 +100,7 @@ class AssetMaintenancesPresenter extends Presenter
'searchable' => true,
'sortable' => true,
'title' => trans('admin/asset_maintenances/form.cost'),
'class' => 'text-right',
], [
'field' => 'user_id',
'searchable' => true,

View file

@ -146,6 +146,7 @@ class AssetPresenter extends Presenter
'sortable' => true,
'title' => trans('general.purchase_cost'),
'footerFormatter' => 'sumFormatter',
'class' => 'text-right',
], [
'field' => 'order_number',
'searchable' => true,

View file

@ -101,7 +101,8 @@ class ComponentPresenter extends Presenter
'sortable' => true,
'title' => trans('general.purchase_cost'),
'visible' => true,
'footerFormatter' => 'sumFormatter',
'footerFormatter' => 'sumFormatterQuantity',
'class' => 'text-right',
],
];

View file

@ -113,7 +113,8 @@ class ConsumablePresenter extends Presenter
'sortable' => true,
'title' => trans('general.purchase_cost'),
'visible' => true,
'footerFormatter' => 'sumFormatter',
'footerFormatter' => 'sumFormatterQuantity',
'class' => 'text-right',
], [
'field' => 'change',
'searchable' => false,

View file

@ -128,6 +128,7 @@ class DepreciationReportPresenter extends Presenter
"visible" => true,
"title" => trans('general.purchase_cost'),
"footerFormatter" => 'sumFormatter',
"class" => "text-right",
], [
"field" => "order_number",
"searchable" => true,
@ -148,6 +149,7 @@ class DepreciationReportPresenter extends Presenter
"visible" => true,
"title" => trans('admin/hardware/table.book_value'),
"footerFormatter" => 'sumFormatter',
"class" => "text-right",
], [
"field" => "monthly_depreciation",
"searchable" => true,
@ -161,6 +163,7 @@ class DepreciationReportPresenter extends Presenter
"visible" => true,
"title" => trans('admin/hardware/table.diff'),
"footerFormatter" => 'sumFormatter',
"class" => "text-right",
],[
"field" => "warranty_expires",
"searchable" => false,

View file

@ -136,7 +136,8 @@ class LicensePresenter extends Presenter
'sortable' => true,
'visible' => false,
'title' => trans('general.purchase_cost'),
'footerFormatter' => 'sumFormatter',
'footerFormatter' => 'sumFormatterQuantity',
'class' => 'text-right',
], [
'field' => 'purchase_order',
'searchable' => true,

View file

@ -61,8 +61,15 @@ class AppServiceProvider extends ServiceProvider
*/
public function register()
{
// Only load rollbar if there is a rollbar key and the app is in production
if (($this->app->environment('production')) && (config('logging.channels.rollbar.access_token'))) {
$this->app->register(\Rollbar\Laravel\RollbarServiceProvider::class);
}
}
// Only load dusk's service provider if the app is in local or develop mode
if ($this->app->environment(['local', 'develop'])) {
$this->app->register(\Laravel\Dusk\DuskServiceProvider::class);
}
}
}

275
c3.php
View file

@ -1,275 +0,0 @@
<?php
// @codingStandardsIgnoreFile
// @codeCoverageIgnoreStart
/**
* C3 - Codeception Code Coverage
*
* @author tiger
*/
// $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'] = 1;
if (isset($_COOKIE['CODECEPTION_CODECOVERAGE'])) {
$cookie = json_decode($_COOKIE['CODECEPTION_CODECOVERAGE'], true);
// fix for improperly encoded JSON in Code Coverage cookie with WebDriver.
// @see https://github.com/Codeception/Codeception/issues/874
if (!is_array($cookie)) {
$cookie = json_decode($cookie, true);
}
if ($cookie) {
foreach ($cookie as $key => $value) {
$_SERVER["HTTP_X_CODECEPTION_".strtoupper($key)] = $value;
}
}
}
if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE', $_SERVER)) {
return;
}
if (!function_exists('__c3_error')) {
function __c3_error($message)
{
$errorLogFile = defined('C3_CODECOVERAGE_ERROR_LOG_FILE') ?
C3_CODECOVERAGE_ERROR_LOG_FILE :
C3_CODECOVERAGE_MEDIATE_STORAGE . DIRECTORY_SEPARATOR . 'error.txt';
if (is_writable($errorLogFile)) {
file_put_contents($errorLogFile, $message);
}else{
$message = "Could not write error to log file ($errorLogFile), original message: $message";
}
if (!headers_sent()) {
header('X-Codeception-CodeCoverage-Error: ' . str_replace("\n", ' ', $message), true, 500);
}
setcookie('CODECEPTION_CODECOVERAGE_ERROR', $message);
}
}
// phpunit codecoverage shimming
if (class_exists('SebastianBergmann\CodeCoverage\CodeCoverage')) {
class_alias('SebastianBergmann\CodeCoverage\CodeCoverage', 'PHP_CodeCoverage');
class_alias('SebastianBergmann\CodeCoverage\Report\Text', 'PHP_CodeCoverage_Report_Text');
class_alias('SebastianBergmann\CodeCoverage\Report\PHP', 'PHP_CodeCoverage_Report_PHP');
class_alias('SebastianBergmann\CodeCoverage\Report\Clover', 'PHP_CodeCoverage_Report_Clover');
class_alias('SebastianBergmann\CodeCoverage\Report\Html\Facade', 'PHP_CodeCoverage_Report_HTML');
class_alias('SebastianBergmann\CodeCoverage\Exception', 'PHP_CodeCoverage_Exception');
}
// Autoload Codeception classes
if (!class_exists('\\Codeception\\Codecept')) {
if (file_exists(__DIR__ . '/codecept.phar')) {
require_once 'phar://'.__DIR__ . '/codecept.phar/autoload.php';
} elseif (stream_resolve_include_path(__DIR__ . '/vendor/autoload.php')) {
require_once __DIR__ . '/vendor/autoload.php';
// Required to load some methods only available at codeception/autoload.php
if (stream_resolve_include_path(__DIR__ . '/vendor/codeception/codeception/autoload.php')) {
require_once __DIR__ . '/vendor/codeception/codeception/autoload.php';
}
} elseif (stream_resolve_include_path('Codeception/autoload.php')) {
require_once 'Codeception/autoload.php';
} else {
__c3_error('Codeception is not loaded. Please check that either PHAR or Composer or PEAR package can be used');
}
}
// Load Codeception Config
$config_dist_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'codeception.dist.yml';
$config_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . 'codeception.yml';
if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG'])) {
$config_file = realpath(__DIR__) . DIRECTORY_SEPARATOR . $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_CONFIG'];
}
if (file_exists($config_file)) {
// Use codeception.yml for configuration.
} elseif (file_exists($config_dist_file)) {
// Use codeception.dist.yml for configuration.
$config_file = $config_dist_file;
} else {
__c3_error(sprintf("Codeception config file '%s' not found", $config_file));
}
try {
\Codeception\Configuration::config($config_file);
} catch (\Exception $e) {
__c3_error($e->getMessage());
}
if (!defined('C3_CODECOVERAGE_MEDIATE_STORAGE')) {
// workaround for 'zend_mm_heap corrupted' problem
gc_disable();
if ((integer)ini_get('memory_limit') < 384) {
ini_set('memory_limit', '384M');
}
define('C3_CODECOVERAGE_MEDIATE_STORAGE', Codeception\Configuration::logDir() . 'c3tmp');
define('C3_CODECOVERAGE_PROJECT_ROOT', Codeception\Configuration::projectDir());
define('C3_CODECOVERAGE_TESTNAME', $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE']);
function __c3_build_html_report(PHP_CodeCoverage $codeCoverage, $path)
{
$writer = new PHP_CodeCoverage_Report_HTML();
$writer->process($codeCoverage, $path . 'html');
if (file_exists($path . '.tar')) {
unlink($path . '.tar');
}
$phar = new PharData($path . '.tar');
$phar->setSignatureAlgorithm(Phar::SHA1);
$files = $phar->buildFromDirectory($path . 'html');
array_map('unlink', $files);
if (in_array('GZ', Phar::getSupportedCompression())) {
if (file_exists($path . '.tar.gz')) {
unlink($path . '.tar.gz');
}
$phar->compress(\Phar::GZ);
// close the file so that we can rename it
unset($phar);
unlink($path . '.tar');
rename($path . '.tar.gz', $path . '.tar');
}
return $path . '.tar';
}
function __c3_build_clover_report(PHP_CodeCoverage $codeCoverage, $path)
{
$writer = new PHP_CodeCoverage_Report_Clover();
$writer->process($codeCoverage, $path . '.clover.xml');
return $path . '.clover.xml';
}
function __c3_send_file($filename)
{
if (!headers_sent()) {
readfile($filename);
}
return __c3_exit();
}
/**
* @param $filename
* @return null|PHP_CodeCoverage
*/
function __c3_factory($filename)
{
$phpCoverage = is_readable($filename)
? unserialize(file_get_contents($filename))
: new PHP_CodeCoverage();
if (isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE'])) {
$suite = $_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_SUITE'];
try {
$settings = \Codeception\Configuration::suiteSettings($suite, \Codeception\Configuration::config());
} catch (Exception $e) {
__c3_error($e->getMessage());
}
} else {
$settings = \Codeception\Configuration::config();
}
try {
\Codeception\Coverage\Filter::setup($phpCoverage)
->whiteList($settings)
->blackList($settings);
} catch (Exception $e) {
__c3_error($e->getMessage());
}
return $phpCoverage;
}
function __c3_exit()
{
if (!isset($_SERVER['HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG'])) {
exit;
}
return null;
}
function __c3_clear()
{
\Codeception\Util\FileSystem::doEmptyDir(C3_CODECOVERAGE_MEDIATE_STORAGE);
}
}
if (!is_dir(C3_CODECOVERAGE_MEDIATE_STORAGE)) {
if (mkdir(C3_CODECOVERAGE_MEDIATE_STORAGE, 0777, true) === false) {
__c3_error('Failed to create directory "' . C3_CODECOVERAGE_MEDIATE_STORAGE . '"');
}
}
// evaluate base path for c3-related files
$path = realpath(C3_CODECOVERAGE_MEDIATE_STORAGE) . DIRECTORY_SEPARATOR . 'codecoverage';
$requested_c3_report = (strpos($_SERVER['REQUEST_URI'], 'c3/report') !== false);
$complete_report = $current_report = $path . '.serialized';
if ($requested_c3_report) {
set_time_limit(0);
$route = ltrim(strrchr($_SERVER['REQUEST_URI'], '/'), '/');
if ($route == 'clear') {
__c3_clear();
return __c3_exit();
}
$codeCoverage = __c3_factory($complete_report);
switch ($route) {
case 'html':
try {
__c3_send_file(__c3_build_html_report($codeCoverage, $path));
} catch (Exception $e) {
__c3_error($e->getMessage());
}
return __c3_exit();
case 'clover':
try {
__c3_send_file(__c3_build_clover_report($codeCoverage, $path));
} catch (Exception $e) {
__c3_error($e->getMessage());
}
return __c3_exit();
case 'serialized':
try {
__c3_send_file($complete_report);
} catch (Exception $e) {
__c3_error($e->getMessage());
}
return __c3_exit();
}
} else {
$codeCoverage = __c3_factory($current_report);
$codeCoverage->start(C3_CODECOVERAGE_TESTNAME);
if (!array_key_exists('HTTP_X_CODECEPTION_CODECOVERAGE_DEBUG', $_SERVER)) {
register_shutdown_function(
function () use ($codeCoverage, $current_report) {
$codeCoverage->stop();
if (!file_exists(dirname($current_report))) { // verify directory exists
if(!mkdir(dirname($current_report), 0777, true)){
__c3_error("Can't write CodeCoverage report into $current_report");
}
}
file_put_contents($current_report, serialize($codeCoverage));
}
);
}
}
// @codeCoverageIgnoreEnd

View file

@ -1,20 +0,0 @@
actor: Tester
paths:
tests: tests
log: tests/_output
data: tests/_data
support: tests/_support
envs: tests/_envs
bootstrap: _bootstrap.php
settings:
colors: true
memory_limit: 1024M
extensions:
enabled:
- Codeception\Extension\RunFailed
coverage:
enabled: true
include:
- app/*
exclude:
- app/cache/*

View file

@ -11,14 +11,14 @@
"license": "AGPL-3.0-or-later",
"type": "project",
"require": {
"php": "^7.3",
"php": ">=7.4 <8.1",
"ext-curl": "*",
"ext-fileinfo": "*",
"ext-json": "*",
"ext-mbstring": "*",
"ext-pdo": "*",
"alek13/slack": "^2.0",
"bacon/bacon-qr-code": "^1.0",
"bacon/bacon-qr-code": "^2.0",
"barryvdh/laravel-debugbar": "^3.6",
"doctrine/cache": "^1.10",
"doctrine/common": "^2.12",
@ -41,13 +41,13 @@
"laravel/tinker": "^2.6",
"laravel/ui": "^3.3",
"laravelcollective/html": "^6.2",
"lcobucci/clock": "1.2.0",
"lcobucci/jwt": "^3.4.5",
"lcobucci/clock": "1.2.0|2.0.0",
"lcobucci/jwt": "^3.4.5|^4.0.4",
"league/csv": "^9.7",
"league/flysystem-aws-s3-v3": "^1.0",
"league/flysystem-cached-adapter": "^1.1",
"livewire/livewire": "^2.4",
"mediconesystems/livewire-datatables": "^0.4.3",
"mediconesystems/livewire-datatables": "^0.5.0",
"neitanod/forceutf8": "^2.0",
"nesbot/carbon": "^2.32",
"nunomaduro/collision": "^5.4",
@ -65,22 +65,16 @@
"watson/validating": "^6.1"
},
"require-dev": {
"codeception/codeception": "^4.1",
"codeception/module-asserts": "^1.2",
"codeception/module-laravel5": "^1.1",
"codeception/module-rest": "^1.2",
"codeception/module-webdriver": "^1.0",
"fzaninotto/faker": "^1.9",
"fakerphp/faker": "^1.16",
"laravel/dusk": "^6.19",
"mockery/mockery": "^1.4",
"overtrue/phplint": "^3.0",
"phpunit/php-token-stream": "^3.1",
"phpunit/phpunit": "^8.5",
"phpunit/phpunit": "^9.0",
"squizlabs/php_codesniffer": "^3.5",
"symfony/css-selector": "^4.4",
"symfony/dom-crawler": "^4.4"
},
"suggest": {
"ext-mcrypt": "For upgrading from before v5.1 this is used to re-encrypt data"
},
"extra": {
"laravel": {
"dont-discover": [
@ -100,9 +94,13 @@
},
"autoload-dev": {
"classmap": [
"tests/TestCase.php",
"tests/unit/BaseTest.php"
]
"tests/DuskTestCase.php",
"tests/TestCase.php"
],
"psr-4": {
"App\\": "app/",
"Tests\\": "tests/"
}
},
"scripts": {
"post-autoload-dump": [
@ -119,4 +117,4 @@
"discard-changes": true,
"process-timeout": 3000
}
}
}

3892
composer.lock generated

File diff suppressed because it is too large Load diff

View file

@ -1,10 +1,10 @@
<?php
return array (
'app_version' => 'v6-pre-alpha',
'full_app_version' => 'v6-pre-alpha - build 6109-gace7abc1a',
'build_version' => '6109',
'full_app_version' => 'v6-pre-alpha - build 6566-ga05fe9c1f',
'build_version' => '6566',
'prerelease_version' => '',
'hash_version' => 'gace7abc1a',
'full_hash' => 'v6-pre-alpha-71-gace7abc1a',
'branch' => 'develop-v6-integration',
'hash_version' => 'ga05fe9c1f',
'full_hash' => 'v6-pre-alpha-7-ga05fe9c1f',
'branch' => 'develop',
);

View file

@ -39,7 +39,6 @@ class ActionlogFactory extends Factory
'item_type' => get_class($asset),
'item_id' => 1,
'user_id' => 1,
'filename' => $this->faker->word,
'action_type' => 'uploaded',
];
}
@ -49,7 +48,7 @@ class ActionlogFactory extends Factory
{
return $this->state(function () {
$target = \App\Models\User::inRandomOrder()->first();
$item = \App\Models\Asset::inRandomOrder()->RTD()->first();
$item = \App\Models\Asset::RTD()->inRandomOrder()->first();
$user_id = rand(1, 2); // keep it simple - make it one of the two superadmins
$asset = Asset::where('id', $item->id)
->update(

View file

@ -5,7 +5,10 @@ namespace Database\Factories;
use App\Models\Asset;
use App\Models\AssetModel;
use App\Models\Category;
use App\Models\Location;
use App\Models\Supplier;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\StatusLabel;
/*
|--------------------------------------------------------------------------
@ -36,16 +39,15 @@ class AssetFactory extends Factory
{
return [
'name' => null,
'rtd_location_id' => rand(1, 10),
'rtd_location_id' => Location::factory()->create(),
'serial' => $this->faker->uuid,
'status_id' => 1,
'status_id' => $this->faker->numberBetween(1,5),
'user_id' => 1,
'asset_tag' => $this->faker->unixTime('now'),
'notes' => 'Created by DB seeder',
'purchase_date' => $this->faker->dateTimeBetween('-1 years', 'now', date_default_timezone_get()),
'purchase_cost' => $this->faker->randomFloat(2, '299.99', '2999.99'),
'order_number' => $this->faker->numberBetween(1000000, 50000000),
'supplier_id' => 1,
'requestable' => $this->faker->boolean(),
'assigned_to' => null,
'assigned_type' => null,

View file

@ -3,6 +3,7 @@
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Category;
/*
|--------------------------------------------------------------------------
@ -81,6 +82,7 @@ class AssetModelFactory extends Factory
{
return [
'user_id' => 1,
'name' => $this->faker->catchPhrase(),
'model_number' => $this->faker->creditCardNumber(),
'notes' => 'Created by demo seeder',
@ -93,7 +95,6 @@ class AssetModelFactory extends Factory
return [
'name' => 'Macbook Pro 13"',
'category_id' => 1,
'manufacturer_id' => 1,
'eol' => '36',
'depreciation_id' => 1,
'image' => 'mbp.jpg',

View file

@ -3,6 +3,7 @@
namespace Database\Factories;
use Illuminate\Database\Eloquent\Factories\Factory;
use App\Models\Category;
/*
|--------------------------------------------------------------------------
@ -30,6 +31,7 @@ class CategoryFactory extends Factory
public function definition()
{
return [
'name' => $this->faker->catchPhrase(),
'checkin_email' => $this->faker->boolean(),
'eula_text' => $this->faker->paragraph(),
'require_acceptance' => false,
@ -38,154 +40,143 @@ class CategoryFactory extends Factory
];
}
// usage: Category::factory()->assetLaptopCategory();
public function assetLaptopCategory()
{
return $this->state(function () {
return [
'name' => 'Laptops',
'category_type' => 'asset',
'require_acceptance' => true,
];
});
return Category::factory()->create([
'name' => 'Laptops',
'category_type' => 'asset',
'require_acceptance' => true,
]);
}
// usage: Category::factory()->assetDesktopCategory();
public function assetDesktopCategory()
{
return $this->state(function () {
return [
'name' => 'Desktops',
'category_type' => 'asset',
];
});
return Category::factory()->create([
'name' => 'Desktops',
'category_type' => 'asset',
'require_acceptance' => true,
]);
}
// usage: Category::factory()->assetDisplayCategory();
public function assetDisplayCategory()
{
return $this->state(function () {
return [
'name' => 'Displays',
'category_type' => 'asset',
];
});
return Category::factory()->create([
'name' => 'Displays',
'category_type' => 'asset',
]);
}
public function assetTabletCategory()
{
return $this->state(function () {
return [
'name' => 'Tablets',
'category_type' => 'asset',
];
});
}
// usage: Category::factory()->assetTabletCategory();
public function assetTabletCategory()
{
return Category::factory()->create([
'name' => 'Tablets',
'category_type' => 'asset',
]);
}
public function assetMobileCategory()
{
return $this->state(function () {
return [
'name' => 'Mobile Phones',
'category_type' => 'asset',
];
});
}
// usage: Category::factory()->assetMobileCategory();
public function assetMobileCategory()
{
return Category::factory()->create([
'name' => 'Mobile Phones',
'category_type' => 'asset',
]);
}
public function assetConferenceCategory()
{
return $this->state(function () {
return [
'name' => 'Conference Phones',
'category_type' => 'asset',
];
});
}
// usage: Category::factory()->assetConferenceCategory();
public function assetConferenceCategory()
{
return Category::factory()->create([
'name' => 'Conference Phones',
'category_type' => 'asset',
]);
}
public function assetVoipCategory()
{
return $this->state(function () {
return [
'name' => 'VOIP Phones',
'category_type' => 'asset',
];
});
}
public function accessoryKeyboardCategory()
{
return $this->state(function () {
return [
'name' => 'Keyboards',
'category_type' => 'accessory',
];
});
}
// usage: Category::factory()->assetVoipCategory();
public function assetVoipCategory()
{
return Category::factory()->create([
'name' => 'VOIP Phones',
'category_type' => 'asset',
]);
}
public function accessoryMouseCategory()
{
return $this->state(function () {
return [
'name' => 'Mouse',
'category_type' => 'accessory',
];
});
}
// usage: Category::factory()->accessoryKeyboardCategory();
public function accessoryKeyboardCategory()
{
return Category::factory()->create([
'name' => 'Keyboardss',
'category_type' => 'accessory',
]);
}
public function componentHddCategory()
{
return $this->state(function () {
return [
'name' => 'HDD/SSD',
'category_type' => 'component',
];
});
}
public function componentRamCategory()
{
return $this->state(function () {
return [
'name' => 'RAM',
'category_type' => 'component',
];
});
}
// usage: Category::factory()->accessoryMouseCategory();
public function accessoryMouseCategory()
{
return Category::factory()->create([
'name' => 'Mouse',
'category_type' => 'accessory',
]);
}
public function consumablePaperCategory()
{
return $this->state(function () {
return [
'name' => 'Printer Paper',
'category_type' => 'consumable',
];
});
}
// usage: Category::factory()->componentHddCategory();
public function componentHddCategory()
{
return Category::factory()->create([
'name' => 'HDD/SSD',
'category_type' => 'component',
]);
}
public function consumableInkCategory()
{
return $this->state(function () {
return [
'name' => 'Printer Ink',
'category_type' => 'consumable',
];
});
}
// usage: Category::factory()->componentRamCategory();
public function componentRamCategory()
{
return Category::factory()->create([
'name' => 'RAM',
'category_type' => 'component',
]);
}
public function licenseGraphicsCategory()
{
return $this->state(function () {
return [
'name' => 'Graphics Software',
'category_type' => 'license',
];
});
}
// usage: Category::factory()->consumablePaperCategory();
public function consumablePaperCategory()
{
return Category::factory()->create([
'name' => 'Printer Paper',
'category_type' => 'consumable',
]);
}
// usage: Category::factory()->consumableInkCategory();
public function consumableInkCategory()
{
return Category::factory()->create([
'name' => 'Printer Ink',
'category_type' => 'consumable',
]);
}
// usage: Category::factory()->licenseGraphicsCategory();
public function licenseGraphicsCategory()
{
return Category::factory()->create([
'name' => 'Graphics Software',
'category_type' => 'license',
]);
}
// usage: Category::factory()->licenseGraphicsCategory();
public function licenseOfficeCategory()
{
return Category::factory()->create([
'name' => 'Office Software',
'category_type' => 'license',
]);
}
public function licenseOfficeCategory()
{
return $this->state(function () {
return [
'name' => 'Office Software',
'category_type' => 'license',
];
});
}
}

View file

@ -30,7 +30,9 @@ class DepreciationFactory extends Factory
public function definition()
{
return [
'name' => $this->faker->catchPhrase(),
'user_id' => 1,
'months' => 36,
];
}

View file

@ -1,36 +1,11 @@
<?php
/*
|--------------------------------------------------------------------------
| Model Factories
|--------------------------------------------------------------------------
|
| Here you may define all of your model factories. Model factories give
| you a convenient way to create models for testing and seeding your
| database. Just tell the factory how a default model should look.
|
*/
namespace Database\Factories;
use App\Models\AssetModel;
use App\Models\Category;
use App\Models\Company;
use App\Models\Location;
use App\Models\Manufacturer;
use App\Models\Statuslabel;
use App\Models\Supplier;
use Illuminate\Database\Eloquent\Factories\Factory;
class LocationFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = \App\Models\Location::class;
/**
* Define the model's default state.
*
@ -39,15 +14,17 @@ class LocationFactory extends Factory
public function definition()
{
return [
'name' => $this->faker->city,
'address' => $this->faker->streetAddress,
'address2' => $this->faker->secondaryAddress,
'city' => $this->faker->city,
'state' => $this->faker->stateAbbr,
'country' => $this->faker->countryCode,
'currency' => $this->faker->currencyCode,
'zip' => $this->faker->postcode,
'name' => $this->faker->city(),
'address' => $this->faker->streetAddress(),
'address2' => $this->faker->secondaryAddress(),
'city' => $this->faker->city(),
'state' => $this->faker->stateAbbr(),
'country' => $this->faker->countryCode(),
'currency' => $this->faker->currencyCode(),
'zip' => $this->faker->postcode(),
'image' => rand(1, 9).'.jpg',
];
}
}

View file

@ -2,19 +2,11 @@
namespace Database\Factories;
use App\Models\Company;
use Illuminate\Database\Eloquent\Factories\Factory;
use \Auth;
class UserFactory extends Factory
{
/**
* The name of the factory's corresponding model.
*
* @var string
*/
protected $model = \App\Models\User::class;
/**
* Define the model's default state.
*
@ -22,23 +14,21 @@ class UserFactory extends Factory
*/
public function definition()
{
$password = bcrypt('password');
return [
'activated' => 1,
'address' => $this->faker->address,
'city' => $this->faker->city,
'address' => $this->faker->address(),
'city' => $this->faker->city(),
'company_id' => rand(1, 4),
'country' => $this->faker->country,
'country' => $this->faker->country(),
'department_id' => rand(1, 6),
'email' => $this->faker->safeEmail,
'employee_num' => $this->faker->numberBetween(3500, 35050),
'first_name' => $this->faker->firstName,
'jobtitle' => $this->faker->jobTitle,
'last_name' => $this->faker->lastName,
'locale' => $this->faker->locale,
'location_id' => rand(1, 5),
'first_name' => $this->faker->firstName(),
'jobtitle' => $this->faker->jobTitle(),
'last_name' => $this->faker->lastName(),
'locale' => $this->faker->locale(),
'notes' => 'Created by DB seeder',
'password' => $password,
'password' => '$2y$10$92IXUNpkjO0rOQ5byMi.Ye4oKoEa3Ro9llC/.og/at2.uheWG/igi', // password
'permissions' => '{"user":"0"}',
'phone' => $this->faker->phoneNumber,
'state' => $this->faker->stateAbbr,
@ -46,7 +36,7 @@ class UserFactory extends Factory
'zip' => $this->faker->postcode,
];
}
public function firstAdmin()
{
return $this->state(function () {
@ -407,4 +397,5 @@ class UserFactory extends Factory
];
});
}
}

View file

@ -0,0 +1,36 @@
<?php
use Illuminate\Database\Migrations\Migration;
use Illuminate\Database\Schema\Blueprint;
use Illuminate\Support\Facades\Schema;
class ChangeSupplierAddressLength extends Migration
{
/**
* Run the migrations.
*
* @return void
*/
public function up()
{
Schema::table('suppliers', function (Blueprint $table) {
//
$table->string('address', 250)->nullable()->change();
$table->string('address2', 250)->nullable()->change();
});
}
/**
* Reverse the migrations.
*
* @return void
*/
public function down()
{
Schema::table('suppliers', function (Blueprint $table) {
//
$table->text('address', 50)->nullable()->default(null)->change();
$table->text('address2', 50)->nullable()->default(null)->change();
});
}
}

View file

@ -1,72 +0,0 @@
<?php
use Illuminate\Database\Seeder;
use App\Models\AssetModel;
use Illuminate\Support\Facades\Storage;
class AssetModelSeeder extends Seeder
{
public function run()
{
AssetModel::truncate();
// Laptops
factory(AssetModel::class, 1)->states('mbp-13-model')->create(); // 1
factory(AssetModel::class, 1)->states('mbp-air-model')->create(); // 2
factory(AssetModel::class, 1)->states('surface-model')->create(); // 3
factory(AssetModel::class, 1)->states('xps13-model')->create(); // 4
factory(AssetModel::class, 1)->states('spectre-model')->create(); // 5
factory(AssetModel::class, 1)->states('zenbook-model')->create(); // 6
factory(AssetModel::class, 1)->states('yoga-model')->create(); // 7
// Desktops
factory(AssetModel::class, 1)->states('macpro-model')->create(); // 8
factory(AssetModel::class, 1)->states('lenovo-i5-model')->create(); // 9
factory(AssetModel::class, 1)->states('optiplex-model')->create(); // 10
// Conference Phones
factory(AssetModel::class, 1)->states('polycom-model')->create(); // 11
factory(AssetModel::class, 1)->states('polycomcx-model')->create(); // 12
// Tablets
factory(AssetModel::class, 1)->states('ipad-model')->create(); // 13
factory(AssetModel::class, 1)->states('tab3-model')->create(); // 14
// Phones
factory(AssetModel::class, 1)->states('iphone11-model')->create(); // 15
factory(AssetModel::class, 1)->states('iphone12-model')->create(); // 16
// Displays
factory(AssetModel::class, 1)->states('ultrafine')->create(); // 17
factory(AssetModel::class, 1)->states('ultrasharp')->create(); // 18
$src = public_path('/img/demo/models/');
$dst = 'models'.'/';
$del_files = Storage::files($dst);
foreach($del_files as $del_file){ // iterate files
$file_to_delete = str_replace($src,'',$del_file);
\Log::debug('Deleting: '.$file_to_delete);
try {
Storage::disk('public')->delete($dst.$del_file);
} catch (\Exception $e) {
\Log::debug($e);
}
}
$add_files = glob($src."/*.*");
foreach($add_files as $add_file){
$file_to_copy = str_replace($src,'',$add_file);
\Log::debug('Copying: '.$file_to_copy);
try {
Storage::disk('public')->put($dst.$file_to_copy, file_get_contents($src.$file_to_copy));
} catch (\Exception $e) {
\Log::debug($e);
}
}
}
}

View file

@ -1,4 +1,4 @@
#!/usr/bin/env python
#!/usr/bin/env python3
# A supervisor event listener which terminates supervisord if any of its child
# processes enter the FATAL state.
# https://stackoverflow.com/a/37527488/119527

2922
package-lock.json generated

File diff suppressed because it is too large Load diff

View file

@ -17,14 +17,16 @@
"axios": "^0.20.0",
"babel-preset-latest": "^6.24.1",
"jquery": "^3.6.0",
"laravel-mix": "^6.0.12",
"laravel-mix": "^6.0.39",
"lodash": "^4.17.20",
"postcss": "^8.2.8",
"postcss": "^8.4.5",
"vue": "2.4.4",
"vue-loader": "^15.9.7",
"vue-template-compiler": "2.4.4"
},
"dependencies": {
"acorn": "^8.6.0",
"acorn-import-assertions": "^1.8.0",
"admin-lte": "^2.4.18",
"ajv": "^6.12.6",
"blueimp-file-upload": "^9.34.0",
@ -32,7 +34,7 @@
"bootstrap-colorpicker": "^2.5.3",
"bootstrap-datepicker": "^1.9.0",
"bootstrap-less": "^3.3.8",
"bootstrap-table": "^1.18.3",
"bootstrap-table": "^1.19.1",
"chart.js": "^2.9.4",
"css-loader": "^3.6.0",
"ekko-lightbox": "^5.1.1",
@ -41,17 +43,19 @@
"imagemin": "^5.3.1",
"jquery-form-validator": "^2.3.79",
"jquery-slimscroll": "^1.3.8",
"jquery-ui": "^1.12.1",
"jquery-ui": "^1.13.0",
"jquery-ui-bundle": "^1.12.1",
"jquery.iframe-transport": "^1.0.0",
"less": "^4.1.1",
"jspdf-autotable": "^3.5.23",
"less": "^4.1.2",
"less-loader": "^5.0.0",
"list.js": "^1.5.0",
"papaparse": "^4.3.3",
"select2": "4.0.13",
"sheetjs": "^2.0.0",
"tableexport.jquery.plugin": "^1.10.26",
"tableexport.jquery.plugin": "^1.21.0",
"tether": "^1.4.0",
"vue-resource": "^1.5.2"
"vue-resource": "^1.5.2",
"webpack": "^5.65.0"
}
}

View file

@ -1,34 +1,22 @@
<?xml version="1.0" encoding="UTF-8"?>
<phpunit backupGlobals="false"
backupStaticAttributes="false"
bootstrap="bootstrap/autoload.php"
colors="true"
convertErrorsToExceptions="true"
convertNoticesToExceptions="true"
convertWarningsToExceptions="true"
processIsolation="false"
stopOnFailure="false">
<testsuites>
<testsuite name="Application Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<filter>
<whitelist>
<directory suffix=".php">app/</directory>
</whitelist>
</filter>
<php>
<env name="APP_ENV" value="testing-ci"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="DB_CONNECTION" value="sqlite_testing" />
<server name="SERVER_NAME" value="http://testing.dev"/>
</php>
<logging>
<log type="coverage-clover" target="build/logs/clover.xml"/>
</logging>
<phpunit xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" backupGlobals="false" backupStaticAttributes="false" bootstrap="bootstrap/autoload.php" colors="true" convertErrorsToExceptions="true" convertNoticesToExceptions="true" convertWarningsToExceptions="true" processIsolation="false" stopOnFailure="false" xsi:noNamespaceSchemaLocation="https://schema.phpunit.de/9.3/phpunit.xsd">
<coverage>
<include>
<directory suffix=".php">app/</directory>
</include>
</coverage>
<testsuites>
<testsuite name="Application Test Suite">
<directory>./tests/</directory>
</testsuite>
</testsuites>
<php>
<env name="APP_ENV" value="testing-ci"/>
<env name="CACHE_DRIVER" value="array"/>
<env name="SESSION_DRIVER" value="array"/>
<env name="QUEUE_DRIVER" value="sync"/>
<env name="DB_CONNECTION" value="sqlite"/>
<server name="SERVER_NAME" value="http://127.0.0.1:8000"/>
<ini name="display_errors" value="true"/>
</php>
</phpunit>

View file

@ -6,7 +6,7 @@
RewriteEngine On
# Needed for https://letsencrypt.org/ certificates.
RewriteRule ^\.well-known/acme-challenge/ - [END]
RewriteRule ^\.well-known/acme-challenge/ - [L]
# Uncomment these two lines to force SSL redirect in Apache
# RewriteCond %{HTTPS} off

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

BIN
public/js/dist/all.js vendored

Binary file not shown.

Binary file not shown.

Binary file not shown.

View file

@ -1,8 +1,8 @@
{
"/js/build/app.js": "/js/build/app.js?id=c8a70594c0d99275266d",
"/js/build/app.js": "/js/build/app.js?id=c015308b9685c9375c71",
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=83e39e254b7f9035eddc",
"/css/build/overrides.css": "/css/build/overrides.css?id=b1866ec98d44c0a8ceea",
"/css/build/app.css": "/css/build/app.css?id=61d5535cb27cce41d422",
"/css/build/overrides.css": "/css/build/overrides.css?id=4fc3a0e0a16964643e70",
"/css/build/app.css": "/css/build/app.css?id=a7cd7ad6e0e053ccf443",
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=65ca7a34198fa16ba846",
"/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=83271cb3576583918804",
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=d81888449b72ecd8dd24",
@ -18,15 +18,15 @@
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=efda2335fa5243175850",
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=6a9d0ac448c28b88e5d6",
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=c24716a423d375902723",
"/css/dist/all.css": "/css/dist/all.css?id=138874c5ffe57b679997",
"/css/dist/all.css": "/css/dist/all.css?id=2ee76a9bb4100b60febc",
"/css/blue.png": "/css/blue.png?id=e83a6c29e04fe851f212",
"/css/blue@2x.png": "/css/blue@2x.png?id=51135dd4d24f88f5de0b",
"/css/dist/signature-pad.css": "/css/dist/signature-pad.css?id=6a89d3cd901305e66ced",
"/css/dist/signature-pad.min.css": "/css/dist/signature-pad.min.css?id=6a89d3cd901305e66ced",
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=93c24b4c89490bbfd73e",
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=810d7e520c3057ee500e",
"/js/build/vendor.js": "/js/build/vendor.js?id=651427cc4b45d8e68d0c",
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=867755a1544f6c0ea828",
"/js/dist/all.js": "/js/dist/all.js?id=a233dcde4650f5d34491",
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=7058545374c5c6a6a881",
"/js/dist/all.js": "/js/dist/all.js?id=b12eaebad0af2541f40b",
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=efda2335fa5243175850",
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=6e35fb4cb2f1063b3047",
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=ec96c42439cdeb022133",

View file

@ -158,6 +158,7 @@
consumables: [
{id: 'item_no', text: "Item Number"},
{id: 'model_number', text: "Model Number"},
{id: 'min_amt', text: "Minimum Quantity"},
],
licenses: [
{id: 'asset_tag', text: 'Assigned To Asset'},
@ -177,7 +178,6 @@
{id: 'phone_number', text: 'Phone Number' },
{id: 'manager_first_name', text: 'Manager First Name' },
{id: 'manager_last_name', text: 'Manager Last Name' },
{id: 'department', text: 'Department' },
{id: 'activated', text: 'Activated' },
{id: 'address', text: 'Address' },
{id: 'city', text: 'City' },
@ -216,6 +216,7 @@
.concat(this.columnOptions.accessories)
.sort(sorter);
case 'consumable':
console.log('Returned consumable');
return this.columnOptions.general
.concat(this.columnOptions.consumables)
.sort(sorter);
@ -309,4 +310,4 @@
select2: require('../select2.vue').default
}
}
</script>
</script>

View file

@ -84,6 +84,37 @@ var baseUrl = $('meta[name="baseUrl"]').attr('content');
var Components = {};
Components.modals = {};
// confirm restore modal
Components.modals.confirmRestore = function() {
var $el = $('table');
var events = {
'click': function(evnt) {
var $context = $(this);
var $restoreConfirmModal = $('#restoreConfirmModal');
var href = $context.attr('href');
var message = $context.attr('data-content');
var title = $context.attr('data-title');
$('#restoreConfirmModalLabel').text(title);
$restoreConfirmModal.find('.modal-body').text(message);
$('#restoreForm').attr('action', href);
$restoreConfirmModal.modal({
show: true
});
return false;
}
};
var render = function() {
$el.on('click', '.restore-asset', events['click']);
};
return {
render: render
};
};
// confirm delete modal
Components.modals.confirmDelete = function() {
var $el = $('table');
@ -121,6 +152,7 @@ var baseUrl = $('meta[name="baseUrl"]').attr('content');
* Component definition stays out of load event, execution only happens.
*/
$(function() {
new Components.modals.confirmRestore().render();
new Components.modals.confirmDelete().render();
});
}(jQuery, window.snipeit.settings));

View file

@ -571,7 +571,7 @@ th.css-envelope > .th-inner,
th.css-accessory > .th-inner
{
font-size: 0px;
line-height: 4!important;
line-height: .75!important;
text-align: left;
text-rendering: auto;
-webkit-font-smoothing: antialiased;
@ -588,41 +588,46 @@ th.css-accessory > .th-inner::before
{
display: inline-block;
font: normal normal normal 14px/1 FontAwesome;
font-size: 20px;
font-family: "Font Awesome 5 Free";
font-weight: 300;
}
th.css-padlock > .th-inner::before
{
content: "\f023";
content: "\f023"; font-family: "Font Awesome 5 Free"; font-weight: 400;
padding-right: 2px;
}
/**
Set the font-weight css property as 900 (For Solid), 400 (Regular or Brands), 300 (Light for pro icons).
**/
th.css-barcode > .th-inner::before
{
content: "\f02a";
content: "\f02a"; font-family: "Font Awesome 5 Free"; font-weight: 900;
}
th.css-license > .th-inner::before
{
content: "\f0c7";
content: "\f0c7"; font-family: "Font Awesome 5 Free"; font-weight: 400;
}
th.css-consumable > .th-inner::before
{
content: "\f043";
content: "\f043"; font-family: "Font Awesome 5 Free"; font-weight: 900;
}
th.css-envelope > .th-inner::before
{
content: "\f003";
content: "\f0e0"; font-family: "Font Awesome 5 Free"; font-weight: 400;
}
th.css-accessory > .th-inner::before
{
content: "\f11c";
content: "\f11c"; font-family: "Font Awesome 5 Free"; font-weight: 400;
}
.small-box .inner {
padding-left: 15px;
padding-right: 15px;

View file

@ -18,5 +18,6 @@ return [
'update' => 'Opdateer kategorie',
'use_default_eula' => 'Gebruik eerder die <a href="#" data-toggle="modal" data-target="#eulaModal">primary standaard EULA</a>.',
'use_default_eula_disabled' => '<del>Gebruik die primêre standaardverlof in plaas daarvan.</del> Geen primêre standaard EULA is ingestel nie. Voeg asseblief een by Instellings.',
'use_default_eula_column' => 'Use default EULA',
];

View file

@ -61,9 +61,12 @@ return [
'label_logo' => 'Label Logo',
'label_logo_size' => 'Square logos look best - will be displayed in the top right of each asset label. ',
'laravel' => 'Laravel Weergawe',
'ldap_client_tls_cert' => 'LDAP Client-Side TLS Certificate',
'ldap_enabled' => 'LDAP aangeskakel',
'ldap_integration' => 'LDAP-integrasie',
'ldap_settings' => 'LDAP-instellings',
'ldap_client_tls_cert_help' => 'Client-Side TLS Certificate and Key for LDAP connections are usually only useful in Google Workspace configurations with "Secure LDAP." Both are required.',
'ldap_client_tls_key' => 'LDAP Client-Side TLS key',
'ldap_login_test_help' => 'Enter a valid LDAP username and password from the base DN you specified above to test whether your LDAP login is configured correctly. YOU MUST SAVE YOUR UPDATED LDAP SETTINGS FIRST.',
'ldap_login_sync_help' => 'This only tests that LDAP can sync correctly. If your LDAP Authentication query is not correct, users may still not be able to login. YOU MUST SAVE YOUR UPDATED LDAP SETTINGS FIRST.',
'ldap_server' => 'LDAP-bediener',

View file

@ -13,6 +13,7 @@ return [
'user_deleted_warning' => 'Hierdie gebruiker is verwyder. Jy sal hierdie gebruiker moet herstel om hulle te wysig of nuwe bates toe te ken.',
'ldap_not_configured' => 'LDAP-integrasie is nie vir hierdie installasie gekonfigureer nie.',
'password_resets_sent' => 'The selected users who are activated and have a valid email addresses have been sent a password reset link.',
'password_reset_sent' => 'A password reset link has been sent to :email!',
'success' => [
'create' => 'Gebruiker is suksesvol geskep.',

View file

@ -1,6 +1,6 @@
<?php
return [
return array(
'actions' => 'aksies',
'add' => 'Voeg nuwe',
'cancel' => 'kanselleer',
@ -11,7 +11,8 @@ return [
'request' => 'versoek',
'submit' => 'Indien',
'upload' => 'oplaai',
'select_file' => 'Kies lêer ...',
'select_file' => 'Kies lêer ...',
'select_files' => 'Select Files...',
'generate_labels' => '{1} Generate Label|[2,*] Generate Labels',
];
'send_password_link' => 'Send Password Reset Link',
);

View file

@ -18,5 +18,6 @@ return array(
'update' => 'Update Category',
'use_default_eula' => 'Use the <a href="#" data-toggle="modal" data-target="#eulaModal">primary default EULA</a> instead.',
'use_default_eula_disabled' => '<del>Use the primary default EULA instead.</del> No primary default EULA is set. Please add one in Settings.',
'use_default_eula_column' => 'Use default EULA',
);

View file

@ -61,9 +61,12 @@ return array(
'label_logo' => 'Label Logo',
'label_logo_size' => 'Square logos look best - will be displayed in the top right of each asset label. ',
'laravel' => 'Laravel Version',
'ldap_client_tls_cert' => 'LDAP Client-Side TLS Certificate',
'ldap_enabled' => 'LDAP enabled',
'ldap_integration' => 'LDAP Integration',
'ldap_settings' => 'LDAP Settings',
'ldap_client_tls_cert_help' => 'Client-Side TLS Certificate and Key for LDAP connections are usually only useful in Google Workspace configurations with "Secure LDAP." Both are required.',
'ldap_client_tls_key' => 'LDAP Client-Side TLS key',
'ldap_login_test_help' => 'Enter a valid LDAP username and password from the base DN you specified above to test whether your LDAP login is configured correctly. YOU MUST SAVE YOUR UPDATED LDAP SETTINGS FIRST.',
'ldap_login_sync_help' => 'This only tests that LDAP can sync correctly. If your LDAP Authentication query is not correct, users may still not be able to login. YOU MUST SAVE YOUR UPDATED LDAP SETTINGS FIRST.',
'ldap_server' => 'LDAP Server',

View file

@ -13,6 +13,7 @@ return array(
'user_deleted_warning' => 'This user has been deleted. You will have to restore this user to edit them or assign them new assets.',
'ldap_not_configured' => 'LDAP integration has not been configured for this installation.',
'password_resets_sent' => 'The selected users who are activated and have a valid email addresses have been sent a password reset link.',
'password_reset_sent' => 'A password reset link has been sent to :email!',
'success' => array(
@ -38,10 +39,10 @@ return array(
'asset_already_accepted' => 'This asset has already been accepted.',
'accept_or_decline' => 'You must either accept or decline this asset.',
'incorrect_user_accepted' => 'The asset you have attempted to accept was not checked out to you.',
'ldap_could_not_connect' => 'Could not connect to the LDAP server. Please check your LDAP server configuration in Admin Settings > LDAP/AD <br>Error from LDAP Server:',
'ldap_could_not_bind' => 'Could not bind to the LDAP server. Please check your LDAP server configuration in Admin Settings > LDAP/AD<br>Error from LDAP Server: ',
'ldap_could_not_search' => 'Could not search the LDAP server. Please check your LDAP server configuration in Admin Settings > LDAP/AD and any Locations that may have additional OUs associated with them. <br>Error from LDAP Server:',
'ldap_could_not_get_entries' => 'Could not get entries from the LDAP server. Please check your LDAP server configuration in Admin Settings > LDAP/AD and any Locations that may have additional OUs associated with them. <br>Error from LDAP Server:',
'ldap_could_not_connect' => 'Could not connect to the LDAP server. Please check your LDAP server configuration in the LDAP config file. <br>Error from LDAP Server:',
'ldap_could_not_bind' => 'Could not bind to the LDAP server. Please check your LDAP server configuration in the LDAP config file. <br>Error from LDAP Server: ',
'ldap_could_not_search' => 'Could not search the LDAP server. Please check your LDAP server configuration in the LDAP config file. <br>Error from LDAP Server:',
'ldap_could_not_get_entries' => 'Could not get entries from the LDAP server. Please check your LDAP server configuration in the LDAP config file. <br>Error from LDAP Server:',
'password_ldap' => 'The password for this account is managed by LDAP/Active Directory. Please contact your IT department to change your password. ',
),

View file

@ -14,4 +14,5 @@ return array(
'select_file' => 'Select File...',
'select_files' => 'Select Files...',
'generate_labels' => '{1} Generate Label|[2,*] Generate Labels',
'send_password_link' => 'Send Password Reset Link',
);

View file

@ -18,5 +18,6 @@ return [
'update' => 'تحديث التصنيف',
'use_default_eula' => 'قم باستعمال <a href="#" data-toggle="modal" data-target="#eulaModal">إتفاقية الترخيص الإفتراضية</a>.',
'use_default_eula_disabled' => '<del>استخدام (اتفاقية ترخيص المستخدم) الافتراضية الأساسية بدلا من ذلك.</del> لم يتم تحديد (اتفاقية ترخيص المستخدم) الافتراضية الأساسية. الرجاء إضافتها من الإعدادات.',
'use_default_eula_column' => 'استخدم EULA الافتراضي',
];

View file

@ -8,6 +8,6 @@ return [
'depreciation_name' => 'اسم الاستهلاك',
'number_of_months' => 'عدد الأشهر',
'update' => 'تحديث الاستهلاك',
'depreciation_min' => 'Minimum Value after Depreciation'
'depreciation_min' => 'الحد الأدنى للقيمة بعد الاستهلاك'
];

View file

@ -10,9 +10,9 @@ return [
'checkout' => 'اخراج الأصل',
'clone' => 'استنساخ الأصل',
'deployable' => 'قابل للتوزيع',
'deleted' => 'This asset has been deleted.',
'deleted' => 'تم حذف هذا الأصل.',
'edit' => 'تعديل الأصل',
'model_deleted' => 'This Assets model has been deleted. You must restore the model before you can restore the Asset.',
'model_deleted' => 'تم حذف موديل الأصول هذا. يجب استعادة الموديل قبل أن تتمكن من استعادة الأصل.',
'requestable' => 'قابل للطلب',
'requested' => 'تم الطلب',
'restore' => 'استعادة الأصل',

View file

@ -3,7 +3,7 @@
return [
'about_models_title' => 'حول موديلات الأصول',
'about_models_text' => 'موديلات الأصول هي طريقة لتجميع الأصول المتطابقة "MBP 2013", "IPhone 6s", الخ.',
'deleted' => 'This model has been deleted.',
'deleted' => 'تم حذف هذا الموديل.',
'bulk_delete' => 'حذف موديلات الاصول بالجملة',
'bulk_delete_help' => 'استخدم مربعات الاختيار أدناه لتأكيد حذف موديلات الأصول المحددة. لا يمكن حذف موديلات الأصول التي تحتوي على أصول مرتبطة بها إلى أن يتم ربط الأصول بموديل مختلف.',
'bulk_delete_warn' => 'أنت على وشك حذف :model_count من موديلات الأصول.',

View file

@ -61,9 +61,12 @@ return array(
'label_logo' => 'شعار التسمية',
'label_logo_size' => 'الشعارات المربعة تبدو أفضل - سيتم عرضها في أعلى يمين كل ملصق أصل. ',
'laravel' => 'نسخة لارافيل',
'ldap_client_tls_cert' => 'LDAP Client-Side TLS Certificate',
'ldap_enabled' => 'تم تمكين لداب',
'ldap_integration' => 'دمج لداب',
'ldap_settings' => 'إعدادات لداب',
'ldap_client_tls_cert_help' => 'Client-Side TLS Certificate and Key for LDAP connections are usually only useful in Google Workspace configurations with "Secure LDAP." Both are required.',
'ldap_client_tls_key' => 'LDAP Client-Side TLS key',
'ldap_login_test_help' => 'أدخل اسم مستخدم وكلمة مرور LDAP من الاسم المميز الأساسي DN الذي حددته أعلاه لاختبار ما إذا كان قد تمت تهيئة معلومات تسجيل الدخول إلى LDAP بشكل صحيح أم لا. يجب حفظ تحديث LDAP الخاص بك أولا.',
'ldap_login_sync_help' => 'هذا يختبر فقط أن LDAP يستطيع المزامنة بشكل صحيح. إذا كان استعلام التوثيق الى LDAP الخاص بك غير صحيح، قد لا يزال المستخدمون غير قادرين على تسجيل الدخول. يجب عليك اولا حفظ اي تغييرات في إعدادات LDAP.',
'ldap_server' => 'خادم لداب',

View file

@ -13,6 +13,7 @@ return [
'user_deleted_warning' => 'تم حذف المستخدم. سيكون عليك استعادة هذا المستخدم اذا ارت التعديل عليه او تسليمه اجهزة جديدة.',
'ldap_not_configured' => 'لم يتم تكوين دمج لداب لهذا التثبيت.',
'password_resets_sent' => 'تم إرسال رابط إعادة تعيين كلمة المرور للمستخدمين المحددين الذين تم تفعيلهم ولديهم عناوين بريد إلكتروني صالحة.',
'password_reset_sent' => 'تم إرسال رابط إعادة تعيين كلمة المرور إلى البريد الإلكتروني!',
'success' => [
'create' => 'تم إنشاء المستخدم بنجاح.',

View file

@ -1,6 +1,6 @@
<?php
return [
return array(
'actions' => 'الإجراءات',
'add' => 'إضافة جديد',
'cancel' => 'إلغاء',
@ -11,7 +11,8 @@ return [
'request' => 'طلب',
'submit' => 'إرسال',
'upload' => 'رفع',
'select_file' => 'حدد ملف ...',
'select_file' => 'حدد ملف ...',
'select_files' => 'إختيار ملف...',
'generate_labels' => '{1} انشاء تسميات [2,*] توليد تسميات',
];
'send_password_link' => 'إرسال رابط إعادة تعيين كلمة السر',
);

View file

@ -176,7 +176,7 @@
'remove_company' => 'إزالة جمعية الشركة',
'reports' => 'التقارير',
'restored' => 'المعاد',
'restore' => 'Restore',
'restore' => 'إستعادة',
'requested' => 'طلب',
'request_canceled' => 'تم إلغاء الطلب',
'save' => 'حفظ',

View file

@ -18,5 +18,6 @@ return [
'update' => 'Обновяване на категория',
'use_default_eula' => 'Използване на <a href="#" data-toggle="modal" data-target="#eulaModal">EULA по подразбиране</a>.',
'use_default_eula_disabled' => '<del>Използване на EULA по подразбиране</del> Няма EULA по подразбиране. Добавете я в Настройки.',
'use_default_eula_column' => 'Use default EULA',
];

View file

@ -61,9 +61,12 @@ return array(
'label_logo' => 'Лого за етикет',
'label_logo_size' => 'Квадратните логота изглеждат най-добре - ще бъдат показани в горния десен ъгъл на всеки артикулен етикет. ',
'laravel' => 'Версия на Laravel',
'ldap_client_tls_cert' => 'LDAP Client-Side TLS Certificate',
'ldap_enabled' => 'LDAP включен',
'ldap_integration' => 'LDAP интеграция',
'ldap_settings' => 'LDAP настройки',
'ldap_client_tls_cert_help' => 'Client-Side TLS Certificate and Key for LDAP connections are usually only useful in Google Workspace configurations with "Secure LDAP." Both are required.',
'ldap_client_tls_key' => 'LDAP Client-Side TLS key',
'ldap_login_test_help' => 'Въведете валидни LDAP потребител и парола от базовия DN, който указахте по-горе, за да тествате коректната конфигурация. НЕОБХОДИМО Е ДА ЗАПИШЕТЕ LDAP НАСТРОЙКИТЕ ПРЕДИ ТОВА.',
'ldap_login_sync_help' => 'Това единствено проверява дали LDAP може да се синхронизира успешно. Ако вашата LDAP заявка за оторизация не е коректна е възможно потребителите да не могат да влязат. НЕОБХОДИМО Е ДА ЗАПИШЕТЕ LDAP НАСТРОЙКИТЕ ПРЕДИ ТОВА.',
'ldap_server' => 'LDAP сървър',

View file

@ -13,6 +13,7 @@ return [
'user_deleted_warning' => 'Този потребител е изтрит. За да редактирате данните за него или да му зададете актив, трябва първо да възстановите потребителя.',
'ldap_not_configured' => 'Интеграцията с LDAP не е конфигурирана за тази инсталация.',
'password_resets_sent' => 'Избраните потребители, които са активирани и имат валиден е-майл адрес им беше изпратен линк за смяна на парола.',
'password_reset_sent' => 'A password reset link has been sent to :email!',
'success' => [
'create' => 'Потребителят е създаден.',

View file

@ -1,6 +1,6 @@
<?php
return [
return array(
'actions' => 'Действия',
'add' => 'Добави нов',
'cancel' => 'Отказ',
@ -11,7 +11,8 @@ return [
'request' => 'Заявка',
'submit' => 'Потвърди',
'upload' => 'Качване',
'select_file' => 'Изберете файл...',
'select_file' => 'Изберете файл...',
'select_files' => 'Изберете файлове...',
'generate_labels' => '{1} Генерирай Етикет|[2,*] Генерирай Етикети',
];
'send_password_link' => 'Send Password Reset Link',
);

View file

@ -18,5 +18,6 @@ return array(
'update' => 'Update Category',
'use_default_eula' => 'Use the <a href="#" data-toggle="modal" data-target="#eulaModal">primary default EULA</a> instead.',
'use_default_eula_disabled' => '<del>Use the primary default EULA instead.</del> No primary default EULA is set. Please add one in Settings.',
'use_default_eula_column' => 'Use default EULA',
);

View file

@ -61,9 +61,12 @@ return array(
'label_logo' => 'Label Logo',
'label_logo_size' => 'Square logos look best - will be displayed in the top right of each asset label. ',
'laravel' => 'Laravel Version',
'ldap_client_tls_cert' => 'LDAP Client-Side TLS Certificate',
'ldap_enabled' => 'LDAP enabled',
'ldap_integration' => 'LDAP Integration',
'ldap_settings' => 'LDAP Settings',
'ldap_client_tls_cert_help' => 'Client-Side TLS Certificate and Key for LDAP connections are usually only useful in Google Workspace configurations with "Secure LDAP." Both are required.',
'ldap_client_tls_key' => 'LDAP Client-Side TLS key',
'ldap_login_test_help' => 'Enter a valid LDAP username and password from the base DN you specified above to test whether your LDAP login is configured correctly. YOU MUST SAVE YOUR UPDATED LDAP SETTINGS FIRST.',
'ldap_login_sync_help' => 'This only tests that LDAP can sync correctly. If your LDAP Authentication query is not correct, users may still not be able to login. YOU MUST SAVE YOUR UPDATED LDAP SETTINGS FIRST.',
'ldap_server' => 'LDAP Server',

View file

@ -13,6 +13,7 @@ return array(
'user_deleted_warning' => 'This user has been deleted. You will have to restore this user to edit them or assign them new assets.',
'ldap_not_configured' => 'LDAP integration has not been configured for this installation.',
'password_resets_sent' => 'The selected users who are activated and have a valid email addresses have been sent a password reset link.',
'password_reset_sent' => 'A password reset link has been sent to :email!',
'success' => array(
@ -38,10 +39,10 @@ return array(
'asset_already_accepted' => 'This asset has already been accepted.',
'accept_or_decline' => 'You must either accept or decline this asset.',
'incorrect_user_accepted' => 'The asset you have attempted to accept was not checked out to you.',
'ldap_could_not_connect' => 'Could not connect to the LDAP server. Please check your LDAP server configuration in Admin Settings > LDAP/AD <br>Error from LDAP Server:',
'ldap_could_not_bind' => 'Could not bind to the LDAP server. Please check your LDAP server configuration in Admin Settings > LDAP/AD<br>Error from LDAP Server: ',
'ldap_could_not_search' => 'Could not search the LDAP server. Please check your LDAP server configuration in Admin Settings > LDAP/AD and any Locations that may have additional OUs associated with them. <br>Error from LDAP Server:',
'ldap_could_not_get_entries' => 'Could not get entries from the LDAP server. Please check your LDAP server configuration in Admin Settings > LDAP/AD and any Locations that may have additional OUs associated with them. <br>Error from LDAP Server:',
'ldap_could_not_connect' => 'Could not connect to the LDAP server. Please check your LDAP server configuration in the LDAP config file. <br>Error from LDAP Server:',
'ldap_could_not_bind' => 'Could not bind to the LDAP server. Please check your LDAP server configuration in the LDAP config file. <br>Error from LDAP Server: ',
'ldap_could_not_search' => 'Could not search the LDAP server. Please check your LDAP server configuration in the LDAP config file. <br>Error from LDAP Server:',
'ldap_could_not_get_entries' => 'Could not get entries from the LDAP server. Please check your LDAP server configuration in the LDAP config file. <br>Error from LDAP Server:',
'password_ldap' => 'The password for this account is managed by LDAP/Active Directory. Please contact your IT department to change your password. ',
),

View file

@ -14,4 +14,5 @@ return array(
'select_file' => 'Select File...',
'select_files' => 'Select Files...',
'generate_labels' => '{1} Generate Label|[2,*] Generate Labels',
'send_password_link' => 'Send Password Reset Link',
);

View file

@ -18,5 +18,6 @@ return [
'update' => 'Upravit kategorii',
'use_default_eula' => 'Použijte raději <a href="#" data-toggle="modal" data-target="#eulaModal">primární výchozí EULA</a>.',
'use_default_eula_disabled' => '<del>Použijte raději primární výchozí EULA.</del> Nenalezena primární výchozí EULA. Přidejte ji v Nastaveních prosím.',
'use_default_eula_column' => 'Use default EULA',
];

View file

@ -61,9 +61,12 @@ return array(
'label_logo' => 'Label Logo',
'label_logo_size' => 'Square logos look best - will be displayed in the top right of each asset label. ',
'laravel' => 'Verze Laravel',
'ldap_client_tls_cert' => 'LDAP Client-Side TLS Certificate',
'ldap_enabled' => 'LDAP povoleno',
'ldap_integration' => 'LDAP integrace',
'ldap_settings' => 'Nastavení LDAP',
'ldap_client_tls_cert_help' => 'Client-Side TLS Certificate and Key for LDAP connections are usually only useful in Google Workspace configurations with "Secure LDAP." Both are required.',
'ldap_client_tls_key' => 'LDAP Client-Side TLS key',
'ldap_login_test_help' => 'Zadejte platné LDAP uživatelské jméno a heslo ze základu rozlišeného názvu který jste určili výše a vyzkoušejte zda je LDAP přihlašování správně nastavené. NEJPRVE JE TŘEBA ULOŽIT ZMĚNĚNÉ NASTAVENÍ LDAP.',
'ldap_login_sync_help' => 'Otestujte, že LDAP může správně synchronizovat. Pokud ověřovací LDAP dotaz není správný, uživatelé se nemusí být schopni přihlásit. JE NUTNÉ NEJPRVE NEJDŘÍVE ULOŽIT NASTAVENÍ LDAP POKUD BYLO ZMĚNĚNO.',
'ldap_server' => 'LDAP server',

View file

@ -13,6 +13,7 @@ return [
'user_deleted_warning' => 'Tento uživatel byl smazán. Budete muset uživatele obnovit, aby jste ho mohli upravil nebo přidělil nové majetky.',
'ldap_not_configured' => 'Integrace LDAP nebyla pro tuto instalaci nakonfigurována.',
'password_resets_sent' => 'The selected users who are activated and have a valid email addresses have been sent a password reset link.',
'password_reset_sent' => 'A password reset link has been sent to :email!',
'success' => [
'create' => 'Uživatel byl úspěšně vytvořen.',

View file

@ -1,6 +1,6 @@
<?php
return [
return array(
'actions' => 'Akce',
'add' => 'Přidej nový',
'cancel' => 'Zrušit',
@ -11,7 +11,8 @@ return [
'request' => 'Požadavek',
'submit' => 'Odeslat',
'upload' => 'Nahrát',
'select_file' => 'Vybrat soubor...',
'select_file' => 'Vybrat soubor...',
'select_files' => 'Vybrat soubory…',
'generate_labels' => '{1} Generate Label|[2,*] Generate Labels',
];
'send_password_link' => 'Send Password Reset Link',
);

View file

@ -18,5 +18,6 @@ return [
'update' => 'Diweddaru Categori',
'use_default_eula' => 'Defnyddio\'r <a href="#" data-toggle="modal" data-target="#eulaModal">prif CTDT diofyn</a> yn lle.',
'use_default_eula_disabled' => '<del>Defnyddio\'r CTDT diofyn yn lle\'r un presennol.</del>Nid oes prif CTDT diofyn wedi gosod. Ychwanegwch yn ynj gosodiadau os gwelwch yn dda.',
'use_default_eula_column' => 'Use default EULA',
];

Some files were not shown because too many files have changed in this diff Show more