Compare commits
457 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 1abd669de5 | |||
| ac9df2fc08 | |||
| eba24b9242 | |||
| edd61705dc | |||
| 3f20e29901 | |||
| 36ae162626 | |||
| 00f7cb9dbb | |||
| 1ca3dc26eb | |||
| 2f3be267b3 | |||
| 5b8f6910fb | |||
| 9fe26ba814 | |||
| 5e97ed1c7e | |||
| 947fb7af7a | |||
| 44bcc157e5 | |||
| 278bf3da13 | |||
| 446bc81d3a | |||
| 9527aac242 | |||
| c57f1f9d7d | |||
| e372527d13 | |||
| 96be1e1275 | |||
| 8ce17d0585 | |||
| 6af1eaa4e4 | |||
| da01487301 | |||
| 708d7b5fc5 | |||
| 62b5a159a9 | |||
| a6d04509a5 | |||
| 0071596274 | |||
| 59f66051f8 | |||
| 9f1e59cf78 | |||
| f1f68b8ef6 | |||
| f22c3cdda9 | |||
| 5e15cc3bbe | |||
| a6690493b0 | |||
| 17a6335d13 | |||
| ca57f6de85 | |||
| aefaabdb1a | |||
| 9211c8d3b1 | |||
| eff1980df5 | |||
| 1553ba5630 | |||
| ec24120d2a | |||
| 50df750202 | |||
| dab4aced48 | |||
| 1774952312 | |||
| d66d6e70a6 | |||
| 4635e9269d | |||
| 574867536d | |||
| 5488a4d118 | |||
| e34f3c7c2c | |||
| ceaff7b645 | |||
| d27a025347 | |||
| 2b2853a183 | |||
| a25263f868 | |||
| 4b9727067b | |||
| 00fc392a12 | |||
| 1da90fe1ec | |||
| 25ba50d6f7 | |||
| f22e99aec8 | |||
| f027fd5f21 | |||
| 37a038c24f | |||
| 3a8f825de5 | |||
| d2df83cf2f | |||
| d481850d4c | |||
| 6c55e2bd9d | |||
| 2fd357c346 | |||
| 0a5e58201a | |||
| d687b20467 | |||
| 7dbcedad40 | |||
| b6e8d28ed3 | |||
| 85ce47f5bb | |||
| 55c98cc27a | |||
| 422f3ec81e | |||
| 54fb91c03b | |||
| 6df9742664 | |||
| f23a221750 | |||
| 4637accb51 | |||
| 74f067d893 | |||
| 43773954cd | |||
| 30cafef9f2 | |||
| 251f2d82b3 | |||
| e905550778 | |||
| adee99db34 | |||
| eda2eb2283 | |||
| a7123a04ba | |||
| 8a562f1d15 | |||
| d4861a74df | |||
| 8971cc4b8b | |||
| bca6dd41d2 | |||
| 221c4eeb0c | |||
| bbb1fbfbe8 | |||
| 5a874a90ac | |||
| 1c14c2fdef | |||
| 73a038afd4 | |||
| 4d55765e28 | |||
| 2b43f3cb84 | |||
| 52c4885335 | |||
| aa5fe52e89 | |||
| ce107dd688 | |||
| 72affd7a5b | |||
| ba4c51dd68 | |||
| 294fb1f774 | |||
| a846afe733 | |||
| 5fb3cea0bb | |||
| 4ae89c23cd | |||
| 3d32fe662b | |||
| 468674a517 | |||
| ebe4354a85 | |||
| f47bc5ea7d | |||
| 427615f627 | |||
| 829b560794 | |||
| f97a15c5c3 | |||
| 25fcf523e3 | |||
| c1be94c4ad | |||
| 3a05d72124 | |||
| 7ec44e46ce | |||
| 060b17df01 | |||
| 74c78d7577 | |||
| 1ef0c1adac | |||
| c2e649e2bf | |||
| 196db9718e | |||
| 9f5b264e04 | |||
| 3825f5fb61 | |||
| e60dbc883c | |||
| bbbfa91db9 | |||
| 5ec8e2da66 | |||
| 9e59bd5687 | |||
| 1d26ccac4e | |||
| 0e2526f627 | |||
| dd9e9c7a6d | |||
| e19922abd0 | |||
| d27bde6047 | |||
| 61f76dedc6 | |||
| 06737f45ad | |||
| 65e8765bdd | |||
| c6a0212384 | |||
| e03614d91b | |||
| b82770d0a8 | |||
| 55e1326164 | |||
| b0aff68c8b | |||
| 6a99855c8c | |||
| 665aa6eb23 | |||
| 42caacbaf9 | |||
| 3531256c3f | |||
| 9a0db72eb4 | |||
| e11a42cf68 | |||
| 114769c2d9 | |||
| 9594596b8a | |||
| 69cf697aa3 | |||
| 45dbe5cb77 | |||
| a1ff35f6ce | |||
| 077a6949e2 | |||
| 44022f07ca | |||
| 30c1e1e86a | |||
| 9a90813877 | |||
| 1113218c6c | |||
| 2556c80250 | |||
| 8f8a5c639b | |||
| 9e9c37c1e8 | |||
| 6cbdbcb1f1 | |||
| c8835bf5db | |||
| 6dfedac7a7 | |||
| 83794eaf33 | |||
| bd1f43f9ee | |||
| 66ffe21ce2 | |||
| f2e86b7d30 | |||
| 5251e6787d | |||
| 856aee0a72 | |||
| 6b4c71f966 | |||
| dd6d040da5 | |||
| 203b60383f | |||
| 61ced0b221 | |||
| ae7675fee0 | |||
| 66ed26fbf9 | |||
| 98662c2a77 | |||
| 7099358985 | |||
| 9a706b3e3e | |||
| 71c9b03779 | |||
| dc7b9315b5 | |||
| 6c17b141db | |||
| 5d2cca855e | |||
| 61e10be04d | |||
| 20d5587851 | |||
| d8eccf03f1 | |||
| 6e40b58dc5 | |||
| 30dd8bcf2b | |||
| f0a11be0b8 | |||
| b8882fa00e | |||
| af337b7018 | |||
| f60267d208 | |||
| a0c844f4f6 | |||
| 7b84b92e72 | |||
| ce338c632d | |||
| d9f70c16f7 | |||
| d0299de898 | |||
| 9380c9ec81 | |||
| 941582ac2a | |||
| 04560b4475 | |||
| 0b30ad0da2 | |||
| cb6ea2c6fb | |||
| 89a5bbb10e | |||
| 2f59bb74cd | |||
| 6c6a3649ea | |||
| 05b97db747 | |||
| 543e4c0666 | |||
| e28619f769 | |||
| 4d8c2d3f4e | |||
| f53eeb8b33 | |||
| aba6d9b338 | |||
| cd5bef414c | |||
| 4f2d2ae4b8 | |||
| 1bd0ab7389 | |||
| 8799276c6e | |||
| 672aabf4ac | |||
| 796d6909d5 | |||
| a3dea99bbb | |||
| fc351a1896 | |||
| d9164281ab | |||
| cbb5b6e846 | |||
| 08bd39dbba | |||
| 430808e180 | |||
| 6976dc2b26 | |||
| 27063d5bae | |||
| 5be86b9dbb | |||
| afc78524fc | |||
| eb33a2451f | |||
| 891a0a0965 | |||
| 50f0797850 | |||
| 36cdf0e0be | |||
| d9cc3c3ec7 | |||
| 069a1608de | |||
| 60accfd601 | |||
| b1f2051b43 | |||
| 233e4af7f8 | |||
| dc1b808a28 | |||
| 91a423e60e | |||
| bd03a6d206 | |||
| d87da78eb5 | |||
| f3e82c2c80 | |||
| 569f05a99e | |||
| ece7c22df9 | |||
| 4eefd39172 | |||
| daae5d6859 | |||
| df76769a29 | |||
| fe72639925 | |||
| c3e6e1144f | |||
| cacb5d62dc | |||
| a8b47a55bc | |||
| 3159fdec9f | |||
| ea990a5381 | |||
| 134183ef16 | |||
| 67ab2536bc | |||
| 756a2ac25c | |||
| acaceb4103 | |||
| 7e3d66ec53 | |||
| 1ca9bb5aa8 | |||
| c641b733e1 | |||
| 16cf6bc852 | |||
| c51b7d7104 | |||
| 5c0ca92fd7 | |||
| 241e9bc253 | |||
| c8820adb56 | |||
| 0f4c6dd5b0 | |||
| f8ab9f62f6 | |||
| 217ed03b8e | |||
| 77e6058e4c | |||
| 4a60026162 | |||
| 3621292a0e | |||
| 6c296ccf8e | |||
| 6df1c36011 | |||
| 924da00f3e | |||
| 44dae22a3c | |||
| d35e251d6e | |||
| 9044aa4ed9 | |||
| 60c7efae3c | |||
| 48fc6ca60e | |||
| 7ac315e1eb | |||
| 374c6845d6 | |||
| c5cbe37007 | |||
| a2346e4666 | |||
| 2479ccc4c6 | |||
| 64dd8f5d65 | |||
| 47420a802a | |||
| 5cdb2b7163 | |||
| d4c080c7e4 | |||
| 065a47a446 | |||
| 5bd9ecb8df | |||
| 1cdec61be6 | |||
| b0ddb26e73 | |||
| 181bafd012 | |||
| e054fc1ef1 | |||
| 9d9ad86dd5 | |||
| afe4e5d62e | |||
| 52950f1322 | |||
| 026c80992e | |||
| 0ee2b74ff3 | |||
| 3a0f7eca54 | |||
| f4d530b4b1 | |||
| 4ccbfb56a4 | |||
| d02904c9a3 | |||
| c8279c0b99 | |||
| f4f184e115 | |||
| b2a86e312b | |||
| 9d56617caf | |||
| 09e94ec176 | |||
| 832ceeba56 | |||
| 9fccafa3ac | |||
| b2a0e7958b | |||
| 99439f0a5c | |||
| ef91c8123e | |||
| 5eb5742b3d | |||
| 296cf3e34b | |||
| e827bc9a07 | |||
| 8f4ede7785 | |||
| 877adb082c | |||
| 90818bb147 | |||
| 32c367090b | |||
| abcfe2b757 | |||
| f7687008b7 | |||
| b156264684 | |||
| 3f9a80942e | |||
| dc62e393c3 | |||
| 801e58d52e | |||
| 06e9625c64 | |||
| 5800e8d8e9 | |||
| 623aa58163 | |||
| 5a9a231359 | |||
| 1736bf5510 | |||
| 2eaac3d381 | |||
| f03249898a | |||
| e80b80f5d1 | |||
| 9e35441281 | |||
| e28ad50bec | |||
| f48c5ee252 | |||
| 98a94dec29 | |||
| 7d95e7765d | |||
| ee75b30683 | |||
| ca9d4e3155 | |||
| 633bcbb6c4 | |||
| 2d4af61e6c | |||
| 45329912e6 | |||
| b9d56a8ecc | |||
| 91c1e53e52 | |||
| 73a87a8ea8 | |||
| bb0a614c39 | |||
| f11ea79406 | |||
| e817b20840 | |||
| 516f766a44 | |||
| f5791c79a5 | |||
| f6a1a76095 | |||
| bbb9145744 | |||
| 194853d860 | |||
| 92670d5711 | |||
| 8a2ea971e1 | |||
| 8d924b60d7 | |||
| 34595c266d | |||
| 638ae9bdd5 | |||
| 713ce7836f | |||
| 093c6652a8 | |||
| 17f0ac1eae | |||
| 43616d1874 | |||
| 9dc4f2ca80 | |||
| 73e3ac7dd8 | |||
| 8ff639913d | |||
| 45419586fe | |||
| d8a480b2a8 | |||
| 29d87246a2 | |||
| 58e638d3cb | |||
| b52380f376 | |||
| 4ae74fb7f6 | |||
| 7d1acd3d79 | |||
| fceba13b03 | |||
| 8ac3937bf4 | |||
| 1c1729854e | |||
| 14c78d9065 | |||
| b1cb9259da | |||
| 702b944698 | |||
| fd42f1ef24 | |||
| 986d5641f6 | |||
| dce1854ac4 | |||
| c20d10d4f2 | |||
| b489c71fa2 | |||
| cf5f6f9b13 | |||
| 860432acc5 | |||
| cc0f2d7074 | |||
| 0d4f13219b | |||
| f2cc9ec1dd | |||
| 7743b03129 | |||
| d691f3b315 | |||
| 2539c9e697 | |||
| 3dfd471fa4 | |||
| 1b85eea28e | |||
| 4459483862 | |||
| a0cf7ecc98 | |||
| 6823aabf92 | |||
| 4642f50d6b | |||
| c8fbf7640c | |||
| 6f40b21986 | |||
| 204de99a64 | |||
| d36a06d8e1 | |||
| 4913e56086 | |||
| db2baae758 | |||
| d146426dd8 | |||
| 1e1782c232 | |||
| 56cb9a0f4e | |||
| 5229dd65ce | |||
| 7f38ca239e | |||
| a6a58094c9 | |||
| fce98b9ca4 | |||
| 954cac3af7 | |||
| 802b5863ab | |||
| 72c91ead8b | |||
| 4f10adfb76 | |||
| d44202e55b | |||
| b7af049589 | |||
| 6f9ba6ede4 | |||
| d60fa65f85 | |||
| b2eea3e5a5 | |||
| 3ea0cd75a5 | |||
| 6dd6b45829 | |||
| 3f5b94f8ad | |||
| 3bb81d1e4d | |||
| 89d733d442 | |||
| 0611ab9b4c | |||
| 7060ffaf34 | |||
| b34156ca25 | |||
| b41b4b1732 | |||
| 53aabdab66 | |||
| bd42505799 | |||
| a6a0bfacc2 | |||
| b4e647dbd1 | |||
| 0f11963127 | |||
| 3391108551 | |||
| ea4ecaea03 | |||
| 814914924f | |||
| 7070bad53b | |||
| f56d53d7c1 | |||
| 6a5098fb0c | |||
| 8bb8eab69b | |||
| a53a8cca74 | |||
| 9d8ce872a4 | |||
| 027361f079 | |||
| 0f63fa23e0 | |||
| bda6fdf09c | |||
| a62198f33f | |||
| 78868813b1 | |||
| 9ae779e442 | |||
| ea2d54b0f7 | |||
| 55c237913c | |||
| 313b327cd7 | |||
| 855d922a3e | |||
| 21ad7f549d | |||
| 485d40c752 | |||
| 109c0f202a | |||
| 6156d67e4a | |||
| bd566324ed | |||
| 939e4cba3e | |||
| 015a8763a0 | |||
| 7b0a3fc6d3 |
+11
-1
@@ -3115,7 +3115,8 @@
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/23613427?v=4",
|
||||
"profile": "https://github.com/bryanlopezinc",
|
||||
"contributions": [
|
||||
"code"
|
||||
"code",
|
||||
"test"
|
||||
]
|
||||
},
|
||||
{
|
||||
@@ -3126,6 +3127,15 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Tyree",
|
||||
"name": "Matt Tyree",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/5395363?v=4",
|
||||
"profile": "https://github.com/Tyree",
|
||||
"contributions": [
|
||||
"doc"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+166
@@ -0,0 +1,166 @@
|
||||
# --------------------------------------------
|
||||
# REQUIRED: DB SETUP
|
||||
# --------------------------------------------
|
||||
MYSQL_DATABASE=snipeit
|
||||
MYSQL_USER=snipeit
|
||||
MYSQL_PASSWORD=changeme1234
|
||||
MYSQL_ROOT_PASSWORD=changeme1234
|
||||
# --------------------------------------------
|
||||
# REQUIRED: BASIC APP SETTINGS
|
||||
# --------------------------------------------
|
||||
APP_ENV=develop
|
||||
APP_DEBUG=false
|
||||
# please regenerate the APP_KEY value by calling `docker-compose run --rm snipeit bash` and then `php artisan key:generate --show` and then copy paste the value here
|
||||
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
|
||||
APP_URL=http://localhost:8000
|
||||
APP_TIMEZONE='UTC'
|
||||
APP_LOCALE=en
|
||||
MAX_RESULTS=500
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: UPLOADED FILE STORAGE SETTINGS
|
||||
# --------------------------------------------
|
||||
PRIVATE_FILESYSTEM_DISK=local
|
||||
PUBLIC_FILESYSTEM_DISK=local_public
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: DATABASE SETTINGS
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=mariadb
|
||||
DB_DATABASE=snipeit
|
||||
DB_USERNAME=snipeit
|
||||
DB_PASSWORD=changeme1234
|
||||
DB_PREFIX=null
|
||||
DB_DUMP_PATH='/usr/bin'
|
||||
DB_CHARSET=utf8mb4
|
||||
DB_COLLATION=utf8mb4_unicode_ci
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SSL DATABASE SETTINGS
|
||||
# --------------------------------------------
|
||||
DB_SSL=false
|
||||
DB_SSL_IS_PAAS=false
|
||||
DB_SSL_KEY_PATH=null
|
||||
DB_SSL_CERT_PATH=null
|
||||
DB_SSL_CA_PATH=null
|
||||
DB_SSL_CIPHER=null
|
||||
DB_SSL_VERIFY_SERVER=null
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: OUTGOING MAIL SERVER SETTINGS
|
||||
# --------------------------------------------
|
||||
MAIL_DRIVER=smtp
|
||||
MAIL_HOST=mailhog
|
||||
MAIL_PORT=1025
|
||||
MAIL_USERNAME=null
|
||||
MAIL_PASSWORD=null
|
||||
MAIL_ENCRYPTION=null
|
||||
MAIL_FROM_ADDR=you@example.com
|
||||
MAIL_FROM_NAME='Snipe-IT'
|
||||
MAIL_REPLYTO_ADDR=you@example.com
|
||||
MAIL_REPLYTO_NAME='Snipe-IT'
|
||||
MAIL_AUTO_EMBED_METHOD='attachment'
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: IMAGE LIBRARY
|
||||
# This should be gd or imagick
|
||||
# --------------------------------------------
|
||||
IMAGE_LIB=gd
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: BACKUP SETTINGS
|
||||
# --------------------------------------------
|
||||
MAIL_BACKUP_NOTIFICATION_DRIVER=null
|
||||
MAIL_BACKUP_NOTIFICATION_ADDRESS=null
|
||||
BACKUP_ENV=true
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SESSION SETTINGS
|
||||
# --------------------------------------------
|
||||
SESSION_LIFETIME=12000
|
||||
EXPIRE_ON_CLOSE=false
|
||||
ENCRYPT=false
|
||||
COOKIE_NAME=snipeit_session
|
||||
COOKIE_DOMAIN=null
|
||||
SECURE_COOKIES=false
|
||||
API_TOKEN_EXPIRATION_YEARS=40
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SECURITY HEADER SETTINGS
|
||||
# --------------------------------------------
|
||||
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
|
||||
ALLOW_IFRAMING=false
|
||||
REFERRER_POLICY=same-origin
|
||||
ENABLE_CSP=false
|
||||
CORS_ALLOWED_ORIGINS=null
|
||||
ENABLE_HSTS=false
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: CACHE SETTINGS
|
||||
# --------------------------------------------
|
||||
CACHE_DRIVER=file
|
||||
SESSION_DRIVER=file
|
||||
QUEUE_DRIVER=sync
|
||||
CACHE_PREFIX=snipeit
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: REDIS SETTINGS
|
||||
# --------------------------------------------
|
||||
REDIS_HOST=redis
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: MEMCACHED SETTINGS
|
||||
# --------------------------------------------
|
||||
MEMCACHED_HOST=null
|
||||
MEMCACHED_PORT=null
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: PUBLIC S3 Settings
|
||||
# --------------------------------------------
|
||||
PUBLIC_AWS_SECRET_ACCESS_KEY=null
|
||||
PUBLIC_AWS_ACCESS_KEY_ID=null
|
||||
PUBLIC_AWS_DEFAULT_REGION=null
|
||||
PUBLIC_AWS_BUCKET=null
|
||||
PUBLIC_AWS_URL=null
|
||||
PUBLIC_AWS_BUCKET_ROOT=null
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: PRIVATE S3 Settings
|
||||
# --------------------------------------------
|
||||
PRIVATE_AWS_ACCESS_KEY_ID=null
|
||||
PRIVATE_AWS_SECRET_ACCESS_KEY=null
|
||||
PRIVATE_AWS_DEFAULT_REGION=null
|
||||
PRIVATE_AWS_BUCKET=null
|
||||
PRIVATE_AWS_URL=null
|
||||
PRIVATE_AWS_BUCKET_ROOT=null
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: AWS Settings
|
||||
# --------------------------------------------
|
||||
AWS_ACCESS_KEY_ID=null
|
||||
AWS_SECRET_ACCESS_KEY=null
|
||||
AWS_DEFAULT_REGION=null
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: LOGIN THROTTLING
|
||||
# --------------------------------------------
|
||||
LOGIN_MAX_ATTEMPTS=5
|
||||
LOGIN_LOCKOUT_DURATION=60
|
||||
RESET_PASSWORD_LINK_EXPIRES=900
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: MISC
|
||||
# --------------------------------------------
|
||||
LOG_CHANNEL=stderr
|
||||
LOG_MAX_DAYS=10
|
||||
APP_LOCKED=false
|
||||
APP_CIPHER=AES-256-CBC
|
||||
APP_FORCE_TLS=false
|
||||
GOOGLE_MAPS_API=
|
||||
LDAP_MEM_LIM=500M
|
||||
LDAP_TIME_LIM=600
|
||||
+18
-12
@@ -1,18 +1,18 @@
|
||||
# --------------------------------------------
|
||||
# REQUIRED: DB SETUP
|
||||
# REQUIRED: DOCKER SPECIFIC SETTINGS
|
||||
# --------------------------------------------
|
||||
MYSQL_DATABASE=snipeit
|
||||
MYSQL_USER=snipeit
|
||||
MYSQL_PASSWORD=changeme1234
|
||||
MYSQL_ROOT_PASSWORD=changeme1234
|
||||
APP_VERSION=v6.4.1
|
||||
APP_PORT=8000
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: BASIC APP SETTINGS
|
||||
# --------------------------------------------
|
||||
APP_ENV=develop
|
||||
APP_ENV=production
|
||||
APP_DEBUG=false
|
||||
# please regenerate the APP_KEY value by calling `docker-compose run --rm snipeit bash` and then `php artisan key:generate --show` and then copy paste the value here
|
||||
# Please regenerate the APP_KEY value by calling `docker compose run --rm snipeit php artisan key:generate --show`. Copy paste the value here
|
||||
APP_KEY=base64:3ilviXqB9u6DX1NRcyWGJ+sjySF+H18CPDGb3+IVwMQ=
|
||||
APP_URL=http://localhost:8000
|
||||
# https://en.wikipedia.org/wiki/List_of_tz_database_time_zones - TZ identifier
|
||||
APP_TIMEZONE='UTC'
|
||||
APP_LOCALE=en
|
||||
MAX_RESULTS=500
|
||||
@@ -27,10 +27,12 @@ PUBLIC_FILESYSTEM_DISK=local_public
|
||||
# REQUIRED: DATABASE SETTINGS
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=mariadb
|
||||
DB_HOST=db
|
||||
DB_PORT='3306'
|
||||
DB_DATABASE=snipeit
|
||||
DB_USERNAME=snipeit
|
||||
DB_PASSWORD=changeme1234
|
||||
MYSQL_ROOT_PASSWORD=changeme1234
|
||||
DB_PREFIX=null
|
||||
DB_DUMP_PATH='/usr/bin'
|
||||
DB_CHARSET=utf8mb4
|
||||
@@ -62,13 +64,18 @@ MAIL_REPLYTO_ADDR=you@example.com
|
||||
MAIL_REPLYTO_NAME='Snipe-IT'
|
||||
MAIL_AUTO_EMBED_METHOD='attachment'
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: DATA PROTECTION
|
||||
# --------------------------------------------
|
||||
ALLOW_BACKUP_DELETE=false
|
||||
ALLOW_DATA_PURGE=false
|
||||
|
||||
# --------------------------------------------
|
||||
# REQUIRED: IMAGE LIBRARY
|
||||
# This should be gd or imagick
|
||||
# --------------------------------------------
|
||||
IMAGE_LIB=gd
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: BACKUP SETTINGS
|
||||
# --------------------------------------------
|
||||
@@ -76,7 +83,6 @@ MAIL_BACKUP_NOTIFICATION_DRIVER=null
|
||||
MAIL_BACKUP_NOTIFICATION_ADDRESS=null
|
||||
BACKUP_ENV=true
|
||||
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SESSION SETTINGS
|
||||
# --------------------------------------------
|
||||
@@ -91,7 +97,7 @@ API_TOKEN_EXPIRATION_YEARS=40
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SECURITY HEADER SETTINGS
|
||||
# --------------------------------------------
|
||||
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1
|
||||
APP_TRUSTED_PROXIES=192.168.1.1,10.0.0.1,172.0.0.0/8
|
||||
ALLOW_IFRAMING=false
|
||||
REFERRER_POLICY=same-origin
|
||||
ENABLE_CSP=false
|
||||
@@ -109,7 +115,7 @@ CACHE_PREFIX=snipeit
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: REDIS SETTINGS
|
||||
# --------------------------------------------
|
||||
REDIS_HOST=redis
|
||||
REDIS_HOST=null
|
||||
REDIS_PASSWORD=null
|
||||
REDIS_PORT=6379
|
||||
|
||||
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push 'snipe-it' image
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile.alpine
|
||||
|
||||
@@ -73,7 +73,7 @@ jobs:
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push 'snipe-it' image
|
||||
id: docker_build
|
||||
uses: docker/build-push-action@v5
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
|
||||
@@ -27,6 +27,7 @@ jobs:
|
||||
php-version:
|
||||
- "8.1"
|
||||
- "8.2"
|
||||
- "8.3"
|
||||
|
||||
name: PHP ${{ matrix.php-version }}
|
||||
|
||||
|
||||
@@ -0,0 +1,75 @@
|
||||
name: Tests in Postgres
|
||||
|
||||
on: workflow_dispatch
|
||||
|
||||
jobs:
|
||||
tests:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
services:
|
||||
postgresql:
|
||||
image: postgres
|
||||
env:
|
||||
POSTGRES_DB: snipeit
|
||||
POSTGRES_USER: snipeit
|
||||
POSTGRES_PASSWORD: password
|
||||
ports:
|
||||
- 5432:5432
|
||||
options: --health-cmd=pg_isready --health-interval=10s --health-timeout=5s --health-retries=3
|
||||
|
||||
strategy:
|
||||
fail-fast: false
|
||||
matrix:
|
||||
php-version:
|
||||
- "8.2"
|
||||
|
||||
name: PHP ${{ matrix.php-version }}
|
||||
|
||||
steps:
|
||||
- uses: shivammathur/setup-php@v2
|
||||
with:
|
||||
php-version: "${{ matrix.php-version }}"
|
||||
coverage: none
|
||||
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: Get Composer Cache Directory
|
||||
id: composer-cache
|
||||
run: |
|
||||
echo "dir=$(composer config cache-files-dir)" >> $GITHUB_OUTPUT
|
||||
- uses: actions/cache@v4
|
||||
with:
|
||||
path: ${{ steps.composer-cache.outputs.dir }}
|
||||
key: ${{ runner.os }}-${{ matrix.php-version }}-composer-${{ hashFiles('**/composer.lock') }}
|
||||
restore-keys: |
|
||||
${{ runner.os }}-composer-
|
||||
|
||||
- name: Copy .env
|
||||
run: |
|
||||
cp -v .env.testing.example .env
|
||||
cp -v .env.testing.example .env.testing
|
||||
|
||||
- name: Install Dependencies
|
||||
run: composer install -q --no-ansi --no-interaction --no-scripts --no-progress --prefer-dist
|
||||
|
||||
- name: Setup Laravel
|
||||
env:
|
||||
DB_CONNECTION: pgsql
|
||||
DB_DATABASE: snipeit
|
||||
DB_PORT: ${{ job.services.postgresql.ports[5432] }}
|
||||
DB_USERNAME: snipeit
|
||||
DB_PASSWORD: password
|
||||
run: |
|
||||
php artisan key:generate
|
||||
php artisan migrate --force
|
||||
php artisan passport:install
|
||||
chmod -R 777 storage bootstrap/cache
|
||||
|
||||
- name: Execute tests (Unit and Feature tests) via PHPUnit
|
||||
env:
|
||||
DB_CONNECTION: pgsql
|
||||
DB_DATABASE: snipeit
|
||||
DB_PORT: ${{ job.services.postgresql.ports[5432] }}
|
||||
DB_USERNAME: snipeit
|
||||
DB_PASSWORD: password
|
||||
run: php artisan test --parallel
|
||||
@@ -4,7 +4,7 @@
|
||||
"DOC3": "Please don't rely on these versions for planning upgrades unless you've fetched the most recent version",
|
||||
"DOC4": "You should really just ignore it and run upgrade.php. Really",
|
||||
"php_min_version": "8.1.0",
|
||||
"php_max_major_minor": "8.2",
|
||||
"php_max_wontwork": "8.3.0",
|
||||
"php_max_major_minor": "8.3",
|
||||
"php_max_wontwork": "8.4.0",
|
||||
"current_snipeit_version": "7.0"
|
||||
}
|
||||
|
||||
+2
-1
@@ -444,10 +444,11 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://www.corelight.com/"><img src="https://avatars.githubusercontent.com/u/1496725?v=4?s=110" width="110px;" alt="i_virus"/><br /><sub><b>i_virus</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=chandanchowdhury" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/gitgrimbo"><img src="https://avatars.githubusercontent.com/u/1020541?v=4?s=110" width="110px;" alt="Paul Grime"/><br /><sub><b>Paul Grime</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=gitgrimbo" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://leeporte.co.uk"><img src="https://avatars.githubusercontent.com/u/922815?v=4?s=110" width="110px;" alt="Lee Porte"/><br /><sub><b>Lee Porte</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=LeePorte" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bryanlopezinc"><img src="https://avatars.githubusercontent.com/u/23613427?v=4?s=110" width="110px;" alt="BRYAN "/><br /><sub><b>BRYAN </b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=bryanlopezinc" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/bryanlopezinc"><img src="https://avatars.githubusercontent.com/u/23613427?v=4?s=110" width="110px;" alt="BRYAN "/><br /><sub><b>BRYAN </b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=bryanlopezinc" title="Code">💻</a> <a href="https://github.com/snipe/snipe-it/commits?author=bryanlopezinc" title="Tests">⚠️</a></td>
|
||||
</tr>
|
||||
<tr>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/U-H-T"><img src="https://avatars.githubusercontent.com/u/64061710?v=4?s=110" width="110px;" alt="U-H-T"/><br /><sub><b>U-H-T</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=U-H-T" title="Code">💻</a></td>
|
||||
<td align="center" valign="top" width="14.28%"><a href="https://github.com/Tyree"><img src="https://avatars.githubusercontent.com/u/5395363?v=4?s=110" width="110px;" alt="Matt Tyree"/><br /><sub><b>Matt Tyree</b></sub></a><br /><a href="https://github.com/snipe/snipe-it/commits?author=Tyree" title="Documentation">📖</a></td>
|
||||
</tr>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Console\Commands;
|
||||
|
||||
use App\Events\UserMerged;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Console\Command;
|
||||
@@ -51,7 +52,7 @@ class MergeUsersByUsername extends Command
|
||||
|
||||
$bad_users = User::where('username', '=', trim($parts[0]))
|
||||
->whereNull('deleted_at')
|
||||
->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations')
|
||||
->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations','uploads', 'acceptances')
|
||||
->get();
|
||||
|
||||
|
||||
@@ -105,10 +106,26 @@ class MergeUsersByUsername extends Command
|
||||
$managedLocation->save();
|
||||
}
|
||||
|
||||
foreach ($bad_user->uploads as $upload) {
|
||||
$this->info('Updating upload log record '.$upload->id.' to user '.$user->id);
|
||||
$upload->item_id = $user->id;
|
||||
$upload->save();
|
||||
}
|
||||
|
||||
foreach ($bad_user->acceptances as $acceptance) {
|
||||
$this->info('Updating acceptance log record '.$acceptance->id.' to user '.$user->id);
|
||||
$acceptance->item_id = $user->id;
|
||||
$acceptance->save();
|
||||
}
|
||||
|
||||
// Mark the user as deleted
|
||||
$this->info('Marking the user as deleted');
|
||||
$bad_user->deleted_at = Carbon::now()->timestamp;
|
||||
$bad_user->save();
|
||||
|
||||
event(new UserMerged($bad_user, $user, null));
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@ class UserMerged
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct(User $from_user, User $to_user, User $admin)
|
||||
public function __construct(User $from_user, User $to_user, ?User $admin)
|
||||
{
|
||||
$this->merged_from = $from_user;
|
||||
$this->merged_to = $to_user;
|
||||
|
||||
@@ -17,22 +17,24 @@ class ActionlogController extends Controller
|
||||
|
||||
$disk = config('filesystems.default');
|
||||
switch (config("filesystems.disks.$disk.driver")) {
|
||||
case 's3':
|
||||
$file = 'private_uploads/signatures/'.$filename;
|
||||
return redirect()->away(Storage::disk($disk)->temporaryUrl($file, now()->addMinutes(5)));
|
||||
default:
|
||||
$this->authorize('view', \App\Models\Asset::class);
|
||||
$file = config('app.private_uploads').'/signatures/'.$filename;
|
||||
$filetype = Helper::checkUploadIsImage($file);
|
||||
case 's3':
|
||||
$file = 'private_uploads/signatures/'.$filename;
|
||||
return redirect()->away(Storage::disk($disk)->temporaryUrl($file, now()->addMinutes(5)));
|
||||
default:
|
||||
$this->authorize('view', \App\Models\Asset::class);
|
||||
$file = config('app.private_uploads').'/signatures/'.$filename;
|
||||
$filetype = Helper::checkUploadIsImage($file);
|
||||
|
||||
$contents = file_get_contents($file, false, stream_context_create(['http' => ['ignore_errors' => true]]));
|
||||
if ($contents === false) {
|
||||
Log::warning('File '.$file.' not found');
|
||||
return false;
|
||||
} else {
|
||||
return Response::make($contents)->header('Content-Type', $filetype);
|
||||
}
|
||||
$contents = file_get_contents($file, false, stream_context_create(['http' => ['ignore_errors' => true]]));
|
||||
if ($contents === false) {
|
||||
Log::warning('File '.$file.' not found');
|
||||
return false;
|
||||
} else {
|
||||
return Response::make($contents)->header('Content-Type', $filetype);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public function getStoredEula($filename){
|
||||
$this->authorize('view', \App\Models\Asset::class);
|
||||
$file = config('app.private_uploads').'/eula-pdfs/'.$filename;
|
||||
|
||||
@@ -0,0 +1,219 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Api;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Http\JsonResponse;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Models\Asset;
|
||||
use App\Models\AssetModel;
|
||||
use App\Models\Actionlog;
|
||||
use \Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
use DB;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\UploadFileRequest;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Input;
|
||||
use Paginator;
|
||||
use Slack;
|
||||
use Str;
|
||||
use TCPDF;
|
||||
use Validator;
|
||||
use Route;
|
||||
|
||||
|
||||
/**
|
||||
* This class controls file related actions related
|
||||
* to assets for the Snipe-IT Asset Management application.
|
||||
*
|
||||
* Based on the Assets/AssetFilesController by A. Gianotto <snipe@snipe.net>
|
||||
*
|
||||
* @version v1.0
|
||||
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
|
||||
*/
|
||||
class AssetFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Accepts a POST to upload a file to the server.
|
||||
*
|
||||
* @param \App\Http\Requests\UploadFileRequest $request
|
||||
* @param int $assetId
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v6.0]
|
||||
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
|
||||
*/
|
||||
public function store(UploadFileRequest $request, $assetId = null)
|
||||
{
|
||||
// Start by checking if the asset being acted upon exists
|
||||
if (! $asset = Asset::find($assetId)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
|
||||
}
|
||||
|
||||
// Make sure we are allowed to update this asset
|
||||
$this->authorize('update', $asset);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
// If the file storage directory doesn't exist; create it
|
||||
if (! Storage::exists('private_uploads/assets')) {
|
||||
Storage::makeDirectory('private_uploads/assets', 775);
|
||||
}
|
||||
|
||||
// Loop over the attached files and add them to the asset
|
||||
foreach ($request->file('file') as $file) {
|
||||
$file_name = $request->handleFile('private_uploads/assets/','hardware-'.$asset->id, $file);
|
||||
|
||||
$asset->logUpload($file_name, e($request->get('notes')));
|
||||
}
|
||||
|
||||
// All done - report success
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $asset, trans('admin/hardware/message.upload.success')));
|
||||
}
|
||||
|
||||
// We only reach here if no files were included in the POST, so tell the user this
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.upload.nofiles')), 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* List the files for an asset.
|
||||
*
|
||||
* @param int $assetId
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v6.0]
|
||||
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
|
||||
*/
|
||||
public function list($assetId = null)
|
||||
{
|
||||
// Start by checking if the asset being acted upon exists
|
||||
if (! $asset = Asset::find($assetId)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
|
||||
}
|
||||
|
||||
// the asset is valid
|
||||
if (isset($asset->id)) {
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
// Check that there are some uploads on this asset that can be listed
|
||||
if ($asset->uploads->count() > 0) {
|
||||
$files = array();
|
||||
foreach ($asset->uploads as $upload) {
|
||||
array_push($files, $upload);
|
||||
}
|
||||
// Give the list of files back to the user
|
||||
return response()->json(Helper::formatStandardApiResponse('success', $files, trans('admin/hardware/message.upload.success')));
|
||||
}
|
||||
|
||||
// There are no files.
|
||||
return response()->json(Helper::formatStandardApiResponse('success', array(), trans('admin/hardware/message.upload.success')));
|
||||
}
|
||||
|
||||
// Send back an error message
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.error')), 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Check for permissions and display the file.
|
||||
*
|
||||
* @param int $assetId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v6.0]
|
||||
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
|
||||
*/
|
||||
public function show($assetId = null, $fileId = null)
|
||||
{
|
||||
// Start by checking if the asset being acted upon exists
|
||||
if (! $asset = Asset::find($assetId)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
|
||||
}
|
||||
|
||||
// the asset is valid
|
||||
if (isset($asset->id)) {
|
||||
$this->authorize('view', $asset);
|
||||
|
||||
// Check that the file being requested exists for the asset
|
||||
if (! $log = Actionlog::whereNotNull('filename')->where('item_id', $asset->id)->find($fileId)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.no_match', ['id' => $fileId])), 404);
|
||||
}
|
||||
|
||||
// Form the full filename with path
|
||||
$file = 'private_uploads/assets/'.$log->filename;
|
||||
\Log::debug('Checking for '.$file);
|
||||
|
||||
if ($log->action_type == 'audit') {
|
||||
$file = 'private_uploads/audits/'.$log->filename;
|
||||
}
|
||||
|
||||
// Check the file actually exists on the filesystem
|
||||
if (! Storage::exists($file)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.does_not_exist', ['id' => $fileId])), 404);
|
||||
}
|
||||
|
||||
if (request('inline') == 'true') {
|
||||
|
||||
$headers = [
|
||||
'Content-Disposition' => 'inline',
|
||||
];
|
||||
|
||||
return Storage::download($file, $log->filename, $headers);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
}
|
||||
|
||||
// Send back an error message
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.download.error', ['id' => $fileId])), 500);
|
||||
}
|
||||
|
||||
/**
|
||||
* Delete the associated file
|
||||
*
|
||||
* @param int $assetId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
* @since [v6.0]
|
||||
* @author [T. Scarsbrook] [<snipe@scarzybrook.co.uk>]
|
||||
*/
|
||||
public function destroy($assetId = null, $fileId = null)
|
||||
{
|
||||
// Start by checking if the asset being acted upon exists
|
||||
if (! $asset = Asset::find($assetId)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 404);
|
||||
}
|
||||
|
||||
$rel_path = 'private_uploads/assets';
|
||||
|
||||
// the asset is valid
|
||||
if (isset($asset->id)) {
|
||||
$this->authorize('update', $asset);
|
||||
|
||||
// Check for the file
|
||||
$log = Actionlog::find($fileId);
|
||||
if ($log) {
|
||||
// Check the file actually exists, and delete it
|
||||
if (Storage::exists($rel_path.'/'.$log->filename)) {
|
||||
Storage::delete($rel_path.'/'.$log->filename);
|
||||
}
|
||||
// Delete the record of the file
|
||||
$log->delete();
|
||||
|
||||
// All deleting done - notify the user of success
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/hardware/message.deletefile.success')), 200);
|
||||
}
|
||||
|
||||
// The file doesn't seem to really exist, so report an error
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.deletefile.error')), 500);
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.deletefile.error')), 500);
|
||||
}
|
||||
}
|
||||
@@ -585,49 +585,8 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
$asset = $asset->handleCustomFieldsForStoring($request);
|
||||
|
||||
// Update custom fields in the database.
|
||||
$model = AssetModel::find($request->input('model_id'));
|
||||
|
||||
// Check that it's an object and not a collection
|
||||
// (Sometimes people send arrays here and they shouldn't
|
||||
if (($model) && ($model instanceof AssetModel) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
|
||||
// Set the field value based on what was sent in the request
|
||||
$field_val = $request->input($field->db_column, null);
|
||||
|
||||
// If input value is null, use custom field's default value
|
||||
if ($field_val == null) {
|
||||
Log::debug('Field value for '.$field->db_column.' is null');
|
||||
$field_val = $field->defaultValue($request->get('model_id'));
|
||||
Log::debug('Use the default fieldset value of '.$field->defaultValue($request->get('model_id')));
|
||||
}
|
||||
|
||||
// if the field is set to encrypted, make sure we encrypt the value
|
||||
if ($field->field_encrypted == '1') {
|
||||
Log::debug('This model field is encrypted in this fieldset.');
|
||||
|
||||
if (Gate::allows('admin')) {
|
||||
|
||||
// If input value is null, use custom field's default value
|
||||
if (($field_val == null) && ($request->has('model_id') != '')) {
|
||||
$field_val = Crypt::encrypt($field->defaultValue($request->get('model_id')));
|
||||
} else {
|
||||
$field_val = Crypt::encrypt($request->input($field->db_column));
|
||||
}
|
||||
}
|
||||
}
|
||||
if ($field->element == 'checkbox') {
|
||||
if(is_array($field_val)) {
|
||||
$field_val = implode(',', $field_val);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$asset->{$field->db_column} = $field_val;
|
||||
}
|
||||
}
|
||||
|
||||
if ($asset->save()) {
|
||||
if ($request->get('assigned_user')) {
|
||||
@@ -688,32 +647,7 @@ class AssetsController extends Controller
|
||||
}
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
$model = AssetModel::find($asset->model_id);
|
||||
|
||||
// Update custom fields
|
||||
$problems_updating_encrypted_custom_fields = false;
|
||||
if (($model) && (isset($model->fieldset))) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
$field_val = $request->input($field->db_column, null);
|
||||
|
||||
if ($request->has($field->db_column)) {
|
||||
if ($field->element == 'checkbox') {
|
||||
if(is_array($field_val)) {
|
||||
$field_val = implode(',', $field_val);
|
||||
}
|
||||
}
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('admin')) {
|
||||
$field_val = Crypt::encrypt($field_val);
|
||||
} else {
|
||||
$problems_updating_encrypted_custom_fields = true;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
$asset->{$field->db_column} = $field_val;
|
||||
}
|
||||
}
|
||||
}
|
||||
$asset = $asset->handleCustomFieldsForStoring($request);
|
||||
|
||||
|
||||
if ($asset->save()) {
|
||||
|
||||
@@ -244,7 +244,7 @@ class LocationsController extends Controller
|
||||
|
||||
if (! $location->isDeletable()) {
|
||||
return response()
|
||||
->json(Helper::formatStandardApiResponse('error', null, trans('admin/companies/message.assoc_users')));
|
||||
->json(Helper::formatStandardApiResponse('error', null, trans('admin/locations/message.assoc_users')));
|
||||
}
|
||||
$this->authorize('delete', $location);
|
||||
$location->delete();
|
||||
|
||||
@@ -78,13 +78,14 @@ class ReportsController extends Controller
|
||||
];
|
||||
|
||||
|
||||
$total = $actionlogs->count();
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $actionlogs->count()) ? $actionlogs->count() : app('api_offset_value');
|
||||
$offset = ($request->input('offset') > $total) ? $total : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
|
||||
$sort = in_array($request->input('sort'), $allowed_columns) ? e($request->input('sort')) : 'created_at';
|
||||
$order = ($request->input('order') == 'asc') ? 'asc' : 'desc';
|
||||
$total = $actionlogs->count();
|
||||
|
||||
|
||||
$actionlogs = $actionlogs->orderBy($sort, $order)->skip($offset)->take($limit)->get();
|
||||
|
||||
|
||||
@@ -13,7 +13,8 @@ use App\Http\Transformers\SelectlistTransformer;
|
||||
use App\Http\Transformers\UsersTransformer;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\Accessory;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CurrentInventory;
|
||||
@@ -22,6 +23,7 @@ use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Validator;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use App\Http\Requests\DeleteUserRequest;
|
||||
|
||||
class UsersController extends Controller
|
||||
{
|
||||
@@ -31,7 +33,7 @@ class UsersController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return array
|
||||
*/
|
||||
public function index(Request $request)
|
||||
{
|
||||
@@ -75,7 +77,7 @@ class UsersController extends Controller
|
||||
'users.autoassign_licenses',
|
||||
'users.website',
|
||||
|
||||
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy')
|
||||
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy', 'managesUsers', 'managedLocations')
|
||||
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count');
|
||||
|
||||
|
||||
@@ -203,9 +205,6 @@ class UsersController extends Controller
|
||||
$users->where('autoassign_licenses', '=', $request->input('autoassign_licenses'));
|
||||
}
|
||||
|
||||
if ($request->filled('location_id') != '') {
|
||||
$users = $users->UserLocation($request->input('location_id'), $request->input('search'));
|
||||
}
|
||||
|
||||
if (($request->filled('deleted')) && ($request->input('deleted') == 'true')) {
|
||||
$users = $users->onlyTrashed();
|
||||
@@ -248,10 +247,6 @@ class UsersController extends Controller
|
||||
'jobtitle',
|
||||
'username',
|
||||
'employee_num',
|
||||
'assets',
|
||||
'accessories',
|
||||
'consumables',
|
||||
'licenses',
|
||||
'groups',
|
||||
'activated',
|
||||
'created_at',
|
||||
@@ -289,10 +284,6 @@ class UsersController extends Controller
|
||||
|
||||
|
||||
|
||||
// Apply companyable scope
|
||||
$users = Company::scopeCompanyables($users);
|
||||
|
||||
|
||||
// Make sure the offset and limit are actually integers and do not exceed system limits
|
||||
$offset = ($request->input('offset') > $users->count()) ? $users->count() : app('api_offset_value');
|
||||
$limit = app('api_limit_value');
|
||||
@@ -325,8 +316,6 @@ class UsersController extends Controller
|
||||
]
|
||||
)->where('show_in_list', '=', '1');
|
||||
|
||||
$users = Company::scopeCompanyables($users);
|
||||
|
||||
if ($request->filled('search')) {
|
||||
$users = $users->where(function ($query) use ($request) {
|
||||
$query->SimpleNameSearch($request->get('search'))
|
||||
@@ -368,7 +357,7 @@ class UsersController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return array | \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function store(SaveUserRequest $request)
|
||||
{
|
||||
@@ -415,15 +404,13 @@ class UsersController extends Controller
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return array | \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function show($id)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
|
||||
$user = User::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count');
|
||||
|
||||
if ($user = Company::scopeCompanyables($user)->find($id)) {
|
||||
if ($user = User::withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count', 'managesUsers as manages_users_count', 'managedLocations as manages_locations_count')->find($id)) {
|
||||
$this->authorize('view', $user);
|
||||
return (new UsersTransformer)->transformUser($user);
|
||||
}
|
||||
@@ -440,86 +427,89 @@ class UsersController extends Controller
|
||||
* @since [v4.0]
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function update(SaveUserRequest $request, $id)
|
||||
{
|
||||
$this->authorize('update', User::class);
|
||||
|
||||
$user = User::findOrFail($id);
|
||||
$user = Company::scopeCompanyables($user)->find($id);
|
||||
$this->authorize('update', $user);
|
||||
|
||||
/**
|
||||
* This is a janky hack to prevent people from changing admin demo user data on the public demo.
|
||||
*
|
||||
* The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder.
|
||||
*
|
||||
* Thanks, jerks. You are why we can't have nice things. - snipe
|
||||
*
|
||||
*/
|
||||
if ($user = User::find($id)) {
|
||||
|
||||
|
||||
if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.'));
|
||||
}
|
||||
$this->authorize('update', $user);
|
||||
|
||||
/**
|
||||
* This is a janky hack to prevent people from changing admin demo user data on the public demo.
|
||||
* The $ids 1 and 2 are special since they are seeded as superadmins in the demo seeder.
|
||||
* Thanks, jerks. You are why we can't have nice things. - snipe
|
||||
*
|
||||
*/
|
||||
|
||||
|
||||
$user->fill($request->all());
|
||||
|
||||
if ($user->id == $request->input('manager_id')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
|
||||
}
|
||||
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
// We need to use has() instead of filled()
|
||||
// here because we need to overwrite permissions
|
||||
// if someone needs to null them out
|
||||
if ($request->has('permissions')) {
|
||||
$permissions_array = $request->input('permissions');
|
||||
|
||||
// Strip out the individual superuser permission if the API user isn't a superadmin
|
||||
if (! Auth::user()->isSuperUser()) {
|
||||
unset($permissions_array['superuser']);
|
||||
if ((($id == 1) || ($id == 2)) && (config('app.lock_passwords'))) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Permission denied. You cannot update user information via API on the demo.'));
|
||||
}
|
||||
|
||||
$user->permissions = $permissions_array;
|
||||
}
|
||||
|
||||
$user->fill($request->all());
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
|
||||
if ($user->id == $request->input('manager_id')) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'You cannot be your own manager'));
|
||||
}
|
||||
|
||||
|
||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
|
||||
|
||||
if ($user->save()) {
|
||||
if ($request->filled('password')) {
|
||||
$user->password = bcrypt($request->input('password'));
|
||||
}
|
||||
|
||||
// Check if the request has groups passed and has a value, AND that the user us a superuser
|
||||
if (($request->has('groups')) && (Auth::user()->isSuperUser())) {
|
||||
// We need to use has() instead of filled()
|
||||
// here because we need to overwrite permissions
|
||||
// if someone needs to null them out
|
||||
if ($request->has('permissions')) {
|
||||
$permissions_array = $request->input('permissions');
|
||||
|
||||
$validator = Validator::make($request->only('groups'), [
|
||||
'groups.*' => 'integer|exists:permission_groups,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()));
|
||||
// Strip out the individual superuser permission if the API user isn't a superadmin
|
||||
if (!Auth::user()->isSuperUser()) {
|
||||
unset($permissions_array['superuser']);
|
||||
}
|
||||
|
||||
// Sync the groups since the user is a superuser and the groups pass validation
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
|
||||
|
||||
$user->permissions = $permissions_array;
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
->where('assigned_to', $user->id)->update(['location_id' => $request->input('location_id', null)]);
|
||||
|
||||
|
||||
app('App\Http\Requests\ImageUploadRequest')->handleImages($user, 600, 'image', 'avatars', 'avatar');
|
||||
|
||||
if ($user->save()) {
|
||||
|
||||
// Check if the request has groups passed and has a value, AND that the user us a superuser
|
||||
if (($request->has('groups')) && (Auth::user()->isSuperUser())) {
|
||||
|
||||
$validator = Validator::make($request->only('groups'), [
|
||||
'groups.*' => 'integer|exists:permission_groups,id',
|
||||
]);
|
||||
|
||||
if ($validator->fails()) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $validator->errors()));
|
||||
}
|
||||
|
||||
// Sync the groups since the user is a superuser and the groups pass validation
|
||||
$user->groups()->sync($request->input('groups'));
|
||||
|
||||
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', (new UsersTransformer)->transformUser($user), trans('admin/users/message.success.update')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -528,41 +518,15 @@ class UsersController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.0]
|
||||
* @param int $id
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function destroy($id)
|
||||
public function destroy(DeleteUserRequest $request, $id)
|
||||
{
|
||||
$this->authorize('delete', User::class);
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed();
|
||||
$user = Company::scopeCompanyables($user)->find($id);
|
||||
$this->authorize('delete', $user);
|
||||
|
||||
if ($user) {
|
||||
if ($user = User::withTrashed()->find($id)) {
|
||||
|
||||
if ($user->id === Auth::id()) {
|
||||
// Redirect to the user management page
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.cannot_delete_yourself')));
|
||||
}
|
||||
|
||||
if (($user->assets) && ($user->assets->count() > 0)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans_choice('admin/users/message.error.delete_has_assets_var', $user->assets()->count(), ['count'=> $user->assets()->count()])));
|
||||
}
|
||||
|
||||
if (($user->licenses) && ($user->licenses->count() > 0)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans_choice('admin/users/message.error.delete_has_licenses_var', $user->licenses()->count(), ['count'=> $user->licenses()->count()])));
|
||||
}
|
||||
|
||||
if (($user->accessories) && ($user->accessories->count() > 0)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans_choice('admin/users/message.error.delete_has_accessories_var', $user->accessories()->count(), ['count'=> $user->accessories()->count()])));
|
||||
}
|
||||
|
||||
if (($user->managedLocations()) && ($user->managedLocations()->count() > 0)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans_choice('admin/users/message.error.delete_has_locations_var', $user->managedLocations()->count(), ['count'=> $user->managedLocations()->count()])));
|
||||
}
|
||||
|
||||
if (($user->managesUsers()) && ($user->managesUsers()->count() > 0)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans_choice('admin/users/message.error.delete_has_users_var', $user->managesUsers()->count(), ['count'=> $user->managesUsers()->count()])));
|
||||
}
|
||||
$this->authorize('delete', $user);
|
||||
|
||||
if ($user->delete()) {
|
||||
|
||||
@@ -577,9 +541,13 @@ class UsersController extends Controller
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.delete')));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete')));
|
||||
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.error.delete')));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -588,39 +556,42 @@ class UsersController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @param $userId
|
||||
* @return string JSON
|
||||
* @return array | \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function assets(Request $request, $id)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$this->authorize('view', Asset::class);
|
||||
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed();
|
||||
$user = Company::scopeCompanyables($user)->find($id);
|
||||
$this->authorize('view', $user);
|
||||
if ($user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id)) {
|
||||
$this->authorize('view', $user);
|
||||
|
||||
$assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model');
|
||||
$assets = Asset::where('assigned_to', '=', $id)->where('assigned_type', '=', User::class)->with('model');
|
||||
|
||||
|
||||
// Filter on category ID
|
||||
if ($request->filled('category_id')) {
|
||||
$assets = $assets->InCategory($request->input('category_id'));
|
||||
}
|
||||
|
||||
|
||||
// Filter on model ID
|
||||
if ($request->filled('model_id')) {
|
||||
|
||||
$model_ids = $request->input('model_id');
|
||||
if (!is_array($model_ids)) {
|
||||
$model_ids = array($model_ids);
|
||||
// Filter on category ID
|
||||
if ($request->filled('category_id')) {
|
||||
$assets = $assets->InCategory($request->input('category_id'));
|
||||
}
|
||||
$assets = $assets->InModelList($model_ids);
|
||||
|
||||
|
||||
// Filter on model ID
|
||||
if ($request->filled('model_id')) {
|
||||
|
||||
$model_ids = $request->input('model_id');
|
||||
if (!is_array($model_ids)) {
|
||||
$model_ids = array($model_ids);
|
||||
}
|
||||
$assets = $assets->InModelList($model_ids);
|
||||
}
|
||||
|
||||
$assets = $assets->get();
|
||||
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
|
||||
}
|
||||
|
||||
$assets = $assets->get();
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
|
||||
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -635,17 +606,21 @@ class UsersController extends Controller
|
||||
public function emailAssetList(Request $request, $id)
|
||||
{
|
||||
$this->authorize('update', User::class);
|
||||
$user = User::findOrFail($id);
|
||||
$user = Company::scopeCompanyables($user)->find($id);
|
||||
$this->authorize('update', $user);
|
||||
|
||||
if (empty($user->email)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
|
||||
if ($user = User::find($id)) {
|
||||
$this->authorize('update', $user);
|
||||
|
||||
if (empty($user->email)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
|
||||
}
|
||||
|
||||
$user->notify((new CurrentInventory($user)));
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success')));
|
||||
}
|
||||
|
||||
$user->notify((new CurrentInventory($user)));
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found', compact('id'))));
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success')));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -654,14 +629,14 @@ class UsersController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @param $userId
|
||||
* @return string JSON
|
||||
* @return array | \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function consumables(Request $request, $id)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$this->authorize('view', Consumable::class);
|
||||
$user = User::findOrFail($id);
|
||||
$this->authorize('update', $user);
|
||||
$this->authorize('view', $user);
|
||||
$consumables = $user->consumables;
|
||||
return (new ConsumablesTransformer)->transformConsumables($consumables, $consumables->count(), $request);
|
||||
}
|
||||
@@ -672,7 +647,7 @@ class UsersController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v4.6.14]
|
||||
* @param $userId
|
||||
* @return string JSON
|
||||
* @return array
|
||||
*/
|
||||
public function accessories($id)
|
||||
{
|
||||
@@ -691,7 +666,7 @@ class UsersController extends Controller
|
||||
* @author [N. Mathar] [<snipe@snipe.net>]
|
||||
* @since [v5.0]
|
||||
* @param $userId
|
||||
* @return string JSON
|
||||
* @return array | \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function licenses($id)
|
||||
{
|
||||
@@ -754,7 +729,7 @@ class UsersController extends Controller
|
||||
* @author [Juan Font] [<juanfontalonso@gmail.com>]
|
||||
* @since [v4.4.2]
|
||||
* @param \Illuminate\Http\Request $request
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return array
|
||||
*/
|
||||
public function getCurrentUserInfo(Request $request)
|
||||
{
|
||||
@@ -767,12 +742,14 @@ class UsersController extends Controller
|
||||
* @author [E. Taylor] [<dev@evantaylor.name>]
|
||||
* @param int $userId
|
||||
* @since [v6.0.0]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function restore($userId = null)
|
||||
public function restore($userId)
|
||||
{
|
||||
$this->authorize('delete', User::class);
|
||||
|
||||
if ($user = User::withTrashed()->find($userId)) {
|
||||
|
||||
$this->authorize('delete', $user);
|
||||
|
||||
if ($user->deleted_at == '') {
|
||||
@@ -791,8 +768,6 @@ class UsersController extends Controller
|
||||
return response()->json(Helper::formatStandardApiResponse('success', null, trans('admin/users/message.success.restored')), 200);
|
||||
}
|
||||
|
||||
// Check validation to make sure we're not restoring a user with the same username as an existing user
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, $user->getErrors()));
|
||||
}
|
||||
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.user_not_found')), 200);
|
||||
|
||||
@@ -85,7 +85,7 @@ class AssetModelsController extends Controller
|
||||
$model->category_id = $request->input('category_id');
|
||||
$model->notes = $request->input('notes');
|
||||
$model->user_id = Auth::id();
|
||||
$model->requestable = Request::has('requestable');
|
||||
$model->requestable = $request->has('requestable');
|
||||
|
||||
if ($request->input('fieldset_id') != '') {
|
||||
$model->fieldset_id = $request->input('fieldset_id');
|
||||
@@ -288,7 +288,7 @@ class AssetModelsController extends Controller
|
||||
public function show($modelId = null)
|
||||
{
|
||||
$this->authorize('view', AssetModel::class);
|
||||
$model = AssetModel::withTrashed()->withCount('assets')->find($modelId);
|
||||
$model = AssetModel::withTrashed()->find($modelId);
|
||||
|
||||
if (isset($model->id)) {
|
||||
return view('models/view', compact('model'));
|
||||
|
||||
@@ -160,29 +160,7 @@ class AssetsController extends Controller
|
||||
$asset = $request->handleImages($asset);
|
||||
}
|
||||
|
||||
// Update custom fields in the database.
|
||||
// Validation for these fields is handled through the AssetRequest form request
|
||||
$model = AssetModel::find($request->get('model_id'));
|
||||
|
||||
if (($model) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('admin')) {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = Crypt::encrypt(implode(', ', $request->input($field->db_column)));
|
||||
} else {
|
||||
$asset->{$field->db_column} = Crypt::encrypt($request->input($field->db_column));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = implode(', ', $request->input($field->db_column));
|
||||
} else {
|
||||
$asset->{$field->db_column} = $request->input($field->db_column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
$asset = $asset->handleCustomFieldsForStoring($request);
|
||||
|
||||
// Validate the asset before saving
|
||||
if ($asset->isValid() && $asset->save()) {
|
||||
@@ -370,32 +348,7 @@ class AssetsController extends Controller
|
||||
$asset->notes = $request->input('notes');
|
||||
|
||||
$asset = $request->handleImages($asset);
|
||||
|
||||
// Update custom fields in the database.
|
||||
// Validation for these fields is handlded through the AssetRequest form request
|
||||
// FIXME: No idea why this is returning a Builder error on db_column_name.
|
||||
// Need to investigate and fix. Using static method for now.
|
||||
$model = AssetModel::find($request->get('model_id'));
|
||||
if (($model) && ($model->fieldset)) {
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('admin')) {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = Crypt::encrypt(implode(', ', $request->input($field->db_column)));
|
||||
} else {
|
||||
$asset->{$field->db_column} = Crypt::encrypt($request->input($field->db_column));
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$asset->{$field->db_column} = implode(', ', $request->input($field->db_column));
|
||||
} else {
|
||||
$asset->{$field->db_column} = $request->input($field->db_column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$asset = $asset->handleCustomFieldsForStoring($request);
|
||||
|
||||
if ($asset->save()) {
|
||||
return redirect()->route('hardware.show', $assetId)
|
||||
@@ -905,7 +858,7 @@ class AssetsController extends Controller
|
||||
if ($request->input('update_location') == '1') {
|
||||
$asset->location_id = $request->input('location_id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Invoke Watson Validating to check the asset itself and check to make sure it saved correctly.
|
||||
|
||||
@@ -427,10 +427,6 @@ class LoginController extends Controller
|
||||
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.code_required'));
|
||||
}
|
||||
|
||||
if (! $request->has('two_factor_secret')) { // TODO this seems almost the same as above?
|
||||
return redirect()->route('two-factor')->with('error', 'Two-factor code is required.');
|
||||
}
|
||||
|
||||
$user = Auth::user();
|
||||
$secret = $request->input('two_factor_secret');
|
||||
|
||||
@@ -439,7 +435,7 @@ class LoginController extends Controller
|
||||
$user->saveQuietly();
|
||||
$request->session()->put('2fa_authed', $user->id);
|
||||
|
||||
return redirect()->route('home')->with('success', 'You are logged in!');
|
||||
return redirect()->route('home')->with('success', trans('auth/message.signin.success'));
|
||||
}
|
||||
|
||||
return redirect()->route('two-factor')->with('error', trans('auth/message.two_factor.invalid_code'));
|
||||
@@ -537,7 +533,7 @@ class LoginController extends Controller
|
||||
|
||||
$minutes = round($seconds / 60);
|
||||
|
||||
$message = \Lang::get('auth/message.throttle', ['minutes' => $minutes]);
|
||||
$message = trans('auth/message.throttle', ['minutes' => $minutes]);
|
||||
|
||||
return redirect()->back()
|
||||
->withInput($request->only($this->username(), 'remember'))
|
||||
|
||||
@@ -28,8 +28,8 @@ class ProfileController extends Controller
|
||||
*/
|
||||
public function getIndex()
|
||||
{
|
||||
$this->authorize('self.profile');
|
||||
$user = Auth::user();
|
||||
|
||||
return view('account/profile', compact('user'));
|
||||
}
|
||||
|
||||
@@ -42,6 +42,7 @@ class ProfileController extends Controller
|
||||
*/
|
||||
public function postIndex(ImageUploadRequest $request)
|
||||
{
|
||||
$this->authorize('self.profile');
|
||||
$user = Auth::user();
|
||||
$user->first_name = $request->input('first_name');
|
||||
$user->last_name = $request->input('last_name');
|
||||
@@ -67,7 +68,7 @@ class ProfileController extends Controller
|
||||
|
||||
|
||||
if ($user->save()) {
|
||||
return redirect()->route('profile')->with('success', trans('account.general.profile_updated'));
|
||||
return redirect()->route('profile')->with('success', trans('account/general.profile_updated'));
|
||||
}
|
||||
|
||||
return redirect()->back()->withInput()->withErrors($user->getErrors());
|
||||
|
||||
@@ -933,7 +933,7 @@ class ReportsController extends Controller
|
||||
$diff = ($asset->purchase_cost - $depreciation);
|
||||
$row[] = Helper::formatCurrencyOutput($depreciation);
|
||||
$row[] = Helper::formatCurrencyOutput($diff);
|
||||
$row[] = ($asset->depreciation) ? $asset->depreciated_date()->format('Y-m-d') : '';
|
||||
$row[] = (($asset->depreciation) && ($asset->depreciated_date())) ? $asset->depreciated_date()->format('Y-m-d') : '';
|
||||
}
|
||||
|
||||
if ($request->filled('checkout_date')) {
|
||||
|
||||
@@ -25,6 +25,7 @@ use Illuminate\Support\Facades\Artisan;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Support\Facades\File;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
@@ -67,28 +68,9 @@ class SettingsController extends Controller
|
||||
$start_settings['db_error'] = $e->getMessage();
|
||||
}
|
||||
|
||||
if (array_key_exists("HTTP_X_FORWARDED_PROTO", $_SERVER)) {
|
||||
$protocol = $_SERVER["HTTP_X_FORWARDED_PROTO"] . "://";
|
||||
} elseif (array_key_exists('HTTPS', $_SERVER) && ('on' == $_SERVER['HTTPS'])) {
|
||||
$protocol = "https://";
|
||||
} else {
|
||||
$protocol = "http://";
|
||||
}
|
||||
|
||||
if (array_key_exists("HTTP_X_FORWARDED_HOST", $_SERVER)) {
|
||||
$host = $_SERVER["HTTP_X_FORWARDED_HOST"];
|
||||
} else {
|
||||
$host = array_key_exists('SERVER_NAME', $_SERVER) ? $_SERVER['SERVER_NAME'] : null;
|
||||
$port = array_key_exists('SERVER_PORT', $_SERVER) ? $_SERVER['SERVER_PORT'] : null;
|
||||
if (('http://' === $protocol && '80' != $port) || ('https://' === $protocol && '443' != $port)) {
|
||||
$host .= ':'.$port;
|
||||
}
|
||||
}
|
||||
$pageURL = $protocol.$host.$_SERVER['REQUEST_URI'];
|
||||
|
||||
$start_settings['url_config'] = config('app.url').'/setup';
|
||||
$start_settings['url_valid'] = ($start_settings['url_config'] === $pageURL);
|
||||
$start_settings['real_url'] = $pageURL;
|
||||
$start_settings['url_config'] = trim(config('app.url'), '/'). '/setup';
|
||||
$start_settings['real_url'] = request()->url();
|
||||
$start_settings['url_valid'] = $start_settings['url_config'] === $start_settings['real_url'];
|
||||
$start_settings['php_version_min'] = true;
|
||||
|
||||
// Curl the .env file to make sure it's not accessible via a browser
|
||||
@@ -125,17 +107,7 @@ class SettingsController extends Controller
|
||||
$start_settings['owner_is_admin'] = false;
|
||||
}
|
||||
|
||||
if ((is_writable(storage_path()))
|
||||
&& (is_writable(storage_path().'/framework'))
|
||||
&& (is_writable(storage_path().'/framework/cache'))
|
||||
&& (is_writable(storage_path().'/framework/sessions'))
|
||||
&& (is_writable(storage_path().'/framework/views'))
|
||||
&& (is_writable(storage_path().'/logs'))
|
||||
) {
|
||||
$start_settings['writable'] = true;
|
||||
} else {
|
||||
$start_settings['writable'] = false;
|
||||
}
|
||||
$start_settings['writable'] = $this->storagePathIsWritable();
|
||||
|
||||
$start_settings['gd'] = extension_loaded('gd');
|
||||
|
||||
@@ -164,6 +136,19 @@ class SettingsController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine if the app storage path is writable.
|
||||
*/
|
||||
protected function storagePathIsWritable(): bool
|
||||
{
|
||||
return File::isWritable(storage_path()) &&
|
||||
File::isWritable(storage_path('framework')) &&
|
||||
File::isWritable(storage_path('framework/cache')) &&
|
||||
File::isWritable(storage_path('framework/sessions')) &&
|
||||
File::isWritable(storage_path('framework/views')) &&
|
||||
File::isWritable(storage_path('logs'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Save the first admin user from Setup.
|
||||
*
|
||||
@@ -363,12 +348,11 @@ class SettingsController extends Controller
|
||||
}
|
||||
|
||||
$setting->default_eula_text = $request->input('default_eula_text');
|
||||
$setting->load_remote = $request->input('load_remote', 0);
|
||||
$setting->thumbnail_max_h = $request->input('thumbnail_max_h');
|
||||
$setting->privacy_policy_link = $request->input('privacy_policy_link');
|
||||
|
||||
$setting->depreciation_method = $request->input('depreciation_method');
|
||||
$setting->dash_chart_type = $request->input('dash_chart_type');
|
||||
$setting->profile_edit = $request->input('profile_edit', 0);
|
||||
|
||||
if ($request->input('per_page') != '') {
|
||||
$setting->per_page = $request->input('per_page');
|
||||
@@ -408,10 +392,11 @@ class SettingsController extends Controller
|
||||
*
|
||||
* @since [v1.0]
|
||||
*
|
||||
* @return View
|
||||
* @return \Illuminate\Contracts\View\View | \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function postBranding(ImageUploadRequest $request)
|
||||
{
|
||||
// Something has gone horribly wrong - no settings record exists!
|
||||
if (is_null($setting = Setting::getSettings())) {
|
||||
return redirect()->to('admin')->with('error', trans('admin/settings/message.update.error'));
|
||||
}
|
||||
@@ -422,51 +407,75 @@ class SettingsController extends Controller
|
||||
$setting->version_footer = $request->input('version_footer');
|
||||
$setting->footer_text = $request->input('footer_text');
|
||||
$setting->skin = $request->input('skin');
|
||||
$setting->allow_user_skin = $request->input('allow_user_skin');
|
||||
$setting->allow_user_skin = $request->input('allow_user_skin', '0');
|
||||
$setting->show_url_in_emails = $request->input('show_url_in_emails', '0');
|
||||
$setting->logo_print_assets = $request->input('logo_print_assets', '0');
|
||||
$setting->load_remote = $request->input('load_remote', 0);
|
||||
|
||||
// Only allow the site name and CSS to be changed if lock_passwords is false
|
||||
// Only allow the site name, images, and CSS to be changed if lock_passwords is false
|
||||
// Because public demos make people act like dicks
|
||||
|
||||
if (! config('app.lock_passwords')) {
|
||||
$request->validate(['site_name' => 'required']);
|
||||
$setting->site_name = $request->input('site_name');
|
||||
if (!config('app.lock_passwords')) {
|
||||
|
||||
if ($request->has('site_name')) {
|
||||
$request->validate(['site_name' => 'required']);
|
||||
}
|
||||
|
||||
$setting->site_name = $request->input('site_name', 'Snipe-IT');
|
||||
$setting->custom_css = $request->input('custom_css');
|
||||
|
||||
// Logo upload
|
||||
$setting = $request->handleImages($setting, 600, 'logo', '', 'logo');
|
||||
|
||||
if ('1' == $request->input('clear_logo')) {
|
||||
Storage::disk('public')->delete($setting->logo);
|
||||
if ($request->input('clear_logo') == '1') {
|
||||
|
||||
if (($setting->logo) && (Storage::exists($setting->logo))) {
|
||||
Storage::disk('public')->delete($setting->logo);
|
||||
}
|
||||
$setting->logo = null;
|
||||
$setting->brand = 1;
|
||||
}
|
||||
|
||||
|
||||
// Email logo upload
|
||||
$setting = $request->handleImages($setting, 600, 'email_logo', '', 'email_logo');
|
||||
if ($request->input('clear_email_logo') == '1') {
|
||||
|
||||
|
||||
if ('1' == $request->input('clear_email_logo')) {
|
||||
Storage::disk('public')->delete($setting->email_logo);
|
||||
if (($setting->email_logo) && (Storage::exists($setting->email_logo))) {
|
||||
Storage::disk('public')->delete($setting->email_logo);
|
||||
}
|
||||
$setting->email_logo = null;
|
||||
// If they are uploading an image, validate it and upload it
|
||||
}
|
||||
|
||||
|
||||
// Label logo upload
|
||||
$setting = $request->handleImages($setting, 600, 'label_logo', '', 'label_logo');
|
||||
if ($request->input('clear_label_logo') == '1') {
|
||||
|
||||
if ('1' == $request->input('clear_label_logo')) {
|
||||
Storage::disk('public')->delete($setting->label_logo);
|
||||
if (($setting->label_logo) && (Storage::exists($setting->label_logo))) {
|
||||
Storage::disk('public')->delete($setting->label_logo);
|
||||
}
|
||||
$setting->label_logo = null;
|
||||
}
|
||||
|
||||
|
||||
$setting = $request->handleImages($setting, 600, 'favicon', '', 'favicon');
|
||||
|
||||
// If the user wants to clear the favicon...
|
||||
// Favicon upload
|
||||
$setting = $request->handleImages($setting, 100, 'favicon', '', 'favicon');
|
||||
if ('1' == $request->input('clear_favicon')) {
|
||||
Storage::disk('public')->delete($setting->favicon);
|
||||
|
||||
if (($setting->favicon) && (Storage::exists($setting->favicon))) {
|
||||
Storage::disk('public')->delete($setting->favicon);
|
||||
}
|
||||
$setting->favicon = null;
|
||||
}
|
||||
|
||||
// Default avatar upload
|
||||
$setting = $request->handleImages($setting, 500, 'default_avatar', 'avatars', 'default_avatar');
|
||||
if ($request->input('clear_default_avatar') == '1') {
|
||||
|
||||
if (($setting->default_avatar) && (Storage::exists('avatars/'.$setting->default_avatar))) {
|
||||
Storage::disk('public')->delete('avatars/'.$setting->default_avatar);
|
||||
}
|
||||
$setting->default_avatar = null;
|
||||
}
|
||||
}
|
||||
|
||||
if ($setting->save()) {
|
||||
|
||||
@@ -42,7 +42,7 @@ class BulkUsersController extends Controller
|
||||
// Get the list of affected users
|
||||
$user_raw_array = request('ids');
|
||||
$users = User::whereIn('id', $user_raw_array)
|
||||
->with('groups', 'assets', 'licenses', 'accessories')->get();
|
||||
->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations','uploads', 'acceptances')->get();
|
||||
|
||||
// bulk edit, display the bulk edit form
|
||||
if ($request->input('bulk_actions') == 'edit') {
|
||||
@@ -317,7 +317,7 @@ class BulkUsersController extends Controller
|
||||
|
||||
// Get the users
|
||||
$merge_into_user = User::find($request->input('merge_into_id'));
|
||||
$users_to_merge = User::whereIn('id', $user_ids_to_merge)->with('assets', 'licenses', 'consumables','accessories')->get();
|
||||
$users_to_merge = User::whereIn('id', $user_ids_to_merge)->with('assets', 'manager', 'userlog', 'licenses', 'consumables', 'accessories', 'managedLocations','uploads', 'acceptances')->get();
|
||||
$admin = User::find(Auth::user()->id);
|
||||
|
||||
// Walk users
|
||||
@@ -344,10 +344,20 @@ class BulkUsersController extends Controller
|
||||
}
|
||||
|
||||
foreach ($user_to_merge->userlog as $log) {
|
||||
$log->target_id = $user_to_merge->id;
|
||||
$log->target_id = $merge_into_user->id;
|
||||
$log->save();
|
||||
}
|
||||
|
||||
foreach ($user_to_merge->uploads as $upload) {
|
||||
$upload->item_id = $merge_into_user->id;
|
||||
$upload->save();
|
||||
}
|
||||
|
||||
foreach ($user_to_merge->acceptances as $acceptance) {
|
||||
$acceptance->item_id = $merge_into_user->id;
|
||||
$acceptance->save();
|
||||
}
|
||||
|
||||
User::where('manager_id', '=', $user_to_merge->id)->update(['manager_id' => $merge_into_user->id]);
|
||||
|
||||
foreach ($user_to_merge->managedLocations as $managedLocation) {
|
||||
@@ -356,7 +366,6 @@ class BulkUsersController extends Controller
|
||||
}
|
||||
|
||||
$user_to_merge->delete();
|
||||
//$user_to_merge->save();
|
||||
|
||||
event(new UserMerged($user_to_merge, $merge_into_user, $admin));
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ namespace App\Http\Controllers\Users;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\DeleteUserRequest;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Http\Requests\SaveUserRequest;
|
||||
use App\Models\Actionlog;
|
||||
@@ -16,7 +17,9 @@ use App\Notifications\WelcomeNotification;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Database\Eloquent\ModelNotFoundException;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Password;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Redirect;
|
||||
use Str;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
@@ -181,8 +184,7 @@ class UsersController extends Controller
|
||||
{
|
||||
|
||||
$this->authorize('update', User::class);
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed();
|
||||
$user = Company::scopeCompanyables($user)->find($id);
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id);
|
||||
|
||||
if ($user) {
|
||||
|
||||
@@ -228,9 +230,7 @@ class UsersController extends Controller
|
||||
$permissions = $request->input('permissions', []);
|
||||
app('request')->request->set('permissions', $permissions);
|
||||
|
||||
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed();
|
||||
$user = Company::scopeCompanyables($user)->find($id);
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id);
|
||||
|
||||
// User is valid - continue...
|
||||
if ($user) {
|
||||
@@ -333,55 +333,26 @@ class UsersController extends Controller
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($id = null)
|
||||
public function destroy(DeleteUserRequest $request, $id = null)
|
||||
{
|
||||
|
||||
$this->authorize('delete', User::class);
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed();
|
||||
$user = Company::scopeCompanyables($user)->find($id);
|
||||
|
||||
if ($user = User::find($id)) {
|
||||
|
||||
if ($user) {
|
||||
// Check if we are not trying to delete ourselves
|
||||
if ($user->id === Auth::id()) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')
|
||||
->with('error', trans('admin/users/message.error.cannot_delete_yourself'));
|
||||
$this->authorize('delete', $user);
|
||||
|
||||
if ($user->delete()) {
|
||||
if (Storage::disk('public')->exists('avatars/' . $user->avatar)) {
|
||||
try {
|
||||
Storage::disk('public')->delete('avatars/' . $user->avatar);
|
||||
} catch (\Exception $e) {
|
||||
Log::debug($e);
|
||||
}
|
||||
}
|
||||
return redirect()->route('users.index')->with('success', trans('admin/users/message.success.delete'));
|
||||
}
|
||||
|
||||
if (($user->assets()) && ($user->assets()->count() > 0)) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')
|
||||
->with('error', trans_choice('admin/users/message.error.delete_has_assets_var', $user->assets()->count(), ['count'=> $user->assets()->count()]));
|
||||
}
|
||||
|
||||
if (($user->licenses()) && ($user->licenses()->count() > 0)) {
|
||||
return redirect()->route('users.index')->with('error', trans_choice('admin/users/message.error.delete_has_licenses_var', $user->licenses()->count(), ['count'=> $user->licenses()->count()]));
|
||||
}
|
||||
|
||||
if (($user->accessories()) && ($user->accessories()->count() > 0)) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')->with('error', trans_choice('admin/users/message.error.delete_has_accessories_var', $user->accessories()->count(), ['count'=> $user->accessories()->count()]));
|
||||
}
|
||||
|
||||
if (($user->managedLocations()) && ($user->managedLocations()->count() > 0)) {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')
|
||||
->with('error', trans_choice('admin/users/message.error.delete_has_locations_var', $user->managedLocations()->count(), ['count'=> $user->managedLocations()->count()]));
|
||||
}
|
||||
|
||||
if (($user->managesUsers()) && ($user->managesUsers()->count() > 0)) {
|
||||
return redirect()->route('users.index')
|
||||
->with('error', trans_choice('admin/users/message.error.delete_has_users_var', $user->managesUsers()->count(), ['count'=> $user->managesUsers()->count()]));
|
||||
}
|
||||
|
||||
// Delete the user
|
||||
$user->delete();
|
||||
return redirect()->route('users.index')->with('success', trans('admin/users/message.success.delete'));
|
||||
}
|
||||
|
||||
return redirect()->route('users.index')
|
||||
->with('error', trans('admin/users/message.user_not_found', compact('id')));
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found'));
|
||||
|
||||
}
|
||||
|
||||
@@ -441,8 +412,7 @@ class UsersController extends Controller
|
||||
// Make sure the user can view users at all
|
||||
$this->authorize('view', User::class);
|
||||
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed();
|
||||
$user = Company::scopeCompanyables($user)->find($userId);
|
||||
$user = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($userId);
|
||||
|
||||
// Make sure they can view this particular user
|
||||
$this->authorize('view', $user);
|
||||
@@ -477,9 +447,7 @@ class UsersController extends Controller
|
||||
app('request')->request->set('permissions', $permissions);
|
||||
|
||||
|
||||
$user_to_clone = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed();
|
||||
$user_to_clone = Company::scopeCompanyables($user_to_clone)->find($id);
|
||||
|
||||
$user_to_clone = User::with('assets', 'assets.model', 'consumables', 'accessories', 'licenses', 'userloc')->withTrashed()->find($id);
|
||||
// Make sure they can view this particular user
|
||||
$this->authorize('view', $user_to_clone);
|
||||
|
||||
@@ -543,10 +511,7 @@ class UsersController extends Controller
|
||||
'groups',
|
||||
'userloc',
|
||||
'company'
|
||||
)->orderBy('created_at', 'DESC');
|
||||
|
||||
// FMCS scoping
|
||||
Company::scopeCompanyables($users)
|
||||
)->orderBy('created_at', 'DESC')
|
||||
->chunk(500, function ($users) use ($handle) {
|
||||
$headers = [
|
||||
// strtolower to prevent Excel from trying to open it as a SYLK file
|
||||
@@ -640,20 +605,21 @@ class UsersController extends Controller
|
||||
public function printInventory($id)
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
$show_user = Company::scopeCompanyables(User::where('id', $id)->withTrashed()->first());
|
||||
$user = User::where('id', $id)->withTrashed()->first();
|
||||
|
||||
|
||||
// Make sure they can view this particular user
|
||||
$this->authorize('view', $show_user);
|
||||
$this->authorize('view', $user);
|
||||
|
||||
$assets = Asset::where('assigned_to', $id)->where('assigned_type', User::class)->with('model', 'model.category')->get();
|
||||
$accessories = $show_user->accessories()->get();
|
||||
$consumables = $show_user->consumables()->get();
|
||||
$accessories = $user->accessories()->get();
|
||||
$consumables = $user->consumables()->get();
|
||||
|
||||
return view('users/print')->with('assets', $assets)
|
||||
->with('licenses', $show_user->licenses()->get())
|
||||
->with('licenses', $user->licenses()->get())
|
||||
->with('accessories', $accessories)
|
||||
->with('consumables', $consumables)
|
||||
->with('show_user', $show_user)
|
||||
->with('show_user', $user)
|
||||
->with('settings', Setting::getSettings());
|
||||
}
|
||||
|
||||
@@ -669,7 +635,7 @@ class UsersController extends Controller
|
||||
{
|
||||
$this->authorize('view', User::class);
|
||||
|
||||
$user = Company::scopeCompanyables(User::find($id));
|
||||
$user = User::find($id);
|
||||
|
||||
// Make sure they can view this particular user
|
||||
$this->authorize('view', $user);
|
||||
@@ -697,7 +663,9 @@ class UsersController extends Controller
|
||||
*/
|
||||
public function sendPasswordReset($id)
|
||||
{
|
||||
if (($user = Company::scopeCompanyables(User::find($id))) && ($user->activated == '1') && ($user->email != '') && ($user->ldap_import == '0')) {
|
||||
$this->authorize('view', User::class);
|
||||
|
||||
if (($user = User::find($id)) && ($user->activated == '1') && ($user->email != '') && ($user->ldap_import == '0')) {
|
||||
$credentials = ['email' => trim($user->email)];
|
||||
|
||||
try {
|
||||
|
||||
@@ -49,10 +49,10 @@ class CheckForTwoFactor
|
||||
|
||||
// Otherwise make sure they're enrolled and show them the 2FA code screen
|
||||
if ((Auth::user()->two_factor_secret != '') && (Auth::user()->two_factor_enrolled == '1')) {
|
||||
return redirect()->route('two-factor')->with('info', 'Please enter your two-factor authentication code.');
|
||||
return redirect()->route('two-factor')->with('info', trans('auth/message.two_factor.enter_two_factor_code'));
|
||||
}
|
||||
|
||||
return redirect()->route('two-factor-enroll')->with('success', 'Please enroll a device in two-factor authentication.');
|
||||
return redirect()->route('two-factor-enroll')->with('success', trans('auth/message.two_factor.please_enroll'));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,99 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use Illuminate\Foundation\Http\FormRequest;
|
||||
use Illuminate\Validation\Rule;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use App\Models\User;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
|
||||
|
||||
class DeleteUserRequest extends FormRequest
|
||||
{
|
||||
|
||||
protected $redirectRoute = 'users.index';
|
||||
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*/
|
||||
public function authorize(): bool
|
||||
{
|
||||
return Gate::allows('delete', User::class);
|
||||
}
|
||||
|
||||
public function prepareForValidation(): void
|
||||
{
|
||||
$user_to_delete = User::withTrashed()->find(request()->route('user'));
|
||||
|
||||
if ($user_to_delete) {
|
||||
$this->merge([
|
||||
'user' => request()->route('user'),
|
||||
'admin_id' => Auth::user()->id,
|
||||
'managed_users' => $user_to_delete->managesUsers()->count(),
|
||||
'managed_locations' => $user_to_delete->managedLocations()->count(),
|
||||
'assigned_assets' => $user_to_delete->assets()->count(),
|
||||
'assigned_licenses' => $user_to_delete->licenses()->count(),
|
||||
'assigned_accessories' => $user_to_delete->accessories()->count(),
|
||||
'deleted_at' => $user_to_delete->deleted_at,
|
||||
]);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the validation rules that apply to the request.
|
||||
*
|
||||
* @return array<string, \Illuminate\Contracts\Validation\ValidationRule|array<mixed>|string>
|
||||
*/
|
||||
public function rules(): array
|
||||
{
|
||||
return [
|
||||
'user' => Rule::notIn([auth()->user()->id]),
|
||||
'managed_users' => Rule::in([0]),
|
||||
'managed_locations' => Rule::in([0]),
|
||||
'assigned_assets' => Rule::in([0]),
|
||||
'assigned_licenses' => Rule::in([0]),
|
||||
'assigned_accessories' => Rule::in([0]),
|
||||
'deleted_at' => Rule::in([null]),
|
||||
];
|
||||
}
|
||||
|
||||
public function messages(): array
|
||||
{
|
||||
|
||||
$user_to_delete = User::withTrashed()->find(request()->route('user'));
|
||||
$messages = [];
|
||||
|
||||
if ($user_to_delete) {
|
||||
|
||||
$messages = array_merge([
|
||||
|
||||
'user.exists' => trans('admin/users/message.user_not_found'),
|
||||
|
||||
// Cannot delete yourself
|
||||
'user.not_in' => trans('admin/users/message.error.cannot_delete_yourself'),
|
||||
|
||||
// managed users is not 0
|
||||
'managed_users.in' => trans_choice('admin/users/message.error.delete_has_users_var', $user_to_delete->managesUsers()->count(), ['count' => $user_to_delete->managesUsers()->count()]),
|
||||
|
||||
// managed locations is not 0
|
||||
'managed_locations.in' => trans_choice('admin/users/message.error.delete_has_locations_var', $user_to_delete->managedLocations()->count(), ['count' => $user_to_delete->managedLocations()->count()]),
|
||||
|
||||
|
||||
// assigned_assets is not 0
|
||||
'assigned_assets.in' => trans_choice('admin/users/message.error.delete_has_assets_var', $user_to_delete->assets()->count(), ['count' => $user_to_delete->assets()->count()]),
|
||||
|
||||
// assigned licenses is not 0
|
||||
'assigned_licenses.in' => trans_choice('admin/users/message.error.delete_has_licenses_var', $user_to_delete->licenses()->count(), ['count' => $user_to_delete->licenses()->count()]),
|
||||
|
||||
// assigned accessories is not 0
|
||||
'assigned_accessories.in' => trans_choice('admin/users/message.error.delete_has_accessories_var', $user_to_delete->accessories()->count(), ['count' => $user_to_delete->accessories()->count()]),
|
||||
|
||||
'deleted_at.in' => trans('admin/users/message.user_deleted_warning'),
|
||||
|
||||
], $messages);
|
||||
}
|
||||
|
||||
return $messages;
|
||||
}
|
||||
}
|
||||
@@ -96,10 +96,7 @@ class ImageUploadRequest extends Request
|
||||
|
||||
$ext = $image->guessExtension();
|
||||
$file_name = $type.'-'.$form_fieldname.'-'.$item->id.'-'.str_random(10).'.'.$ext;
|
||||
|
||||
Log::info('File name will be: '.$file_name);
|
||||
Log::debug('File extension is: '.$ext);
|
||||
|
||||
|
||||
if (($image->getMimeType() == 'image/vnd.microsoft.icon') || ($image->getMimeType() == 'image/x-icon') || ($image->getMimeType() == 'image/avif') || ($image->getMimeType() == 'image/webp')) {
|
||||
// If the file is an icon, webp or avif, we need to just move it since gd doesn't support resizing
|
||||
// icons or avif, and webp support and needs to be compiled into gd for resizing to be available
|
||||
|
||||
@@ -2,12 +2,14 @@
|
||||
|
||||
namespace App\Http\Requests;
|
||||
|
||||
use App\Http\Traits\ConvertsBase64ToFiles;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class UploadFileRequest extends Request
|
||||
{
|
||||
use ConvertsBase64ToFiles;
|
||||
/**
|
||||
* Determine if the user is authorized to make this request.
|
||||
*
|
||||
|
||||
@@ -49,7 +49,12 @@ class ActionlogsTransformer
|
||||
public function transformActionlog (Actionlog $actionlog, $settings = null)
|
||||
{
|
||||
$icon = $actionlog->present()->icon();
|
||||
$custom_fields = CustomField::all();
|
||||
|
||||
static $custom_fields = false;
|
||||
|
||||
if ($custom_fields === false) {
|
||||
$custom_fields = CustomField::all();
|
||||
}
|
||||
|
||||
if ($actionlog->filename!='') {
|
||||
$icon = Helper::filetype_icon($actionlog->filename);
|
||||
@@ -217,13 +222,30 @@ class ActionlogsTransformer
|
||||
*/
|
||||
|
||||
public function changedInfo(array $clean_meta)
|
||||
{ $location = Location::withTrashed()->get();
|
||||
$supplier = Supplier::withTrashed()->get();
|
||||
$model = AssetModel::withTrashed()->get();
|
||||
$status = Statuslabel::withTrashed()->get();
|
||||
$company = Company::get();
|
||||
{
|
||||
static $location = false;
|
||||
static $supplier = false;
|
||||
static $model = false;
|
||||
static $status = false;
|
||||
static $company = false;
|
||||
|
||||
|
||||
if ($location === false) {
|
||||
$location = Location::select('id', 'name')->withTrashed()->get();
|
||||
}
|
||||
if ($supplier === false) {
|
||||
$supplier = Supplier::select('id', 'name')->withTrashed()->get();
|
||||
}
|
||||
if ($model === false) {
|
||||
$model = AssetModel::select('id', 'name')->withTrashed()->get();
|
||||
}
|
||||
if ($status === false) {
|
||||
$status = Statuslabel::select('id', 'name')->withTrashed()->get();
|
||||
}
|
||||
if ($company === false) {
|
||||
$company = Company::select('id', 'name')->get();
|
||||
}
|
||||
|
||||
if(array_key_exists('rtd_location_id',$clean_meta)) {
|
||||
|
||||
$oldRtd = $location->find($clean_meta['rtd_location_id']['old']);
|
||||
|
||||
@@ -24,7 +24,7 @@ class UsersTransformer
|
||||
|
||||
$array = [
|
||||
'id' => (int) $user->id,
|
||||
'avatar' => e($user->present()->gravatar),
|
||||
'avatar' => e($user->present()->gravatar) ?? null,
|
||||
'name' => e($user->getFullNameAttribute()),
|
||||
'first_name' => e($user->first_name),
|
||||
'last_name' => e($user->last_name),
|
||||
|
||||
@@ -7,8 +7,10 @@ use App\Models\AssetModel;
|
||||
use App\Models\Statuslabel;
|
||||
use App\Models\User;
|
||||
use App\Events\CheckoutableCheckedIn;
|
||||
use Carbon\CarbonImmutable;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
|
||||
class AssetImporter extends ItemImporter
|
||||
{
|
||||
@@ -18,8 +20,10 @@ class AssetImporter extends ItemImporter
|
||||
{
|
||||
parent::__construct($filename);
|
||||
|
||||
if (!is_null(Statuslabel::first())) {
|
||||
$this->defaultStatusLabelId = Statuslabel::first()->id;
|
||||
$this->defaultStatusLabelId = Statuslabel::first()->id;
|
||||
|
||||
if (!is_null(Statuslabel::deployable()->first())) {
|
||||
$this->defaultStatusLabelId = Statuslabel::deployable()->first()->id;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -64,16 +68,14 @@ class AssetImporter extends ItemImporter
|
||||
$editingAsset = false;
|
||||
$asset_tag = $this->findCsvMatch($row, 'asset_tag');
|
||||
|
||||
if(empty($asset_tag)){
|
||||
if (empty($asset_tag)){
|
||||
$asset_tag = Asset::autoincrement_asset();
|
||||
}
|
||||
|
||||
|
||||
$asset = Asset::where(['asset_tag'=> (string) $asset_tag])->first();
|
||||
if ($asset) {
|
||||
if (! $this->updating) {
|
||||
$this->log('A matching Asset '.$asset_tag.' already exists');
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
@@ -83,6 +85,13 @@ class AssetImporter extends ItemImporter
|
||||
$this->log('No Matching Asset, Creating a new one');
|
||||
$asset = new Asset;
|
||||
}
|
||||
|
||||
// If no status ID is found
|
||||
if (! array_key_exists('status_id', $this->item) && ! $editingAsset) {
|
||||
$this->log('No status ID field found, defaulting to first deployable status label.');
|
||||
$this->item['status_id'] = $this->defaultStatusLabelId;
|
||||
}
|
||||
|
||||
$this->item['notes'] = trim($this->findCsvMatch($row, 'asset_notes'));
|
||||
$this->item['image'] = trim($this->findCsvMatch($row, 'image'));
|
||||
$this->item['requestable'] = trim(($this->fetchHumanBoolean($this->findCsvMatch($row, 'requestable'))) == 1) ? '1' : 0;
|
||||
@@ -90,14 +99,12 @@ class AssetImporter extends ItemImporter
|
||||
$this->item['warranty_months'] = intval(trim($this->findCsvMatch($row, 'warranty_months')));
|
||||
$this->item['model_id'] = $this->createOrFetchAssetModel($row);
|
||||
$this->item['byod'] = ($this->fetchHumanBoolean(trim($this->findCsvMatch($row, 'byod'))) == 1) ? '1' : 0;
|
||||
|
||||
|
||||
// If no status ID is found
|
||||
if (! array_key_exists('status_id', $this->item) && ! $editingAsset) {
|
||||
$this->log('No status field found, defaulting to first status.');
|
||||
$this->item['status_id'] = $this->defaultStatusLabelId;
|
||||
}
|
||||
|
||||
$this->item['last_checkin'] = trim($this->findCsvMatch($row, 'last_checkin'));
|
||||
$this->item['last_checkout'] = trim($this->findCsvMatch($row, 'last_checkout'));
|
||||
$this->item['expected_checkin'] = trim($this->findCsvMatch($row, 'expected_checkin'));
|
||||
$this->item['last_audit_date'] = trim($this->findCsvMatch($row, 'last_audit_date'));
|
||||
$this->item['next_audit_date'] = trim($this->findCsvMatch($row, 'next_audit_date'));
|
||||
$this->item['asset_eol_date'] = trim($this->findCsvMatch($row, 'asset_eol_date'));
|
||||
$this->item['asset_tag'] = $asset_tag;
|
||||
|
||||
// We need to save the user if it exists so that we can checkout to user later.
|
||||
@@ -105,7 +112,9 @@ class AssetImporter extends ItemImporter
|
||||
if (array_key_exists('checkout_target', $this->item)) {
|
||||
$target = $this->item['checkout_target'];
|
||||
}
|
||||
|
||||
$item = $this->sanitizeItemForStoring($asset, $editingAsset);
|
||||
|
||||
// The location id fetched by the csv reader is actually the rtd_location_id.
|
||||
// This will also set location_id, but then that will be overridden by the
|
||||
// checkout method if necessary below.
|
||||
@@ -113,16 +122,42 @@ class AssetImporter extends ItemImporter
|
||||
$item['rtd_location_id'] = $this->item['location_id'];
|
||||
}
|
||||
|
||||
$item['last_audit_date'] = null;
|
||||
if (isset($this->item['last_audit_date'])) {
|
||||
$item['last_audit_date'] = $this->item['last_audit_date'];
|
||||
|
||||
/**
|
||||
* We use this to backdate the checkin action further down
|
||||
*/
|
||||
$checkin_date = date('Y-m-d H:i:s');
|
||||
if ($this->item['last_checkin']!='') {
|
||||
$item['last_checkin'] = $this->parseOrNullDate('last_checkin', 'datetime');
|
||||
$checkout_date = $this->item['last_checkin'];
|
||||
}
|
||||
|
||||
$item['next_audit_date'] = null;
|
||||
if (isset($this->item['next_audit_date'])) {
|
||||
$item['next_audit_date'] = $this->item['next_audit_date'];
|
||||
/**
|
||||
* We use this to backdate the checkout action further down
|
||||
*/
|
||||
$checkout_date = date('Y-m-d H:i:s');
|
||||
if ($this->item['last_checkout']!='') {
|
||||
$item['last_checkout'] = $this->parseOrNullDate('last_checkout', 'datetime');
|
||||
$checkout_date = $this->item['last_checkout'];
|
||||
}
|
||||
|
||||
|
||||
if ($this->item['expected_checkin']!='') {
|
||||
$item['expected_checkin'] = $this->parseOrNullDate('expected_checkin');
|
||||
}
|
||||
|
||||
if ($this->item['last_audit_date']!='') {
|
||||
$item['last_audit_date'] = $this->parseOrNullDate('last_audit_date');
|
||||
}
|
||||
|
||||
if ($this->item['next_audit_date']!='') {
|
||||
$item['next_audit_date'] = $this->parseOrNullDate('next_audit_date');
|
||||
}
|
||||
|
||||
if ($this->item['asset_eol_date']!='') {
|
||||
$item['asset_eol_date'] = $this->parseOrNullDate('asset_eol_date');
|
||||
}
|
||||
|
||||
|
||||
if ($editingAsset) {
|
||||
$asset->update($item);
|
||||
} else {
|
||||
@@ -135,27 +170,31 @@ class AssetImporter extends ItemImporter
|
||||
$asset->{$custom_field} = $val;
|
||||
}
|
||||
}
|
||||
|
||||
// This sets an attribute on the Loggable trait for the action log
|
||||
$asset->setImported(true);
|
||||
|
||||
if ($asset->save()) {
|
||||
|
||||
$this->log('Asset '.$this->item['name'].' with serial number '.$this->item['serial'].' was created');
|
||||
|
||||
// If we have a target to checkout to, lets do so.
|
||||
//-- user_id is a property of the abstract class Importer, which this class inherits from and it's setted by
|
||||
//-- user_id is a property of the abstract class Importer, which this class inherits from and it's set by
|
||||
//-- the class that needs to use it (command importer or GUI importer inside the project).
|
||||
if (isset($target) && ($target !== false)) {
|
||||
if (!is_null($asset->assigned_to)){
|
||||
if ($asset->assigned_to != $target->id){
|
||||
event(new CheckoutableCheckedIn($asset, User::find($asset->assigned_to), Auth::user(), $asset->notes, date('Y-m-d H:i:s')));
|
||||
if ($asset->assigned_to != $target->id) {
|
||||
event(new CheckoutableCheckedIn($asset, User::find($asset->assigned_to), Auth::user(), 'Checkin from CSV Importer', $checkin_date));
|
||||
}
|
||||
}
|
||||
|
||||
$asset->fresh()->checkOut($target, $this->user_id, date('Y-m-d H:i:s'), null, $asset->notes, $asset->name);
|
||||
$asset->fresh()->checkOut($target, $this->user_id, $checkout_date, null, 'Checkout from CSV Importer', $asset->name);
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
$this->logError($asset, 'Asset "'.$this->item['name'].'"');
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ use App\Models\CustomField;
|
||||
use App\Models\Department;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use Carbon\CarbonImmutable;
|
||||
use ForceUTF8\Encoding;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
@@ -551,4 +552,35 @@ abstract class Importer
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Parse a date or return null
|
||||
*
|
||||
* @author A. Gianotto
|
||||
* @since 7.0.0
|
||||
* @param $field
|
||||
* @param $format
|
||||
* @return string|null
|
||||
|
||||
*/
|
||||
public function parseOrNullDate($field, $format = 'date') {
|
||||
|
||||
$date_format = 'Y-m-d';
|
||||
|
||||
if ($format == 'datetime') {
|
||||
$date_format = 'Y-m-d H:i:s';
|
||||
}
|
||||
|
||||
if (array_key_exists($field, $this->item) && $this->item[$field] != '') {
|
||||
|
||||
try {
|
||||
$value = CarbonImmutable::parse($this->item[$field])->format($date_format);
|
||||
return $value;
|
||||
} catch (\Exception $e) {
|
||||
$this->log('Unable to parse date: ' . $this->item[$field]);
|
||||
return null;
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -79,26 +79,18 @@ class ItemImporter extends Importer
|
||||
$this->item['purchase_date'] = date('Y-m-d', strtotime($this->findCsvMatch($row, 'purchase_date')));
|
||||
}
|
||||
|
||||
$this->item['last_audit_date'] = null;
|
||||
if ($this->findCsvMatch($row, 'last_audit_date') != '') {
|
||||
$this->item['last_audit_date'] = date('Y-m-d', strtotime($this->findCsvMatch($row, 'last_audit_date')));
|
||||
}
|
||||
// $this->item['asset_eol_date'] = null;
|
||||
// if ($this->findCsvMatch($row, 'asset_eol_date') != '') {
|
||||
// $csvMatch = $this->findCsvMatch($row, 'asset_eol_date');
|
||||
// \Log::warning('EOL Date for $csvMatch is '.$csvMatch);
|
||||
// try {
|
||||
// $this->item['asset_eol_date'] = CarbonImmutable::parse($csvMatch)->format('Y-m-d');
|
||||
// } catch (\Exception $e) {
|
||||
// Log::info($e->getMessage());
|
||||
// $this->log('Unable to parse date: '.$csvMatch);
|
||||
// }
|
||||
// }
|
||||
|
||||
$this->item['next_audit_date'] = null;
|
||||
if ($this->findCsvMatch($row, 'next_audit_date') != '') {
|
||||
$this->item['next_audit_date'] = date('Y-m-d', strtotime($this->findCsvMatch($row, 'next_audit_date')));
|
||||
}
|
||||
|
||||
$this->item['asset_eol_date'] = null;
|
||||
if($this->findCsvMatch($row, 'asset_eol_date') != '') {
|
||||
$csvMatch = $this->findCsvMatch($row, 'asset_eol_date');
|
||||
try {
|
||||
$this->item['asset_eol_date'] = CarbonImmutable::parse($csvMatch)->format('Y-m-d');
|
||||
} catch (\Exception $e) {
|
||||
Log::info($e->getMessage());
|
||||
$this->log('Unable to parse date: '.$csvMatch);
|
||||
}
|
||||
}
|
||||
|
||||
$this->item['qty'] = $this->findCsvMatch($row, 'quantity');
|
||||
$this->item['requestable'] = $this->findCsvMatch($row, 'requestable');
|
||||
@@ -389,7 +381,6 @@ class ItemImporter extends Importer
|
||||
|
||||
if ($status->save()) {
|
||||
$this->log('Status '.$asset_statuslabel_name.' was created');
|
||||
|
||||
return $status->id;
|
||||
}
|
||||
|
||||
@@ -509,4 +500,5 @@ class ItemImporter extends Importer
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -111,7 +111,7 @@ class LogListener
|
||||
$logaction->target_type = User::class;
|
||||
$logaction->action_type = 'merged';
|
||||
$logaction->note = trans('general.merged_log_this_user_from', $to_from_array);
|
||||
$logaction->user_id = $event->admin->id;
|
||||
$logaction->user_id = $event->admin->id ?? null;
|
||||
$logaction->save();
|
||||
|
||||
// Add a record to the users being merged TO
|
||||
@@ -122,7 +122,7 @@ class LogListener
|
||||
$logaction->item_type = User::class;
|
||||
$logaction->action_type = 'merged';
|
||||
$logaction->note = trans('general.merged_log_this_user_into', $to_from_array);
|
||||
$logaction->user_id = $event->admin->id;
|
||||
$logaction->user_id = $event->admin->id ?? null;
|
||||
$logaction->save();
|
||||
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
namespace App\Livewire;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
+1
-1
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
namespace App\Livewire;
|
||||
|
||||
use Livewire\Component;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
namespace App\Livewire;
|
||||
|
||||
use App\Models\CustomField;
|
||||
use Livewire\Component;
|
||||
@@ -8,7 +8,6 @@ use Livewire\Component;
|
||||
use App\Models\Import;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Foundation\Auth\Access\AuthorizesRequests;
|
||||
|
||||
|
||||
@@ -60,7 +59,7 @@ class Importer extends Component
|
||||
];
|
||||
|
||||
/**
|
||||
* This is used in resources/views/livewire/importer.blade.php, and we kinda shouldn't need to check for
|
||||
* This is used in resources/views/livewire.importer.blade.php, and we kinda shouldn't need to check for
|
||||
* activeFile here, but there's some UI goofiness that allows this to crash out on some imports.
|
||||
*
|
||||
* @return string
|
||||
@@ -119,8 +118,7 @@ class Importer extends Component
|
||||
public function updating($name, $new_import_type)
|
||||
{
|
||||
if ($name == "activeFile.import_type") {
|
||||
Log::debug("WE ARE CHANGING THE import_type!!!!! TO: " . $new_import_type);
|
||||
Log::debug("so, what's \$this->>field_map at?: " . print_r($this->field_map, true));
|
||||
|
||||
// go through each header, find a matching field to try and map it to.
|
||||
foreach ($this->activeFile->header_row as $i => $header) {
|
||||
// do we have something mapped already?
|
||||
@@ -237,6 +235,15 @@ class Importer extends Component
|
||||
'email' => trans('general.importer.checked_out_to_email'),
|
||||
'username' => trans('general.importer.checked_out_to_username'),
|
||||
'checkout_location' => trans('general.importer.checkout_location'),
|
||||
/**
|
||||
* These are here so users can import history, to replace the dinosaur that
|
||||
* was the history importer
|
||||
*/
|
||||
'last_checkin' => trans('admin/hardware/table.last_checkin_date'),
|
||||
'last_checkout' => trans('admin/hardware/table.checkout_date'),
|
||||
'expected_checkin' => trans('admin/hardware/form.expected_checkin'),
|
||||
'last_audit_date' => trans('general.last_audit'),
|
||||
'next_audit_date' => trans('general.next_audit_date'),
|
||||
];
|
||||
|
||||
$this->consumables_fields = [
|
||||
@@ -380,6 +387,12 @@ class Importer extends Component
|
||||
'job title for user',
|
||||
'job title',
|
||||
],
|
||||
'full_name' =>
|
||||
[
|
||||
'full name',
|
||||
'fullname',
|
||||
trans('general.importer.checked_out_to_fullname')
|
||||
],
|
||||
'username' =>
|
||||
[
|
||||
'user name',
|
||||
@@ -412,6 +425,7 @@ class Importer extends Component
|
||||
'telephone',
|
||||
'tel.',
|
||||
],
|
||||
|
||||
'serial' =>
|
||||
[
|
||||
'serial number',
|
||||
@@ -456,6 +470,12 @@ class Importer extends Component
|
||||
[
|
||||
'Next Audit',
|
||||
],
|
||||
'last_checkout' =>
|
||||
[
|
||||
'Last Checkout',
|
||||
'Last Checkout Date',
|
||||
'Checkout Date',
|
||||
],
|
||||
'address2' =>
|
||||
[
|
||||
'Address 2',
|
||||
@@ -523,9 +543,8 @@ class Importer extends Component
|
||||
{
|
||||
// TODO: why don't we just do File::find($id)? This seems dumb.
|
||||
foreach($this->files as $file) {
|
||||
Log::debug("File id is: ".$file->id);
|
||||
if($id == $file->id) {
|
||||
if(Storage::delete('private_uploads/imports/'.$file->file_path)) {
|
||||
if ($id == $file->id) {
|
||||
if (Storage::delete('private_uploads/imports/'.$file->file_path)) {
|
||||
$file->delete();
|
||||
|
||||
$this->message = trans('admin/hardware/message.import.file_delete_success');
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
namespace App\Livewire;
|
||||
|
||||
use Illuminate\Support\Facades\Http;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -19,21 +19,11 @@ class OauthClients extends Component
|
||||
|
||||
public $authorizationError;
|
||||
|
||||
protected $clientRepository;
|
||||
protected $tokenRepository;
|
||||
|
||||
public function __construct()
|
||||
{
|
||||
$this->clientRepository = app(ClientRepository::class);
|
||||
$this->tokenRepository = app(TokenRepository::class);
|
||||
parent::__construct();
|
||||
}
|
||||
|
||||
public function render()
|
||||
{
|
||||
return view('livewire.oauth-clients', [
|
||||
'clients' => $this->clientRepository->activeForUser(auth()->user()->id),
|
||||
'authorized_tokens' => $this->tokenRepository->forUser(auth()->user()->id)->where('revoked', false),
|
||||
'clients' => app(ClientRepository::class)->activeForUser(auth()->user()->id),
|
||||
'authorized_tokens' => app(TokenRepository::class)->forUser(auth()->user()->id)->where('revoked', false),
|
||||
]);
|
||||
}
|
||||
|
||||
@@ -44,13 +34,13 @@ class OauthClients extends Component
|
||||
'redirect' => 'required|url|max:255',
|
||||
]);
|
||||
|
||||
$newClient = $this->clientRepository->create(
|
||||
app(ClientRepository::class)->create(
|
||||
auth()->user()->id,
|
||||
$this->name,
|
||||
$this->redirect,
|
||||
);
|
||||
|
||||
$this->dispatchBrowserEvent('clientCreated');
|
||||
$this->dispatch('clientCreated');
|
||||
}
|
||||
|
||||
public function deleteClient(Client $clientId): void
|
||||
@@ -58,7 +48,7 @@ class OauthClients extends Component
|
||||
// test for safety
|
||||
// ->delete must be of type Client - thus the model binding
|
||||
if ($clientId->user_id == auth()->user()->id) {
|
||||
$this->clientRepository->delete($clientId);
|
||||
app(ClientRepository::class)->delete($clientId);
|
||||
} else {
|
||||
Log::warning('User ' . auth()->user()->id . ' attempted to delete client ' . $clientId->id . ' which belongs to user ' . $clientId->user_id);
|
||||
$this->authorizationError = 'You are not authorized to delete this client.';
|
||||
@@ -67,9 +57,9 @@ class OauthClients extends Component
|
||||
|
||||
public function deleteToken($tokenId): void
|
||||
{
|
||||
$token = $this->tokenRepository->find($tokenId);
|
||||
$token = app(TokenRepository::class)->find($tokenId);
|
||||
if ($token->user_id == auth()->user()->id) {
|
||||
$this->tokenRepository->revokeAccessToken($tokenId);
|
||||
app(TokenRepository::class)->revokeAccessToken($tokenId);
|
||||
} else {
|
||||
Log::warning('User ' . auth()->user()->id . ' attempted to delete token ' . $tokenId . ' which belongs to user ' . $token->user_id);
|
||||
$this->authorizationError = 'You are not authorized to delete this token.';
|
||||
@@ -83,7 +73,7 @@ class OauthClients extends Component
|
||||
|
||||
$this->editClientId = $editClientId->id;
|
||||
|
||||
$this->dispatchBrowserEvent('editClient');
|
||||
$this->dispatch('editClient');
|
||||
}
|
||||
|
||||
public function updateClient(Client $editClientId): void
|
||||
@@ -93,7 +83,7 @@ class OauthClients extends Component
|
||||
'editRedirect' => 'required|url|max:255',
|
||||
]);
|
||||
|
||||
$client = $this->clientRepository->find($editClientId->id);
|
||||
$client = app(ClientRepository::class)->find($editClientId->id);
|
||||
if ($client->user_id == auth()->user()->id) {
|
||||
$client->name = $this->editName;
|
||||
$client->redirect = $this->editRedirect;
|
||||
@@ -103,7 +93,7 @@ class OauthClients extends Component
|
||||
$this->authorizationError = 'You are not authorized to edit this client.';
|
||||
}
|
||||
|
||||
$this->dispatchBrowserEvent('clientUpdated');
|
||||
$this->dispatch('clientUpdated');
|
||||
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
namespace App\Livewire;
|
||||
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
@@ -17,7 +17,7 @@ class PersonalAccessTokens extends Component
|
||||
//this is just an annoying thing to make the modal input autofocus
|
||||
public function autoFocusModalEvent(): void
|
||||
{
|
||||
$this->dispatchBrowserEvent('autoFocusModal');
|
||||
$this->dispatch('autoFocusModal');
|
||||
}
|
||||
|
||||
public function render()
|
||||
@@ -42,13 +42,13 @@ class PersonalAccessTokens extends Component
|
||||
|
||||
$this->newTokenString = $newToken->accessToken;
|
||||
|
||||
$this->dispatchBrowserEvent('tokenCreated', $newToken->accessToken);
|
||||
$this->dispatch('tokenCreated', token: $newToken->accessToken);
|
||||
}
|
||||
|
||||
public function deleteToken($tokenId): void
|
||||
{
|
||||
//this needs safety (though the scope of auth::user might kind of do it...)
|
||||
//seems like it does, test more
|
||||
Auth::user()->tokens()->find($tokenId)->delete();
|
||||
Auth::user()->tokens()->find($tokenId)?->delete();
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Livewire;
|
||||
namespace App\Livewire;
|
||||
|
||||
use GuzzleHttp\Client;
|
||||
use Illuminate\Support\Facades\Http;
|
||||
@@ -23,15 +23,17 @@ class SlackSettingsForm extends Component
|
||||
|
||||
public Setting $setting;
|
||||
|
||||
public $save_button;
|
||||
|
||||
public $webhook_test;
|
||||
|
||||
public $webhook_endpoint_rules;
|
||||
|
||||
|
||||
protected $rules = [
|
||||
'webhook_endpoint' => 'required_with:webhook_channel|starts_with:http://,https://,ftp://,irc://,https://hooks.slack.com/services/|url|nullable',
|
||||
'webhook_channel' => 'required_with:webhook_endpoint|starts_with:#|nullable',
|
||||
'webhook_botname' => 'string|nullable',
|
||||
];
|
||||
|
||||
|
||||
|
||||
public function mount() {
|
||||
$this->webhook_text= [
|
||||
+112
-25
@@ -10,15 +10,19 @@ use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Traits\Acceptable;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use AssetPresenter;
|
||||
use App\Presenters\AssetPresenter;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Support\Facades\Crypt;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use Illuminate\Database\Eloquent\Casts\Attribute;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
|
||||
/**
|
||||
* Model for Assets.
|
||||
@@ -28,7 +32,7 @@ use Watson\Validating\ValidatingTrait;
|
||||
class Asset extends Depreciable
|
||||
{
|
||||
|
||||
protected $presenter = \App\Presenters\AssetPresenter::class;
|
||||
protected $presenter = AssetPresenter::class;
|
||||
|
||||
use CompanyableTrait;
|
||||
use HasFactory, Loggable, Requestable, Presentable, SoftDeletes, ValidatingTrait, UniqueUndeletedTrait;
|
||||
@@ -60,6 +64,12 @@ class Asset extends Depreciable
|
||||
*/
|
||||
protected $table = 'assets';
|
||||
|
||||
/**
|
||||
* Leaving this commented out, since we need to test further, but this would eager load the model relationship every single
|
||||
* time the asset model is loaded.
|
||||
*/
|
||||
// protected $with = ['model'];
|
||||
|
||||
/**
|
||||
* Whether the model should inject it's identifier to the unique
|
||||
* validation rules before attempting validation. If this property
|
||||
@@ -145,31 +155,33 @@ class Asset extends Depreciable
|
||||
'expected_checkin',
|
||||
'byod',
|
||||
'asset_eol_date',
|
||||
'eol_explicit',
|
||||
'eol_explicit',
|
||||
'last_audit_date',
|
||||
'next_audit_date',
|
||||
'asset_eol_date',
|
||||
'last_checkin',
|
||||
'last_checkout',
|
||||
];
|
||||
|
||||
use Searchable;
|
||||
|
||||
/**
|
||||
* The attributes that should be included when searching the model.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableAttributes = [
|
||||
'name',
|
||||
'asset_tag',
|
||||
'serial',
|
||||
'order_number',
|
||||
'purchase_cost',
|
||||
'notes',
|
||||
'name',
|
||||
'asset_tag',
|
||||
'serial',
|
||||
'order_number',
|
||||
'purchase_cost',
|
||||
'notes',
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'purchase_date',
|
||||
'expected_checkin',
|
||||
'next_audit_date',
|
||||
'updated_at',
|
||||
'purchase_date',
|
||||
'expected_checkin',
|
||||
'next_audit_date',
|
||||
'last_audit_date',
|
||||
'last_checkin',
|
||||
'last_checkout',
|
||||
@@ -178,7 +190,7 @@ class Asset extends Depreciable
|
||||
|
||||
/**
|
||||
* The relations and their attributes that should be included when searching the model.
|
||||
*
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $searchableRelations = [
|
||||
@@ -291,7 +303,7 @@ class Asset extends Depreciable
|
||||
|
||||
// The asset status is not archived and is deployable
|
||||
if (($this->assetstatus) && ($this->assetstatus->archived == '0')
|
||||
&& ($this->assetstatus->deployable == '1'))
|
||||
&& ($this->assetstatus->deployable == '1'))
|
||||
{
|
||||
return true;
|
||||
|
||||
@@ -564,7 +576,7 @@ class Asset extends Depreciable
|
||||
*/
|
||||
public function assignedType()
|
||||
{
|
||||
return strtolower(class_basename($this->assigned_type));
|
||||
return $this->assigned_type ? strtolower(class_basename($this->assigned_type)) : null;
|
||||
}
|
||||
|
||||
|
||||
@@ -848,11 +860,11 @@ class Asset extends Depreciable
|
||||
foreach ($assets as $asset) {
|
||||
$results = preg_match("/\d+$/", $asset['asset_tag'], $matches);
|
||||
|
||||
if ($results)
|
||||
if ($results)
|
||||
{
|
||||
$number = $matches[0];
|
||||
|
||||
if ($number > $max)
|
||||
if ($number > $max)
|
||||
{
|
||||
$max = $number;
|
||||
}
|
||||
@@ -956,6 +968,46 @@ class Asset extends Depreciable
|
||||
return $cost;
|
||||
}
|
||||
|
||||
public function handleCustomFieldsForStoring($request) : Asset
|
||||
{
|
||||
$model = AssetModel::find($this->model_id);
|
||||
|
||||
if (($model) && ($model instanceof AssetModel) && ($model->fieldset)) {
|
||||
|
||||
foreach ($model->fieldset->fields as $field) {
|
||||
|
||||
/*
|
||||
* Check if the decrypted existing value is different from one we just submitted
|
||||
* and if not, pull it out of the object since it shouldn't really be updating at all.
|
||||
* If we don't do this, it will try to re-encrypt it, and the same value encrypted two
|
||||
* different times will have different values, so it will *look* like it was updated
|
||||
* but it wasn't.
|
||||
*/
|
||||
if ($request->input($field->db_column)!='') {
|
||||
|
||||
if ($field->field_encrypted == '1') {
|
||||
if (Gate::allows('admin')) {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$this->{$field->db_column} = Crypt::encrypt(implode(', ', $request->input($field->db_column)));
|
||||
} else {
|
||||
$this->{$field->db_column} = Crypt::encrypt($request->input($field->db_column));
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
if (is_array($request->input($field->db_column))) {
|
||||
$this->{$field->db_column} = implode(', ', $request->input($field->db_column));
|
||||
} else {
|
||||
$this->{$field->db_column} = $request->input($field->db_column);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return $this;
|
||||
}
|
||||
|
||||
/**
|
||||
* -----------------------------------------------
|
||||
* BEGIN MUTATORS
|
||||
@@ -971,14 +1023,45 @@ class Asset extends Depreciable
|
||||
* @param $value
|
||||
* @return void
|
||||
*/
|
||||
public function getNextAuditDateAttribute($value)
|
||||
|
||||
protected function nextAuditDate(): Attribute
|
||||
{
|
||||
return $this->attributes['next_audit_date'] = $value ? Carbon::parse($value)->format('Y-m-d') : null;
|
||||
return Attribute::make(
|
||||
get: fn ($value) => $value ? Carbon::parse($value)->format('Y-m-d') : null,
|
||||
set: fn ($value) => $value ? Carbon::parse($value)->format('Y-m-d') : null,
|
||||
);
|
||||
}
|
||||
|
||||
public function setNextAuditDateAttribute($value)
|
||||
protected function lastAuditDate(): Attribute
|
||||
{
|
||||
$this->attributes['next_audit_date'] = $value ? Carbon::parse($value)->format('Y-m-d') : null;
|
||||
return Attribute::make(
|
||||
get: fn ($value) => $value ? Carbon::parse($value)->format('Y-m-d H:i:s') : null,
|
||||
set: fn ($value) => $value ? Carbon::parse($value)->format('Y-m-d H:i:s') : null,
|
||||
);
|
||||
}
|
||||
|
||||
protected function lastCheckout(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn ($value) => $value ? Carbon::parse($value)->format('Y-m-d H:i:s') : null,
|
||||
set: fn ($value) => $value ? Carbon::parse($value)->format('Y-m-d H:i:s') : null,
|
||||
);
|
||||
}
|
||||
|
||||
protected function lastCheckin(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn ($value) => $value ? Carbon::parse($value)->format('Y-m-d H:i:s') : null,
|
||||
set: fn ($value) => $value ? Carbon::parse($value)->format('Y-m-d H:i:s') : null,
|
||||
);
|
||||
}
|
||||
|
||||
protected function assetEolDate(): Attribute
|
||||
{
|
||||
return Attribute::make(
|
||||
get: fn ($value) => $value ? Carbon::parse($value)->format('Y-m-d') : null,
|
||||
set: fn ($value) => $value ? Carbon::parse($value)->format('Y-m-d') : null,
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -990,9 +1073,13 @@ class Asset extends Depreciable
|
||||
* @param $value
|
||||
* @return void
|
||||
*/
|
||||
public function setRequestableAttribute($value)
|
||||
|
||||
protected function requestable(): Attribute
|
||||
{
|
||||
$this->attributes['requestable'] = (int) filter_var($value, FILTER_VALIDATE_BOOLEAN);
|
||||
return Attribute::make(
|
||||
get: fn ($value) => (int) filter_var($value, FILTER_VALIDATE_BOOLEAN),
|
||||
set: fn ($value) => (int) filter_var($value, FILTER_VALIDATE_BOOLEAN),
|
||||
);
|
||||
}
|
||||
|
||||
|
||||
|
||||
+16
-12
@@ -5,11 +5,11 @@ namespace App\Models;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
/**
|
||||
* Model for Companies.
|
||||
*
|
||||
@@ -147,7 +147,7 @@ final class Company extends SnipeModel
|
||||
// This is primary for the gate:allows-check in location->isDeletable()
|
||||
// Locations don't have a company_id so without this it isn't possible to delete locations with FullMultipleCompanySupport enabled
|
||||
// because this function is called by SnipePermissionsPolicy->before()
|
||||
if (!$companyable instanceof Company && !\Schema::hasColumn($company_table, 'company_id')) {
|
||||
if (!$companyable instanceof Company && !Schema::hasColumn($company_table, 'company_id')) {
|
||||
return true;
|
||||
}
|
||||
|
||||
@@ -259,7 +259,7 @@ final class Company extends SnipeModel
|
||||
public static function scopeCompanyables($query, $column = 'company_id', $table_name = null)
|
||||
{
|
||||
// If not logged in and hitting this, assume we are on the command line and don't scope?'
|
||||
if (! static::isFullMultipleCompanySupportEnabled() || (Auth::check() && Auth::user()->isSuperUser()) || (! Auth::check())) {
|
||||
if (! static::isFullMultipleCompanySupportEnabled() || (Auth::hasUser() && Auth::user()->isSuperUser()) || (! Auth::hasUser())) {
|
||||
return $query;
|
||||
} else {
|
||||
return static::scopeCompanyablesDirectly($query, $column, $table_name);
|
||||
@@ -267,27 +267,31 @@ final class Company extends SnipeModel
|
||||
}
|
||||
|
||||
/**
|
||||
* Scoping table queries, determining if a logged in user is part of a company, and only allows
|
||||
* Scoping table queries, determining if a logged-in user is part of a company, and only allows
|
||||
* that user to see items associated with that company
|
||||
*
|
||||
* @see https://github.com/laravel/framework/pull/24518 for info on Auth::hasUser()
|
||||
*/
|
||||
private static function scopeCompanyablesDirectly($query, $column = 'company_id', $table_name = null)
|
||||
{
|
||||
// Get the company ID of the logged in user, or set it to null if there is no company assicoated with the user
|
||||
if (Auth::user()) {
|
||||
|
||||
// Get the company ID of the logged-in user, or set it to null if there is no company associated with the user
|
||||
if (Auth::hasUser()) {
|
||||
$company_id = Auth::user()->company_id;
|
||||
} else {
|
||||
$company_id = null;
|
||||
}
|
||||
|
||||
// Dynamically get the table name if it's not passed in, based on the model we're querying against
|
||||
$table = ($table_name) ? $table_name."." : $query->getModel()->getTable().".";
|
||||
|
||||
// If the column exists in the table, use it to scope the query
|
||||
if (\Schema::hasColumn($query->getModel()->getTable(), $column)) {
|
||||
if ((($query) && ($query->getModel()) && (Schema::hasColumn($query->getModel()->getTable(), $column)))) {
|
||||
|
||||
// Dynamically get the table name if it's not passed in, based on the model we're querying against
|
||||
$table = ($table_name) ? $table_name."." : $query->getModel()->getTable().".";
|
||||
|
||||
return $query->where($table.$column, '=', $company_id);
|
||||
} else {
|
||||
return $query->join('users as users_comp', 'users_comp.id', 'user_id')->where('users_comp.company_id', '=', $company_id);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -305,7 +309,7 @@ final class Company extends SnipeModel
|
||||
|
||||
if (count($companyable_names) == 0) {
|
||||
throw new Exception('No Companyable Children to scope');
|
||||
} elseif (! static::isFullMultipleCompanySupportEnabled() || (Auth::check() && Auth::user()->isSuperUser())) {
|
||||
} elseif (! static::isFullMultipleCompanySupportEnabled() || (Auth::hasUser() && Auth::user()->isSuperUser())) {
|
||||
return $query;
|
||||
} else {
|
||||
$f = function ($q) {
|
||||
|
||||
@@ -173,10 +173,14 @@ class Depreciable extends SnipeModel
|
||||
|
||||
public function depreciated_date()
|
||||
{
|
||||
$date = date_create($this->purchase_date);
|
||||
date_add($date, date_interval_create_from_date_string($this->get_depreciation()->months.' months'));
|
||||
if (($this->purchase_date) && ($this->get_depreciation())) {
|
||||
$date = date_create($this->purchase_date);
|
||||
|
||||
return date_add($date, date_interval_create_from_date_string($this->get_depreciation()->months.' months'));//date_format($date, 'Y-m-d'); //don't bake-in format, for internationalization
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
return $date; //date_format($date, 'Y-m-d'); //don't bake-in format, for internationalization
|
||||
}
|
||||
|
||||
// it's necessary for unit tests
|
||||
|
||||
@@ -25,6 +25,17 @@ abstract class Label
|
||||
*/
|
||||
public abstract function getUnit();
|
||||
|
||||
/**
|
||||
* Returns the PDF rotation.
|
||||
* 0, 90, 180, 270
|
||||
* 0 is a sane default. Override when necessary.
|
||||
*
|
||||
* @return int
|
||||
*/
|
||||
public function getRotation() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the label's width in getUnit() units
|
||||
*
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Labels\Tapes\Brother;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Labels\Label;
|
||||
|
||||
/*
|
||||
* Rotated Label (print direction = landscape) for 62mm wide labels
|
||||
*/
|
||||
abstract class TZe_62mm_Landscape extends Label
|
||||
{
|
||||
private const WIDTH = 62.00;
|
||||
private const MARGIN_SIDES = 1.50;
|
||||
private const MARGIN_ENDS = 1.50;
|
||||
|
||||
public function getWidth() { return Helper::convertUnit(self::WIDTH, 'mm', $this->getUnit()); }
|
||||
public function getMarginTop() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit()); }
|
||||
public function getMarginBottom() { return Helper::convertUnit(self::MARGIN_SIDES, 'mm', $this->getUnit());}
|
||||
public function getMarginLeft() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
|
||||
public function getMarginRight() { return Helper::convertUnit(self::MARGIN_ENDS, 'mm', $this->getUnit()); }
|
||||
public function getRotation() { return 90; }
|
||||
}
|
||||
@@ -0,0 +1,106 @@
|
||||
<?php
|
||||
|
||||
namespace App\Models\Labels\Tapes\Brother;
|
||||
|
||||
class TZe_62mm_Landscape_A extends TZe_62mm_Landscape
|
||||
{
|
||||
public function getUnit() { return 'mm'; }
|
||||
public function getHeight() { return 31.50; }
|
||||
public function getSupportAssetTag() { return true; }
|
||||
public function getSupport1DBarcode() { return true; }
|
||||
public function getSupport2DBarcode() { return true; }
|
||||
public function getSupportFields() { return 2; }
|
||||
public function getSupportLogo() { return true; }
|
||||
public function getSupportTitle() { return true; }
|
||||
|
||||
private const BARCODE1D_HEIGHT = 3.00;
|
||||
private const BARCODE1D_MARGIN = 3.00;
|
||||
private const BARCODE2D_SIZE = 20.00;
|
||||
private const BARCODE2D_MARGIN = 1.50;
|
||||
private const TAG_SIZE = 3.00;
|
||||
private const LOGO_HEIGHT = 10.00;
|
||||
private const LOGO_MARGIN = 1.50;
|
||||
private const TITLE_SIZE = 3.00;
|
||||
private const TITLE_MARGIN = 0.50;
|
||||
private const LABEL_SIZE = 2.00;
|
||||
private const LABEL_MARGIN = - 0.35;
|
||||
private const FIELD_SIZE = 3.00;
|
||||
private const FIELD_MARGIN = 0.10;
|
||||
|
||||
public function preparePDF($pdf) {}
|
||||
|
||||
public function write($pdf, $record) {
|
||||
$pa = $this->getPrintableArea();
|
||||
|
||||
$currentX = $pa->x1;
|
||||
$currentY = $pa->y1;
|
||||
|
||||
// Wide 1D barcode on top
|
||||
|
||||
if ($record->has('barcode1d')) {
|
||||
static::write1DBarcode(
|
||||
$pdf, $record->get('barcode1d')->content, $record->get('barcode1d')->type,
|
||||
$currentX, $currentY, $pa->w, self::BARCODE1D_HEIGHT
|
||||
);
|
||||
$currentY = self::BARCODE1D_HEIGHT + self::BARCODE1D_MARGIN;
|
||||
}
|
||||
|
||||
// Left column
|
||||
|
||||
if ($record->has('barcode2d')) {
|
||||
$columnY = $currentY;
|
||||
static::write2DBarcode(
|
||||
$pdf, $record->get('barcode2d')->content, $record->get('barcode2d')->type,
|
||||
$currentX, $columnY,
|
||||
self::BARCODE2D_SIZE, self::BARCODE2D_SIZE
|
||||
);
|
||||
$columnY += self::BARCODE2D_SIZE + self::BARCODE2D_MARGIN;
|
||||
static::writeText(
|
||||
$pdf, $record->get('tag'),
|
||||
$currentX, $columnY,
|
||||
'freemono', 'b', self::TAG_SIZE, 'C',
|
||||
self::BARCODE2D_SIZE, self::TAG_SIZE, true, 0
|
||||
);
|
||||
$currentX += self::BARCODE2D_SIZE + self::BARCODE2D_MARGIN;
|
||||
}
|
||||
|
||||
// Right column
|
||||
if ($record->get('logo')) {
|
||||
static::writeImage(
|
||||
$pdf, $record->get('logo'),
|
||||
$currentX, $currentY,
|
||||
$pa->w - $currentX, self::LOGO_HEIGHT,
|
||||
'L', 'T', 300, true, false, 0
|
||||
);
|
||||
$currentY += self::LOGO_HEIGHT + self::LOGO_MARGIN;
|
||||
}
|
||||
|
||||
if ($record->has('title')) {
|
||||
static::writeText(
|
||||
$pdf, $record->get('title'),
|
||||
$currentX, $currentY,
|
||||
'freesans', '', self::TITLE_SIZE, 'L',
|
||||
$pa->w - $currentX, self::TITLE_SIZE, true, 0
|
||||
);
|
||||
$currentY += self::TITLE_SIZE + self::TITLE_MARGIN;
|
||||
}
|
||||
|
||||
foreach ($record->get('fields') as $field) {
|
||||
static::writeText(
|
||||
$pdf, $field['label'],
|
||||
$currentX, $currentY,
|
||||
'freesans', '', self::LABEL_SIZE, 'L',
|
||||
$pa->w - $currentX, self::LABEL_SIZE, true, 0, 0
|
||||
);
|
||||
$currentY += self::LABEL_SIZE + self::LABEL_MARGIN;
|
||||
|
||||
static::writeText(
|
||||
$pdf, $field['value'],
|
||||
$currentX, $currentY,
|
||||
'freemono', 'B', self::FIELD_SIZE, 'L',
|
||||
$pa->w - $currentX, self::FIELD_SIZE, true, 0, 0.3
|
||||
);
|
||||
$currentY += self::FIELD_SIZE + self::FIELD_MARGIN;
|
||||
}
|
||||
}
|
||||
}
|
||||
+46
-15
@@ -5,7 +5,6 @@ namespace App\Models;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
use Illuminate\Auth\Authenticatable;
|
||||
use Illuminate\Auth\Passwords\CanResetPassword;
|
||||
use Illuminate\Contracts\Auth\Access\Authorizable as AuthorizableContract;
|
||||
@@ -24,6 +23,7 @@ use Watson\Validating\ValidatingTrait;
|
||||
class User extends SnipeModel implements AuthenticatableContract, AuthorizableContract, CanResetPasswordContract, HasLocalePreference
|
||||
{
|
||||
use HasFactory;
|
||||
use CompanyableTrait;
|
||||
|
||||
protected $presenter = \App\Presenters\UserPresenter::class;
|
||||
use SoftDeletes, ValidatingTrait;
|
||||
@@ -204,6 +204,23 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
return $this->checkPermissionSection('superuser');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Checks if the can edit their own profile
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v6.3.4]
|
||||
* @return bool
|
||||
*/
|
||||
public function canEditProfile() : bool {
|
||||
|
||||
$setting = Setting::getSettings();
|
||||
if ($setting->profile_edit == 1) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the user is deletable
|
||||
*
|
||||
@@ -464,8 +481,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
/**
|
||||
* Establishes the user -> uploads relationship
|
||||
*
|
||||
* @todo I don't think we use this?
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
@@ -479,6 +494,21 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the user -> acceptances relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v7.0.7]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function acceptances()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Actionlog::class, 'target_id')
|
||||
->where('target_type', self::class)
|
||||
->where('action_type', '=', 'accepted')
|
||||
->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the user -> requested assets relationship
|
||||
*
|
||||
@@ -572,7 +602,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
|
||||
if ($format=='firstname.lastname') {
|
||||
$username = str_slug($first_name) . '.' . str_slug($last_name);
|
||||
|
||||
} elseif ($format == 'lastnamefirstinitial') {
|
||||
$username = str_slug($last_name.substr($first_name, 0, 1));
|
||||
} elseif ($format == 'firstintial.lastname') {
|
||||
@@ -589,7 +618,9 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
$username = str_slug($first_name).str_slug($last_name);
|
||||
} elseif ($format == 'firstnamelastinitial') {
|
||||
$username = str_slug(($first_name.substr($last_name, 0, 1)));
|
||||
}
|
||||
} elseif ($format == 'lastname.firstname') {
|
||||
$username = str_slug($last_name).'.'.str_slug($first_name);
|
||||
}
|
||||
}
|
||||
|
||||
$user['first_name'] = $first_name;
|
||||
@@ -827,16 +858,16 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
|
||||
|
||||
return $query->where('location_id','=', $location)
|
||||
->where('first_name', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('email', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('last_name', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('permissions', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('country', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('phone', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('jobtitle', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('employee_num', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('username', 'LIKE', '%' . $search . '%')
|
||||
->orwhereRaw('CONCAT(first_name," ",last_name) LIKE \''.$search.'%\'');
|
||||
->where('users.first_name', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.email', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.last_name', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.permissions', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.country', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.phone', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.jobtitle', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.employee_num', 'LIKE', '%' . $search . '%')
|
||||
->orWhere('users.username', 'LIKE', '%' . $search . '%')
|
||||
->orwhereRaw('CONCAT(users.first_name," ",users.last_name) LIKE \''.$search.'%\'');
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -92,7 +92,7 @@ class AssetObserver
|
||||
|
||||
// only modify the 'next' one if it's *bigger* than the stored base
|
||||
//
|
||||
if($next_asset_tag > $settings->next_auto_tag_base) {
|
||||
if ($next_asset_tag > $settings->next_auto_tag_base && $next_asset_tag < PHP_INT_MAX) {
|
||||
$settings->next_auto_tag_base = $next_asset_tag;
|
||||
$settings->save();
|
||||
}
|
||||
|
||||
@@ -223,6 +223,7 @@ class UserPresenter extends Presenter
|
||||
'class' => 'css-barcode',
|
||||
'title' => trans('general.assets'),
|
||||
'visible' => true,
|
||||
'formatter' => 'linkNumberToUserAssetsFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'licenses_count',
|
||||
@@ -232,6 +233,7 @@ class UserPresenter extends Presenter
|
||||
'class' => 'css-license',
|
||||
'title' => trans('general.licenses'),
|
||||
'visible' => true,
|
||||
'formatter' => 'linkNumberToUserLicensesFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'consumables_count',
|
||||
@@ -241,6 +243,7 @@ class UserPresenter extends Presenter
|
||||
'class' => 'css-consumable',
|
||||
'title' => trans('general.consumables'),
|
||||
'visible' => true,
|
||||
'formatter' => 'linkNumberToUserConsumablesFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'accessories_count',
|
||||
@@ -250,6 +253,7 @@ class UserPresenter extends Presenter
|
||||
'class' => 'css-accessory',
|
||||
'title' => trans('general.accessories'),
|
||||
'visible' => true,
|
||||
'formatter' => 'linkNumberToUserAccessoriesFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'manages_users_count',
|
||||
@@ -259,6 +263,7 @@ class UserPresenter extends Presenter
|
||||
'class' => 'css-users',
|
||||
'title' => trans('admin/users/table.managed_users'),
|
||||
'visible' => true,
|
||||
'formatter' => 'linkNumberToUserManagedUsersFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'manages_locations_count',
|
||||
@@ -268,6 +273,7 @@ class UserPresenter extends Presenter
|
||||
'class' => 'css-location',
|
||||
'title' => trans('admin/users/table.managed_locations'),
|
||||
'visible' => true,
|
||||
'formatter' => 'linkNumberToUserManagedLocationsFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'notes',
|
||||
@@ -426,6 +432,8 @@ class UserPresenter extends Presenter
|
||||
*/
|
||||
public function gravatar()
|
||||
{
|
||||
|
||||
// User's specific avatar
|
||||
if ($this->avatar) {
|
||||
|
||||
// Check if it's a google avatar or some external avatar
|
||||
@@ -437,6 +445,12 @@ class UserPresenter extends Presenter
|
||||
return Storage::disk('public')->url('avatars/'.e($this->avatar));
|
||||
}
|
||||
|
||||
// If there is a default avatar
|
||||
if (Setting::getSettings()->default_avatar!= '') {
|
||||
return Storage::disk('public')->url('avatars/'.e(Setting::getSettings()->default_avatar));
|
||||
}
|
||||
|
||||
// Fall back to Gravatar if the settings allow loading remote scripts
|
||||
if (Setting::getSettings()->load_remote == '1') {
|
||||
if ($this->model->gravatar != '') {
|
||||
|
||||
@@ -450,8 +464,8 @@ class UserPresenter extends Presenter
|
||||
}
|
||||
}
|
||||
|
||||
// Set a fun, gender-neutral default icon
|
||||
return config('app.url').'/img/default-sm.png';
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -21,6 +21,7 @@ use Illuminate\Routing\UrlGenerator;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
use Illuminate\Support\ServiceProvider;
|
||||
use Illuminate\Support\Facades\Log;
|
||||
use Illuminate\Support\Facades\URL;
|
||||
|
||||
/**
|
||||
* This service provider handles setting the observers on models
|
||||
@@ -31,7 +32,7 @@ use Illuminate\Support\Facades\Log;
|
||||
class AppServiceProvider extends ServiceProvider
|
||||
{
|
||||
/**
|
||||
* Custom email array validation
|
||||
* Bootstrap application services.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
@@ -39,19 +40,24 @@ class AppServiceProvider extends ServiceProvider
|
||||
*/
|
||||
public function boot(UrlGenerator $url)
|
||||
{
|
||||
if (env('APP_FORCE_TLS')) {
|
||||
if (strpos(env('APP_URL'), 'https') === 0) {
|
||||
$url->forceScheme('https');
|
||||
} else {
|
||||
Log::debug("'APP_FORCE_TLS' is set to true, but 'APP_URL' does not start with 'https://'. Will not force TLS on connections.");
|
||||
}
|
||||
/**
|
||||
* This is a workaround for proxies/reverse proxies that don't always pass the proper headers.
|
||||
*
|
||||
* Here, we check if the APP_URL starts with https://, which we should always honor,
|
||||
* regardless of how well the proxy or network is configured.
|
||||
*
|
||||
* We'll force the https scheme if the APP_URL starts with https://, or if APP_FORCE_TLS is set to true.
|
||||
*
|
||||
*/
|
||||
if ((strpos(env('APP_URL'), 'https://') === 0) || (env('APP_FORCE_TLS'))) {
|
||||
$url->forceScheme('https');
|
||||
}
|
||||
|
||||
// TODO - isn't it somehow 'gauche' to check the environment directly; shouldn't we be using config() somehow?
|
||||
if ( ! env('APP_ALLOW_INSECURE_HOSTS')) { // unless you set APP_ALLOW_INSECURE_HOSTS, you should PROHIBIT forging domain parts of URL via Host: headers
|
||||
$url_parts = parse_url(config('app.url'));
|
||||
if ($url_parts && array_key_exists('scheme', $url_parts) && array_key_exists('host', $url_parts)) { // check for the *required* parts of a bare-minimum URL
|
||||
\URL::forceRootUrl(config('app.url'));
|
||||
URL::forceRootUrl(config('app.url'));
|
||||
} else {
|
||||
Log::error("Your APP_URL in your .env is misconfigured - it is: ".config('app.url').". Many things will work strangely unless you fix it.");
|
||||
}
|
||||
|
||||
@@ -232,5 +232,12 @@ class AuthServiceProvider extends ServiceProvider
|
||||
|| $user->can('update', User::class)
|
||||
|| $user->can('create', User::class);
|
||||
});
|
||||
|
||||
|
||||
// This determines whether the user can edit their profile based on the setting in Admin > General
|
||||
Gate::define('self.profile', function ($user) {
|
||||
return $user->canEditProfile();
|
||||
});
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -163,6 +163,7 @@ class Saml
|
||||
OneLogin_Saml2_Utils::setProxyVars(request()->isFromTrustedProxy());
|
||||
|
||||
data_set($settings, 'sp.entityId', config('app.url'));
|
||||
data_set($settings, 'baseurl', config('app.url') . '/saml');
|
||||
data_set($settings, 'sp.assertionConsumerService.url', route('saml.acs'));
|
||||
data_set($settings, 'sp.singleLogoutService.url', route('saml.sls'));
|
||||
data_set($settings, 'sp.x509cert', $setting->saml_sp_x509cert);
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Services;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use Illuminate\Translation\Translator;
|
||||
|
||||
/***************************************************************
|
||||
@@ -17,6 +18,10 @@ use Illuminate\Translation\Translator;
|
||||
***************************************************************/
|
||||
class SnipeTranslator extends Translator {
|
||||
|
||||
static $legacy_translation_namespaces = [
|
||||
"backup::" //Spatie backup uses 'legacy' locale names
|
||||
];
|
||||
|
||||
//This is copied-and-pasted (almost) verbatim from Illuminate\Translation\Translator
|
||||
public function choice($key, $number, array $replace = [], $locale = null)
|
||||
{
|
||||
@@ -39,4 +44,28 @@ class SnipeTranslator extends Translator {
|
||||
);
|
||||
}
|
||||
|
||||
public function get($key, array $replace = [], $locale = null, $fallback = true)
|
||||
{
|
||||
$modified_locale = $locale;
|
||||
$changed_fallback = false;
|
||||
$previous_fallback = $this->fallback;
|
||||
// 'legacy' translation directories tend to be two-char ('en'), not 5-char ('en-US').
|
||||
// Here we try our best to handle that.
|
||||
foreach (self::$legacy_translation_namespaces as $namespace) {
|
||||
if (preg_match("/^$namespace/", $key)) {
|
||||
$modified_locale = Helper::mapBackToLegacyLocale($locale);
|
||||
$changed_fallback = true;
|
||||
$this->fallback = 'en'; //TODO - should this be 'env-able'? Or do we just put our foot down and say 'en'?
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$result = parent::get($key, $replace, $modified_locale, $fallback);
|
||||
if ($changed_fallback) {
|
||||
$this->fallback = $previous_fallback;
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
+1
-1
@@ -54,7 +54,7 @@ class Label implements View
|
||||
$pdf = new TCPDF(
|
||||
$template->getOrientation(),
|
||||
$template->getUnit(),
|
||||
[ $template->getWidth(), $template->getHeight() ]
|
||||
[0 => $template->getWidth(), 1 => $template->getHeight(), 'Rotate' => $template->getRotation()]
|
||||
);
|
||||
|
||||
// Reset parameters
|
||||
|
||||
+8
-8
@@ -26,7 +26,7 @@
|
||||
"alek13/slack": "^2.0",
|
||||
"arietimmerman/laravel-scim-server": "dev-master",
|
||||
"bacon/bacon-qr-code": "^2.0",
|
||||
"barryvdh/laravel-debugbar": "^3.6",
|
||||
"barryvdh/laravel-debugbar": "^3.13",
|
||||
"barryvdh/laravel-dompdf": "^2.0",
|
||||
"doctrine/cache": "^1.10",
|
||||
"doctrine/dbal": "^3.1",
|
||||
@@ -49,7 +49,7 @@
|
||||
"laravelcollective/html": "^6.2",
|
||||
"league/csv": "^9.7",
|
||||
"league/flysystem-aws-s3-v3": "^3.0",
|
||||
"livewire/livewire": "^2.4",
|
||||
"livewire/livewire": "^3.5",
|
||||
"neitanod/forceutf8": "^2.0",
|
||||
"nesbot/carbon": "^2.32",
|
||||
"nunomaduro/collision": "^6.1",
|
||||
@@ -61,7 +61,7 @@
|
||||
"phpspec/prophecy": "^1.10",
|
||||
"pragmarx/google2fa-laravel": "^1.3",
|
||||
"rollbar/rollbar-laravel": "^8.0",
|
||||
"spatie/laravel-backup": "^8.0",
|
||||
"spatie/laravel-backup": "^8.8",
|
||||
"spatie/laravel-ignition": "^2.0",
|
||||
"tecnickcom/tc-lib-barcode": "^1.15",
|
||||
"tecnickcom/tcpdf": "^6.5",
|
||||
@@ -70,17 +70,17 @@
|
||||
},
|
||||
"suggest": {
|
||||
"ext-ldap": "*",
|
||||
"ext-zip": "*"
|
||||
"ext-zip": "*",
|
||||
"ext-exif": "*"
|
||||
},
|
||||
"require-dev": {
|
||||
"brianium/paratest": "^v6.4.4",
|
||||
"fakerphp/faker": "^1.16",
|
||||
"larastan/larastan": "^2.9",
|
||||
"mockery/mockery": "^1.4",
|
||||
"nunomaduro/larastan": "^2.0",
|
||||
"nunomaduro/phpinsights": "^2.7",
|
||||
"php-mock/php-mock-phpunit": "^2.8",
|
||||
"phpunit/php-token-stream": "^3.1",
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"php-mock/php-mock-phpunit": "^2.10",
|
||||
"phpunit/phpunit": "^9.6.19",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
"symfony/css-selector": "^4.4",
|
||||
"symfony/dom-crawler": "^4.4",
|
||||
|
||||
Generated
+1480
-815
File diff suppressed because it is too large
Load Diff
+1
-1
@@ -112,7 +112,7 @@ return [
|
||||
|
|
||||
*/
|
||||
|
||||
'fallback_locale' => 'en-US',
|
||||
'fallback_locale' => env('FALLBACK_APP_LOCALE', 'en-US'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|
||||
+25
-6
@@ -121,12 +121,12 @@ return [
|
||||
'notifications' => [
|
||||
|
||||
'notifications' => [
|
||||
\Spatie\Backup\Notifications\Notifications\BackupHasFailed::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
\Spatie\Backup\Notifications\Notifications\UnhealthyBackupWasFound::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
\Spatie\Backup\Notifications\Notifications\CleanupHasFailed::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
\Spatie\Backup\Notifications\Notifications\BackupWasSuccessful::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
\Spatie\Backup\Notifications\Notifications\HealthyBackupWasFound::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
\Spatie\Backup\Notifications\Notifications\CleanupWasSuccessful::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
\Spatie\Backup\Notifications\Notifications\BackupHasFailedNotification::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
\Spatie\Backup\Notifications\Notifications\UnhealthyBackupWasFoundNotification::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
\Spatie\Backup\Notifications\Notifications\CleanupHasFailedNotification::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
\Spatie\Backup\Notifications\Notifications\BackupWasSuccessfulNotification::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
\Spatie\Backup\Notifications\Notifications\HealthyBackupWasFoundNotification::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
\Spatie\Backup\Notifications\Notifications\CleanupWasSuccessfulNotification::class => [env('MAIL_BACKUP_NOTIFICATION_DRIVER', null)],
|
||||
],
|
||||
|
||||
/*
|
||||
@@ -137,6 +137,11 @@ return [
|
||||
|
||||
'mail' => [
|
||||
'to' => env('MAIL_BACKUP_NOTIFICATION_ADDRESS', null),
|
||||
|
||||
'from' => [
|
||||
'address' => env('MAIL_FROM_ADDRESS', 'hello@example.com'),
|
||||
'name' => env('MAIL_FROM_NAME', 'Example'),
|
||||
],
|
||||
],
|
||||
|
||||
'slack' => [
|
||||
@@ -152,6 +157,20 @@ return [
|
||||
'icon' => null,
|
||||
|
||||
],
|
||||
|
||||
'discord' => [
|
||||
'webhook_url' => '',
|
||||
|
||||
/*
|
||||
* If this is an empty string, the name field on the webhook will be used.
|
||||
*/
|
||||
'username' => '',
|
||||
|
||||
/*
|
||||
* If this is an empty string, the avatar on the webhook will be used.
|
||||
*/
|
||||
'avatar_url' => '',
|
||||
],
|
||||
],
|
||||
|
||||
/*
|
||||
|
||||
+107
-105
@@ -3,156 +3,158 @@
|
||||
return [
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|---------------------------------------------------------------------------
|
||||
| Class Namespace
|
||||
|--------------------------------------------------------------------------
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| This value sets the root namespace for Livewire component classes in
|
||||
| your application. This value affects component auto-discovery and
|
||||
| any Livewire file helper commands, like `artisan make:livewire`.
|
||||
|
|
||||
| After changing this item, run: `php artisan livewire:discover`.
|
||||
| This value sets the root class namespace for Livewire component classes in
|
||||
| your application. This value will change where component auto-discovery
|
||||
| finds components. It's also referenced by the file creation commands.
|
||||
|
|
||||
*/
|
||||
|
||||
'class_namespace' => 'App\\Http\\Livewire',
|
||||
'class_namespace' => 'App\\Livewire',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|---------------------------------------------------------------------------
|
||||
| View Path
|
||||
|--------------------------------------------------------------------------
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| This value sets the path for Livewire component views. This affects
|
||||
| file manipulation helper commands like `artisan make:livewire`.
|
||||
| This value is used to specify where Livewire component Blade templates are
|
||||
| stored when running file creation commands like `artisan make:livewire`.
|
||||
| It is also used if you choose to omit a component's render() method.
|
||||
|
|
||||
*/
|
||||
|
||||
'view_path' => resource_path('views/livewire'),
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|---------------------------------------------------------------------------
|
||||
| Layout
|
||||
|--------------------------------------------------------------------------
|
||||
| The default layout view that will be used when rendering a component via
|
||||
| Route::get('/some-endpoint', SomeComponent::class);. In this case the
|
||||
| the view returned by SomeComponent will be wrapped in "layouts.app"
|
||||
|---------------------------------------------------------------------------
|
||||
| The view that will be used as the layout when rendering a single component
|
||||
| as an entire page via `Route::get('/post/create', CreatePost::class);`.
|
||||
| In this case, the view returned by CreatePost will render into $slot.
|
||||
|
|
||||
*/
|
||||
|
||||
'layout' => 'layouts.app',
|
||||
'layout' => 'components.layouts.app',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Livewire Assets URL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value sets the path to Livewire JavaScript assets, for cases where
|
||||
| your app's domain root is not the correct path. By default, Livewire
|
||||
| will load its JavaScript assets from the app's "relative root".
|
||||
|
|
||||
| Examples: "/assets", "myurl.com/app".
|
||||
|---------------------------------------------------------------------------
|
||||
| Lazy Loading Placeholder
|
||||
|---------------------------------------------------------------------------
|
||||
| Livewire allows you to lazy load components that would otherwise slow down
|
||||
| the initial page load. Every component can have a custom placeholder or
|
||||
| you can define the default placeholder view for all components below.
|
||||
|
|
||||
*/
|
||||
|
||||
'asset_url' => env('APP_URL'),
|
||||
'lazy_placeholder' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Livewire App URL
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value should be used if livewire assets are served from CDN.
|
||||
| Livewire will communicate with an app through this url.
|
||||
|
|
||||
| Examples: "https://my-app.com", "myurl.com/app".
|
||||
|
|
||||
*/
|
||||
|
||||
'app_url' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Livewire Endpoint Middleware Group
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value sets the middleware group that will be applied to the main
|
||||
| Livewire "message" endpoint (the endpoint that gets hit everytime
|
||||
| a Livewire component updates). It is set to "web" by default.
|
||||
|
|
||||
*/
|
||||
|
||||
'middleware_group' => 'web',
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Livewire Temporary File Uploads Endpoint Configuration
|
||||
|--------------------------------------------------------------------------
|
||||
|---------------------------------------------------------------------------
|
||||
| Temporary File Uploads
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| Livewire handles file uploads by storing uploads in a temporary directory
|
||||
| before the file is validated and stored permanently. All file uploads
|
||||
| are directed to a global endpoint for temporary storage. The config
|
||||
| items below are used for customizing the way the endpoint works.
|
||||
| before the file is stored permanently. All file uploads are directed to
|
||||
| a global endpoint for temporary storage. You may configure this below:
|
||||
|
|
||||
*/
|
||||
|
||||
'temporary_file_upload' => [
|
||||
'disk' => env('PRIVATE_FILESYSTEM_DISK', 'local'), // Example: 'local', 's3' Default: 'default'
|
||||
'rules' => null, // Example: ['file', 'mimes:png,jpg'] Default: ['required', 'file', 'max:12288'] (12MB)
|
||||
'directory' => null, // Example: 'tmp' Default 'livewire-tmp'
|
||||
'middleware' => null, // Example: 'throttle:5,1' Default: 'throttle:60,1'
|
||||
'preview_mimes' => [ // Supported file types for temporary pre-signed file URLs.
|
||||
'rules' => null, // Example: ['file', 'mimes:png,jpg'] | Default: ['required', 'file', 'max:12288'] (12MB)
|
||||
'directory' => null, // Example: 'tmp' | Default: 'livewire-tmp'
|
||||
'middleware' => null, // Example: 'throttle:5,1' | Default: 'throttle:60,1'
|
||||
'preview_mimes' => [ // Supported file types for temporary pre-signed file URLs...
|
||||
'png', 'gif', 'bmp', 'svg', 'wav', 'mp4',
|
||||
'mov', 'avi', 'wmv', 'mp3', 'm4a',
|
||||
'jpg', 'jpeg', 'mpga', 'webp', 'wma',
|
||||
],
|
||||
'max_upload_time' => 5, // Max duration (in minutes) before an upload gets invalidated.
|
||||
'max_upload_time' => 5, // Max duration (in minutes) before an upload is invalidated...
|
||||
'cleanup' => true, // Should cleanup temporary uploads older than 24 hrs...
|
||||
],
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Manifest File Path
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value sets the path to the Livewire manifest file.
|
||||
| The default should work for most cases (which is
|
||||
| "<app_root>/bootstrap/cache/livewire-components.php"), but for specific
|
||||
| cases like when hosting on Laravel Vapor, it could be set to a different value.
|
||||
|
|
||||
| Example: for Laravel Vapor, it would be "/tmp/storage/bootstrap/cache/livewire-components.php".
|
||||
|
|
||||
*/
|
||||
|
||||
'manifest_path' => null,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Back Button Cache
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines whether the back button cache will be used on pages
|
||||
| that contain Livewire. By disabling back button cache, it ensures that
|
||||
| the back button shows the correct state of components, instead of
|
||||
| potentially stale, cached data.
|
||||
|
|
||||
| Setting it to "false" (default) will disable back button cache.
|
||||
|
|
||||
*/
|
||||
|
||||
'back_button_cache' => false,
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
|---------------------------------------------------------------------------
|
||||
| Render On Redirect
|
||||
|--------------------------------------------------------------------------
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| This value determines whether Livewire will render before it's redirected
|
||||
| or not. Setting it to "false" (default) will mean the render method is
|
||||
| skipped when redirecting. And "true" will mean the render method is
|
||||
| run before redirecting. Browsers bfcache can store a potentially
|
||||
| stale view if render is skipped on redirect.
|
||||
| This value determines if Livewire will run a component's `render()` method
|
||||
| after a redirect has been triggered using something like `redirect(...)`
|
||||
| Setting this to true will render the view once more before redirecting
|
||||
|
|
||||
*/
|
||||
|
||||
'render_on_redirect' => false,
|
||||
|
||||
/*
|
||||
|---------------------------------------------------------------------------
|
||||
| Eloquent Model Binding
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| Previous versions of Livewire supported binding directly to eloquent model
|
||||
| properties using wire:model by default. However, this behavior has been
|
||||
| deemed too "magical" and has therefore been put under a feature flag.
|
||||
|
|
||||
*/
|
||||
|
||||
'legacy_model_binding' => true,
|
||||
|
||||
/*
|
||||
|---------------------------------------------------------------------------
|
||||
| Auto-inject Frontend Assets
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| By default, Livewire automatically injects its JavaScript and CSS into the
|
||||
| <head> and <body> of pages containing Livewire components. By disabling
|
||||
| this behavior, you need to use @livewireStyles and @livewireScripts.
|
||||
|
|
||||
*/
|
||||
|
||||
'inject_assets' => true,
|
||||
|
||||
/*
|
||||
|---------------------------------------------------------------------------
|
||||
| Navigate (SPA mode)
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| By adding `wire:navigate` to links in your Livewire application, Livewire
|
||||
| will prevent the default link handling and instead request those pages
|
||||
| via AJAX, creating an SPA-like effect. Configure this behavior here.
|
||||
|
|
||||
*/
|
||||
|
||||
'navigate' => [
|
||||
'show_progress_bar' => true,
|
||||
'progress_bar_color' => '#2299dd',
|
||||
],
|
||||
|
||||
/*
|
||||
|---------------------------------------------------------------------------
|
||||
| HTML Morph Markers
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| Livewire intelligently "morphs" existing HTML into the newly rendered HTML
|
||||
| after each update. To make this process more reliable, Livewire injects
|
||||
| "markers" into the rendered Blade surrounding @if, @class & @foreach.
|
||||
|
|
||||
*/
|
||||
|
||||
'inject_morph_markers' => true,
|
||||
|
||||
/*
|
||||
|---------------------------------------------------------------------------
|
||||
| Pagination Theme
|
||||
|---------------------------------------------------------------------------
|
||||
|
|
||||
| When enabling Livewire's pagination feature by using the `WithPagination`
|
||||
| trait, Livewire will use Tailwind templates to render pagination views
|
||||
| on the page. If you want Bootstrap CSS, you can specify: "bootstrap"
|
||||
|
|
||||
*/
|
||||
|
||||
'pagination_theme' => 'tailwind',
|
||||
];
|
||||
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
return array (
|
||||
'app_version' => 'v7.0.0-dev',
|
||||
'full_app_version' => 'v7.0.0 - build 8df9007-gb489c71fa2',
|
||||
'build_version' => '13487',
|
||||
'app_version' => 'v7.0.7',
|
||||
'full_app_version' => 'v7.0.7 - build 14172-ge50296870',
|
||||
'build_version' => '14172',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => '8df9007',
|
||||
'full_hash' => 'v7.0.0-99-8df9007',
|
||||
'hash_version' => 'ge50296870',
|
||||
'full_hash' => 'v7.0.7-53-ge50296870',
|
||||
'branch' => 'develop',
|
||||
);
|
||||
@@ -105,4 +105,64 @@ class ActionlogFactory extends Factory
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function filesUploaded()
|
||||
{
|
||||
return $this->state(function () {
|
||||
|
||||
return [
|
||||
'created_at' => $this->faker->dateTimeBetween('-1 years', 'now', date_default_timezone_get()),
|
||||
'action_type' => 'uploaded',
|
||||
'item_type' => User::class,
|
||||
'filename' => $this->faker->unixTime('now'),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function acceptedSignature()
|
||||
{
|
||||
return $this->state(function () {
|
||||
|
||||
$asset = Asset::factory()->create();
|
||||
|
||||
return [
|
||||
'created_at' => $this->faker->dateTimeBetween('-1 years', 'now', date_default_timezone_get()),
|
||||
'action_type' => 'accepted',
|
||||
'item_id' => $asset->id,
|
||||
'item_type' => Asset::class,
|
||||
'target_type' => User::class,
|
||||
'accept_signature' => $this->faker->unixTime('now'),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function acceptedEula()
|
||||
{
|
||||
return $this->state(function () {
|
||||
|
||||
$asset = Asset::factory()->create();
|
||||
|
||||
return [
|
||||
'created_at' => $this->faker->dateTimeBetween('-1 years', 'now', date_default_timezone_get()),
|
||||
'action_type' => 'accepted',
|
||||
'item_id' => $asset->id,
|
||||
'item_type' => Asset::class,
|
||||
'target_type' => User::class,
|
||||
'filename' => $this->faker->unixTime('now'),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
public function userUpdated()
|
||||
{
|
||||
return $this->state(function () {
|
||||
|
||||
return [
|
||||
'created_at' => $this->faker->dateTimeBetween('-1 years', 'now', date_default_timezone_get()),
|
||||
'action_type' => 'update',
|
||||
'target_type' => User::class,
|
||||
'item_type' => User::class,
|
||||
];
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use App\Models\Company;
|
||||
use App\Models\Consumable;
|
||||
use App\Models\Manufacturer;
|
||||
use App\Models\User;
|
||||
use Carbon\Carbon;
|
||||
use Illuminate\Database\Eloquent\Factories\Factory;
|
||||
use App\Models\Supplier;
|
||||
|
||||
@@ -116,4 +117,16 @@ class ConsumableFactory extends Factory
|
||||
$consumable->category->update(['require_acceptance' => 1]);
|
||||
});
|
||||
}
|
||||
|
||||
public function checkedOutToUser(User $user = null)
|
||||
{
|
||||
return $this->afterCreating(function (Consumable $consumable) use ($user) {
|
||||
$consumable->users()->attach($consumable->id, [
|
||||
'consumable_id' => $consumable->id,
|
||||
'created_at' => Carbon::now(),
|
||||
'user_id' => User::factory()->create()->id,
|
||||
'assigned_to' => $user->id ?? User::factory()->create()->id,
|
||||
]);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -38,6 +38,16 @@ class UserFactory extends Factory
|
||||
];
|
||||
}
|
||||
|
||||
public function deletedUser()
|
||||
{
|
||||
return $this->state(function () {
|
||||
return [
|
||||
'deleted_at' => $this->faker->dateTime(),
|
||||
];
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
public function firstAdmin()
|
||||
{
|
||||
return $this->state(function () {
|
||||
|
||||
@@ -0,0 +1,30 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->boolean('profile_edit')->nullable()->default(1);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('settings', 'profile_edit')) {
|
||||
$table->dropColumn('profile_edit');
|
||||
}
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,28 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
return new class extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*/
|
||||
public function up(): void
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->string('default_avatar')->after('favicon')->default('default.png')->nullable();
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*/
|
||||
public function down(): void
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->dropColumn('default_avatar');
|
||||
});
|
||||
}
|
||||
};
|
||||
@@ -0,0 +1,50 @@
|
||||
version: '3'
|
||||
|
||||
services:
|
||||
snipeit:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.alpine
|
||||
container_name: snipeit
|
||||
ports:
|
||||
- "8000:80"
|
||||
volumes:
|
||||
- ./storage/logs:/var/www/html/storage/logs
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
env_file:
|
||||
- .env.docker
|
||||
networks:
|
||||
- snipeit-backend
|
||||
|
||||
mariadb:
|
||||
image: mariadb:10.6.4-focal
|
||||
volumes:
|
||||
- db:/var/lib/mysql
|
||||
env_file:
|
||||
- .env.docker
|
||||
networks:
|
||||
- snipeit-backend
|
||||
ports:
|
||||
- "3306:3306"
|
||||
|
||||
redis:
|
||||
image: redis:6.2.5-buster
|
||||
networks:
|
||||
- snipeit-backend
|
||||
|
||||
mailhog:
|
||||
image: mailhog/mailhog:v1.0.1
|
||||
ports:
|
||||
# - 1025:1025
|
||||
- "8025:8025"
|
||||
networks:
|
||||
- snipeit-backend
|
||||
|
||||
|
||||
volumes:
|
||||
db: {}
|
||||
|
||||
networks:
|
||||
snipeit-backend: {}
|
||||
+26
-42
@@ -1,50 +1,34 @@
|
||||
version: '3'
|
||||
volumes:
|
||||
db_data:
|
||||
storage:
|
||||
|
||||
services:
|
||||
snipeit:
|
||||
build:
|
||||
context: .
|
||||
dockerfile: Dockerfile.alpine
|
||||
container_name: snipeit
|
||||
ports:
|
||||
- "8000:80"
|
||||
app:
|
||||
image: snipe/snipe-it:${APP_VERSION:-v6.4.1}
|
||||
restart: always
|
||||
volumes:
|
||||
- ./storage/logs:/var/www/html/storage/logs
|
||||
- storage:/var/lib/snipeit
|
||||
ports:
|
||||
- "${APP_PORT:-8000}:80"
|
||||
depends_on:
|
||||
- mariadb
|
||||
- redis
|
||||
db:
|
||||
condition: service_healthy
|
||||
restart: true
|
||||
env_file:
|
||||
- .env.docker
|
||||
networks:
|
||||
- snipeit-backend
|
||||
- .env
|
||||
|
||||
mariadb:
|
||||
db:
|
||||
image: mariadb:10.6.4-focal
|
||||
restart: always
|
||||
volumes:
|
||||
- db:/var/lib/mysql
|
||||
env_file:
|
||||
- .env.docker
|
||||
networks:
|
||||
- snipeit-backend
|
||||
ports:
|
||||
- "3306:3306"
|
||||
|
||||
redis:
|
||||
image: redis:6.2.5-buster
|
||||
networks:
|
||||
- snipeit-backend
|
||||
|
||||
mailhog:
|
||||
image: mailhog/mailhog:v1.0.1
|
||||
ports:
|
||||
# - 1025:1025
|
||||
- "8025:8025"
|
||||
networks:
|
||||
- snipeit-backend
|
||||
|
||||
|
||||
volumes:
|
||||
db: {}
|
||||
|
||||
networks:
|
||||
snipeit-backend: {}
|
||||
- db_data:/var/lib/mysql
|
||||
environment:
|
||||
MYSQL_DATABASE: ${DB_DATABASE}
|
||||
MYSQL_USER: ${DB_USERNAME}
|
||||
MYSQL_PASSWORD: ${DB_PASSWORD}
|
||||
MYSQL_ROOT_PASSWORD: ${MYSQL_ROOT_PASSWORD}
|
||||
healthcheck:
|
||||
test: mysqladmin ping -h 127.0.0.1 -u $$MYSQL_USER --password=$$MYSQL_PASSWORD
|
||||
interval: 5s
|
||||
timeout: 1s
|
||||
retries: 5
|
||||
|
||||
Generated
+23
-32
@@ -10,7 +10,6 @@
|
||||
"acorn-import-assertions": "^1.9.0",
|
||||
"admin-lte": "^2.4.18",
|
||||
"ajv": "^6.12.6",
|
||||
"alpinejs": "^3.13.10",
|
||||
"blueimp-file-upload": "^9.34.0",
|
||||
"bootstrap": "^3.4.1",
|
||||
"bootstrap-colorpicker": "^2.5.3",
|
||||
@@ -31,13 +30,13 @@
|
||||
"less-loader": "^6.0",
|
||||
"list.js": "^1.5.0",
|
||||
"morris.js": "github:morrisjs/morris.js",
|
||||
"papaparse": "5.2.0",
|
||||
"papaparse": "5.4.1",
|
||||
"select2": "4.0.13",
|
||||
"sheetjs": "^2.0.0",
|
||||
"signature_pad": "^4.2.0",
|
||||
"tableexport.jquery.plugin": "1.30.0",
|
||||
"tether": "^1.4.0",
|
||||
"webpack": "^5.90.2"
|
||||
"webpack": "^5.92.0"
|
||||
},
|
||||
"devDependencies": {
|
||||
"all-contributors-cli": "^6.26.1",
|
||||
@@ -2312,17 +2311,6 @@
|
||||
"@types/node": "*"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/reactivity": {
|
||||
"version": "3.1.5",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"@vue/shared": "3.1.5"
|
||||
}
|
||||
},
|
||||
"node_modules/@vue/shared": {
|
||||
"version": "3.1.5",
|
||||
"license": "MIT"
|
||||
},
|
||||
"node_modules/@webassemblyjs/ast": {
|
||||
"version": "1.12.1",
|
||||
"license": "MIT",
|
||||
@@ -2509,6 +2497,14 @@
|
||||
"acorn": "^8"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-import-attributes": {
|
||||
"version": "1.9.5",
|
||||
"resolved": "https://registry.npmjs.org/acorn-import-attributes/-/acorn-import-attributes-1.9.5.tgz",
|
||||
"integrity": "sha512-n02Vykv5uA3eHGM/Z2dQrcD56kL8TyDb2p1+0P83PClMnC/nc+anbQRhIOWnSq4Ke/KvDPrY3C9hDtC/A3eHnQ==",
|
||||
"peerDependencies": {
|
||||
"acorn": "^8"
|
||||
}
|
||||
},
|
||||
"node_modules/acorn-node": {
|
||||
"version": "1.8.2",
|
||||
"license": "Apache-2.0",
|
||||
@@ -2662,14 +2658,6 @@
|
||||
"prettier": "^2"
|
||||
}
|
||||
},
|
||||
"node_modules/alpinejs": {
|
||||
"version": "3.13.10",
|
||||
"resolved": "https://registry.npmjs.org/alpinejs/-/alpinejs-3.13.10.tgz",
|
||||
"integrity": "sha512-86RB307VWICex0vG15Eq0x058cNNsvS57ohrjN6n/TJAVSFV+zXOK/E34nNHDHc6Poq+yTNCLqEzPqEkRBTMRQ==",
|
||||
"dependencies": {
|
||||
"@vue/reactivity": "~3.1.1"
|
||||
}
|
||||
},
|
||||
"node_modules/ansi-escapes": {
|
||||
"version": "4.3.2",
|
||||
"dev": true,
|
||||
@@ -5311,8 +5299,9 @@
|
||||
}
|
||||
},
|
||||
"node_modules/enhanced-resolve": {
|
||||
"version": "5.16.0",
|
||||
"license": "MIT",
|
||||
"version": "5.17.0",
|
||||
"resolved": "https://registry.npmjs.org/enhanced-resolve/-/enhanced-resolve-5.17.0.tgz",
|
||||
"integrity": "sha512-dwDPwZL0dmye8Txp2gzFmA6sxALaSvdRDjPH0viLcKrtlOL3tw62nWWweVD1SdILDTJrbrL6tdWVN58Wo6U3eA==",
|
||||
"dependencies": {
|
||||
"graceful-fs": "^4.2.4",
|
||||
"tapable": "^2.2.0"
|
||||
@@ -8347,9 +8336,9 @@
|
||||
"license": "(MIT AND Zlib)"
|
||||
},
|
||||
"node_modules/papaparse": {
|
||||
"version": "5.2.0",
|
||||
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.2.0.tgz",
|
||||
"integrity": "sha512-ylq1wgUSnagU+MKQtNeVqrPhZuMYBvOSL00DHycFTCxownF95gpLAk1HiHdUW77N8yxRq1qHXLdlIPyBSG9NSA=="
|
||||
"version": "5.4.1",
|
||||
"resolved": "https://registry.npmjs.org/papaparse/-/papaparse-5.4.1.tgz",
|
||||
"integrity": "sha512-HipMsgJkZu8br23pW15uvo6sib6wne/4woLZPlFf3rpDyMe9ywEXUsuD7+6K9PRkJlVT51j/sCOYDKGGS3ZJrw=="
|
||||
},
|
||||
"node_modules/param-case": {
|
||||
"version": "3.0.4",
|
||||
@@ -10414,7 +10403,8 @@
|
||||
},
|
||||
"node_modules/tapable": {
|
||||
"version": "2.2.1",
|
||||
"license": "MIT",
|
||||
"resolved": "https://registry.npmjs.org/tapable/-/tapable-2.2.1.tgz",
|
||||
"integrity": "sha512-GNzQvQTOIP6RyTfE2Qxb8ZVlNmw0n88vp1szwWRimP02mnTsx3Wtn5qRdqY9w2XduFNUgvOwhNnQsjwCp+kqaQ==",
|
||||
"engines": {
|
||||
"node": ">=6"
|
||||
}
|
||||
@@ -10877,8 +10867,9 @@
|
||||
"license": "BSD-2-Clause"
|
||||
},
|
||||
"node_modules/webpack": {
|
||||
"version": "5.91.0",
|
||||
"license": "MIT",
|
||||
"version": "5.92.1",
|
||||
"resolved": "https://registry.npmjs.org/webpack/-/webpack-5.92.1.tgz",
|
||||
"integrity": "sha512-JECQ7IwJb+7fgUFBlrJzbyu3GEuNBcdqr1LD7IbSzwkSmIevTm8PF+wej3Oxuz/JFBUZ6O1o43zsPkwm1C4TmA==",
|
||||
"dependencies": {
|
||||
"@types/eslint-scope": "^3.7.3",
|
||||
"@types/estree": "^1.0.5",
|
||||
@@ -10886,10 +10877,10 @@
|
||||
"@webassemblyjs/wasm-edit": "^1.12.1",
|
||||
"@webassemblyjs/wasm-parser": "^1.12.1",
|
||||
"acorn": "^8.7.1",
|
||||
"acorn-import-assertions": "^1.9.0",
|
||||
"acorn-import-attributes": "^1.9.5",
|
||||
"browserslist": "^4.21.10",
|
||||
"chrome-trace-event": "^1.0.2",
|
||||
"enhanced-resolve": "^5.16.0",
|
||||
"enhanced-resolve": "^5.17.0",
|
||||
"es-module-lexer": "^1.2.1",
|
||||
"eslint-scope": "5.1.1",
|
||||
"events": "^3.2.0",
|
||||
|
||||
+2
-3
@@ -30,7 +30,6 @@
|
||||
"acorn-import-assertions": "^1.9.0",
|
||||
"admin-lte": "^2.4.18",
|
||||
"ajv": "^6.12.6",
|
||||
"alpinejs": "^3.13.10",
|
||||
"blueimp-file-upload": "^9.34.0",
|
||||
"bootstrap": "^3.4.1",
|
||||
"bootstrap-colorpicker": "^2.5.3",
|
||||
@@ -51,12 +50,12 @@
|
||||
"less-loader": "^6.0",
|
||||
"list.js": "^1.5.0",
|
||||
"morris.js": "github:morrisjs/morris.js",
|
||||
"papaparse": "5.2.0",
|
||||
"papaparse": "5.4.1",
|
||||
"select2": "4.0.13",
|
||||
"sheetjs": "^2.0.0",
|
||||
"signature_pad": "^4.2.0",
|
||||
"tableexport.jquery.plugin": "1.30.0",
|
||||
"tether": "^1.4.0",
|
||||
"webpack": "^5.90.2"
|
||||
"webpack": "^5.92.0"
|
||||
}
|
||||
}
|
||||
|
||||
+3
@@ -554,4 +554,7 @@ div.container.row-new-striped {
|
||||
.table > tfoot > tr.danger > th {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
@@ -554,4 +554,7 @@ div.container.row-new-striped {
|
||||
.table > tfoot > tr.danger > th {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -525,4 +525,7 @@ a:visited {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
@@ -525,4 +525,7 @@ a:visited {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -512,4 +512,7 @@ a:visited {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
@@ -512,4 +512,7 @@ a:visited {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -513,4 +513,7 @@ input[type=search] {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
@@ -513,4 +513,7 @@ input[type=search] {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -520,4 +520,7 @@ a:visited {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
@@ -520,4 +520,7 @@ a:visited {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -531,4 +531,7 @@ a:visited {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -531,4 +531,7 @@ a:visited {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
+3
@@ -484,4 +484,7 @@ tr th div.th-inner {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
@@ -484,4 +484,7 @@ tr th div.th-inner {
|
||||
.search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +0,0 @@
|
||||
GIF89a
|
||||
<?php echo "Hello, the date is: " . date('c');
|
||||
|
||||
|
Before Width: | Height: | Size: 55 B |
+46
-26
@@ -586,22 +586,27 @@ function htmlEntities(str) {
|
||||
*
|
||||
* 1. Set the class of your select2 elements to 'livewire-select2').
|
||||
* 2. Name your element to match a property in your Livewire component
|
||||
* 3. Add an attribute called 'data-livewire-component' that points to $_instance->id (via `{{ }}` if you're in a blade,
|
||||
* or just $_instance->id if not).
|
||||
* 3. Add an attribute called 'data-livewire-component' that points to $this->getId() (via `{{ }}` if you're in a blade,
|
||||
* or just $this->getId() if not).
|
||||
*/
|
||||
$(function () {
|
||||
document.addEventListener('livewire:init', function () {
|
||||
$('.livewire-select2').select2();
|
||||
$(document).on('select2:select', '.livewire-select2', function (event) {
|
||||
var target = $(event.target);
|
||||
if (!event.target.name || !target.data('livewire-component')) {
|
||||
console.error("You need to set both name (which should match a Livewire property) and data-livewire-component on your Livewire-ed select2 elements!");
|
||||
console.error("For data-livewire-component, you probably want to use $_instance->id or {{ $_instance->id }}, as appropriate");
|
||||
console.error("For data-livewire-component, you probably want to use $this->getId() or {{ $this->getId() }}, as appropriate");
|
||||
return false;
|
||||
}
|
||||
window.livewire.find(target.data('livewire-component')).set(event.target.name, this.options[this.selectedIndex].value);
|
||||
Livewire.find(target.data('livewire-component')).set(event.target.name, this.options[this.selectedIndex].value);
|
||||
});
|
||||
window.livewire.hook('message.processed', function (el, component) {
|
||||
$('.livewire-select2').select2();
|
||||
Livewire.hook('request', function (_ref) {
|
||||
var succeed = _ref.succeed;
|
||||
succeed(function () {
|
||||
queueMicrotask(function () {
|
||||
$('.livewire-select2').select2();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -32208,6 +32213,19 @@ __webpack_require__.r(__webpack_exports__);
|
||||
// extracted by mini-css-extract-plugin
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./node_modules/admin-lte/build/less/AdminLTE.less":
|
||||
/*!*********************************************************!*\
|
||||
!*** ./node_modules/admin-lte/build/less/AdminLTE.less ***!
|
||||
\*********************************************************/
|
||||
/***/ ((__unused_webpack_module, __webpack_exports__, __webpack_require__) => {
|
||||
|
||||
"use strict";
|
||||
__webpack_require__.r(__webpack_exports__);
|
||||
// extracted by mini-css-extract-plugin
|
||||
|
||||
|
||||
/***/ }),
|
||||
|
||||
/***/ "./resources/assets/less/app.less":
|
||||
@@ -32377,6 +32395,7 @@ __webpack_require__.r(__webpack_exports__);
|
||||
/******/ "css/dist/skins/skin-blue": 0,
|
||||
/******/ "css/build/overrides": 0,
|
||||
/******/ "css/build/app": 0,
|
||||
/******/ "css/build/AdminLTE": 0,
|
||||
/******/ "css/dist/skins/skin-orange": 0,
|
||||
/******/ "css/dist/skins/skin-orange-dark": 0,
|
||||
/******/ "css/dist/skins/skin-blue-dark": 0,
|
||||
@@ -32439,25 +32458,26 @@ __webpack_require__.r(__webpack_exports__);
|
||||
/******/ // startup
|
||||
/******/ // Load entry module and return exports
|
||||
/******/ // This entry module depends on other loaded chunks and execution need to be delayed
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/js/snipeit.js")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/js/snipeit_modals.js")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/app.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/overrides.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-blue.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-red.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-contrast.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-green.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-green-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-black.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-black-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-red-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-purple.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-purple-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-yellow.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-yellow-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-blue-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-orange-dark.less")))
|
||||
/******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-orange.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/js/snipeit.js")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/js/snipeit_modals.js")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./node_modules/admin-lte/build/less/AdminLTE.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/app.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/overrides.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-blue.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-red.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-contrast.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-green.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-green-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-black.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-black-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-red-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-purple.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-purple-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-yellow.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-yellow-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-blue-dark.less")))
|
||||
/******/ __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-orange-dark.less")))
|
||||
/******/ var __webpack_exports__ = __webpack_require__.O(undefined, ["css/dist/skins/skin-red","css/dist/skins/skin-blue","css/build/overrides","css/build/app","css/build/AdminLTE","css/dist/skins/skin-orange","css/dist/skins/skin-orange-dark","css/dist/skins/skin-blue-dark","css/dist/skins/skin-yellow-dark","css/dist/skins/skin-yellow","css/dist/skins/skin-purple-dark","css/dist/skins/skin-purple","css/dist/skins/skin-red-dark","css/dist/skins/skin-black-dark","css/dist/skins/skin-black","css/dist/skins/skin-green-dark","css/dist/skins/skin-green","css/dist/skins/skin-contrast"], () => (__webpack_require__("./resources/assets/less/skins/skin-orange.less")))
|
||||
/******/ __webpack_exports__ = __webpack_require__.O(__webpack_exports__);
|
||||
/******/
|
||||
/******/ })()
|
||||
|
||||
File diff suppressed because one or more lines are too long
Vendored
+59
-33
File diff suppressed because one or more lines are too long
+18
-18
@@ -1,20 +1,21 @@
|
||||
{
|
||||
"/js/build/app.js": "/js/build/app.js?id=bcf31142100dae10c9e075884f901d56",
|
||||
"/js/build/app.js": "/js/build/app.js?id=d47043e03f80612693d9b9034d94e28f",
|
||||
"/css/dist/skins/skin-red.css": "/css/dist/skins/skin-red.css?id=44bf834f2110504a793dadec132a5898",
|
||||
"/css/dist/skins/skin-blue.css": "/css/dist/skins/skin-blue.css?id=f677207c6cf9678eb539abecb408c374",
|
||||
"/css/build/overrides.css": "/css/build/overrides.css?id=004835e70ed3ae2e2340162b7a37c752",
|
||||
"/css/build/app.css": "/css/build/app.css?id=7ecac57fc8cf6fdbe447c18d5f2ae7bc",
|
||||
"/css/build/AdminLTE.css": "/css/build/AdminLTE.css?id=4ea0068716c1bb2434d87a16d51b98c9",
|
||||
"/css/dist/skins/skin-orange.css": "/css/dist/skins/skin-orange.css?id=6f0563e726c2fe4fab4026daaa5bfdf2",
|
||||
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=620b684d9dd9d3bb5fdda00a3a2467c3",
|
||||
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=23f2e8df6b60e8d9816e645cc5000874",
|
||||
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=2600828a93288ba791de9bf711171796",
|
||||
"/css/dist/skins/skin-orange-dark.css": "/css/dist/skins/skin-orange-dark.css?id=4fa7aa3ba499c8f4e390eb8549da3f74",
|
||||
"/css/dist/skins/skin-blue-dark.css": "/css/dist/skins/skin-blue-dark.css?id=0640e45bad692dcf62873c6e85904899",
|
||||
"/css/dist/skins/skin-yellow-dark.css": "/css/dist/skins/skin-yellow-dark.css?id=393aaa7b368b0670fc42434c8cca7dc7",
|
||||
"/css/dist/skins/skin-yellow.css": "/css/dist/skins/skin-yellow.css?id=7b315b9612b8fde8f9c5b0ddb6bba690",
|
||||
"/css/dist/skins/skin-purple-dark.css": "/css/dist/skins/skin-purple-dark.css?id=e56aa0fcc7789f1efd1e14bc5e0b4159",
|
||||
"/css/dist/skins/skin-purple-dark.css": "/css/dist/skins/skin-purple-dark.css?id=f8b26018a1533b9db864247daaf06daa",
|
||||
"/css/dist/skins/skin-purple.css": "/css/dist/skins/skin-purple.css?id=6fe68325d5356197672c27bc77cedcb4",
|
||||
"/css/dist/skins/skin-red-dark.css": "/css/dist/skins/skin-red-dark.css?id=821b68e0a3efc3b6743453bf0ed2a954",
|
||||
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=b31e80c39b29106d02bf9b3a0a833343",
|
||||
"/css/dist/skins/skin-red-dark.css": "/css/dist/skins/skin-red-dark.css?id=ad39859637dafa781288630f9d6d6523",
|
||||
"/css/dist/skins/skin-black-dark.css": "/css/dist/skins/skin-black-dark.css?id=f0b08873a06bb54daeee176a9459f4a9",
|
||||
"/css/dist/skins/skin-black.css": "/css/dist/skins/skin-black.css?id=76482123f6c70e866d6b971ba91de7bb",
|
||||
"/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=ec0a01609bec55e90f0692d86cb81625",
|
||||
"/css/dist/skins/skin-green-dark.css": "/css/dist/skins/skin-green-dark.css?id=553ee68741b5a392037abcf04da80adc",
|
||||
"/css/dist/skins/skin-green.css": "/css/dist/skins/skin-green.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
|
||||
"/css/dist/skins/skin-contrast.css": "/css/dist/skins/skin-contrast.css?id=da6c7997d9de2f8329142399f0ce50da",
|
||||
"/css/dist/all.css": "/css/dist/all.css?id=0f9956c66f93c6417f69f0134c6ae128",
|
||||
@@ -29,23 +30,22 @@
|
||||
"/css/webfonts/fa-v4compatibility.ttf": "/css/webfonts/fa-v4compatibility.ttf?id=8994b282f9f3b7a00380bb1e2731a4bf",
|
||||
"/css/webfonts/fa-v4compatibility.woff2": "/css/webfonts/fa-v4compatibility.woff2?id=111e341dba724e1df946e8d1f406a7bd",
|
||||
"/css/dist/bootstrap-table.css": "/css/dist/bootstrap-table.css?id=5f79123a6750afd34dbf565faec3dda3",
|
||||
"/js/build/vendor.js": "/js/build/vendor.js?id=2f71c05daf36d9ec4852d1a8c87bc74c",
|
||||
"/js/build/vendor.js": "/js/build/vendor.js?id=179bfe20e8767f7df32658c6b5a10ca3",
|
||||
"/js/dist/bootstrap-table.js": "/js/dist/bootstrap-table.js?id=e5918703a22f8992c4c98f1dbbecb8f7",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=aa7cb7c65a042b69e46aeaa93a7d50ec",
|
||||
"/js/dist/all-defer.js": "/js/dist/all-defer.js?id=75d841799f917cbcacf6b87698379726",
|
||||
"/js/dist/all.js": "/js/dist/all.js?id=a5164c1c20074421f561fade29d392c3",
|
||||
"/css/dist/skins/skin-green.min.css": "/css/dist/skins/skin-green.min.css?id=0a82a6ae6bb4e58fe62d162c4fb50397",
|
||||
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=ec0a01609bec55e90f0692d86cb81625",
|
||||
"/css/dist/skins/skin-green-dark.min.css": "/css/dist/skins/skin-green-dark.min.css?id=553ee68741b5a392037abcf04da80adc",
|
||||
"/css/dist/skins/skin-black.min.css": "/css/dist/skins/skin-black.min.css?id=76482123f6c70e866d6b971ba91de7bb",
|
||||
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=b31e80c39b29106d02bf9b3a0a833343",
|
||||
"/css/dist/skins/skin-black-dark.min.css": "/css/dist/skins/skin-black-dark.min.css?id=f0b08873a06bb54daeee176a9459f4a9",
|
||||
"/css/dist/skins/skin-blue.min.css": "/css/dist/skins/skin-blue.min.css?id=f677207c6cf9678eb539abecb408c374",
|
||||
"/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=23f2e8df6b60e8d9816e645cc5000874",
|
||||
"/css/dist/skins/skin-blue-dark.min.css": "/css/dist/skins/skin-blue-dark.min.css?id=0640e45bad692dcf62873c6e85904899",
|
||||
"/css/dist/skins/skin-yellow.min.css": "/css/dist/skins/skin-yellow.min.css?id=7b315b9612b8fde8f9c5b0ddb6bba690",
|
||||
"/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=2600828a93288ba791de9bf711171796",
|
||||
"/css/dist/skins/skin-yellow-dark.min.css": "/css/dist/skins/skin-yellow-dark.min.css?id=393aaa7b368b0670fc42434c8cca7dc7",
|
||||
"/css/dist/skins/skin-red.min.css": "/css/dist/skins/skin-red.min.css?id=44bf834f2110504a793dadec132a5898",
|
||||
"/css/dist/skins/skin-red-dark.min.css": "/css/dist/skins/skin-red-dark.min.css?id=821b68e0a3efc3b6743453bf0ed2a954",
|
||||
"/css/dist/skins/skin-red-dark.min.css": "/css/dist/skins/skin-red-dark.min.css?id=ad39859637dafa781288630f9d6d6523",
|
||||
"/css/dist/skins/skin-purple.min.css": "/css/dist/skins/skin-purple.min.css?id=6fe68325d5356197672c27bc77cedcb4",
|
||||
"/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=e56aa0fcc7789f1efd1e14bc5e0b4159",
|
||||
"/css/dist/skins/skin-purple-dark.min.css": "/css/dist/skins/skin-purple-dark.min.css?id=f8b26018a1533b9db864247daaf06daa",
|
||||
"/css/dist/skins/skin-orange.min.css": "/css/dist/skins/skin-orange.min.css?id=6f0563e726c2fe4fab4026daaa5bfdf2",
|
||||
"/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=620b684d9dd9d3bb5fdda00a3a2467c3",
|
||||
"/css/dist/skins/skin-orange-dark.min.css": "/css/dist/skins/skin-orange-dark.min.css?id=4fa7aa3ba499c8f4e390eb8549da3f74",
|
||||
"/css/dist/skins/skin-contrast.min.css": "/css/dist/skins/skin-contrast.min.css?id=da6c7997d9de2f8329142399f0ce50da"
|
||||
}
|
||||
|
||||
+10792
File diff suppressed because it is too large
Load Diff
Vendored
+9914
-14
File diff suppressed because one or more lines are too long
+103
File diff suppressed because one or more lines are too long
+7
File diff suppressed because one or more lines are too long
Vendored
+2
-1
@@ -1 +1,2 @@
|
||||
{"/livewire.js":"/livewire.js?id=90730a3b0e7144480175"}
|
||||
|
||||
{"/livewire.js":"87e1046f"}
|
||||
|
||||
@@ -610,24 +610,27 @@ function htmlEntities(str) {
|
||||
*
|
||||
* 1. Set the class of your select2 elements to 'livewire-select2').
|
||||
* 2. Name your element to match a property in your Livewire component
|
||||
* 3. Add an attribute called 'data-livewire-component' that points to $_instance->id (via `{{ }}` if you're in a blade,
|
||||
* or just $_instance->id if not).
|
||||
* 3. Add an attribute called 'data-livewire-component' that points to $this->getId() (via `{{ }}` if you're in a blade,
|
||||
* or just $this->getId() if not).
|
||||
*/
|
||||
$(function () {
|
||||
document.addEventListener('livewire:init', () => {
|
||||
$('.livewire-select2').select2()
|
||||
|
||||
$(document).on('select2:select', '.livewire-select2', function (event) {
|
||||
var target = $(event.target)
|
||||
if(!event.target.name || !target.data('livewire-component')) {
|
||||
console.error("You need to set both name (which should match a Livewire property) and data-livewire-component on your Livewire-ed select2 elements!")
|
||||
console.error("For data-livewire-component, you probably want to use $_instance->id or {{ $_instance->id }}, as appropriate")
|
||||
console.error("For data-livewire-component, you probably want to use $this->getId() or {{ $this->getId() }}, as appropriate")
|
||||
return false
|
||||
}
|
||||
window.livewire.find(target.data('livewire-component')).set(event.target.name, this.options[this.selectedIndex].value)
|
||||
})
|
||||
|
||||
window.livewire.hook('message.processed', function (el,component) {
|
||||
$('.livewire-select2').select2();
|
||||
Livewire.find(target.data('livewire-component')).set(event.target.name, this.options[this.selectedIndex].value)
|
||||
});
|
||||
|
||||
})
|
||||
Livewire.hook('request', ({succeed}) => {
|
||||
succeed(() => {
|
||||
queueMicrotask(() => {
|
||||
$('.livewire-select2').select2();
|
||||
});
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
@@ -457,4 +457,7 @@ div.container.row-new-striped{
|
||||
}
|
||||
.table > thead > tr > td.danger, .table > tbody > tr > td.danger, .table > tfoot > tr > td.danger, .table > thead > tr > th.danger, .table > tbody > tr > th.danger, .table > tfoot > tr > th.danger, .table > thead > tr.danger > td, .table > tbody > tr.danger > td, .table > tfoot > tr.danger > td, .table > thead > tr.danger > th, .table > tbody > tr.danger > th, .table > tfoot > tr.danger > th {
|
||||
background-color: var(--back-sub);
|
||||
}
|
||||
.table > tbody > tr.warning > td{
|
||||
background-color:var(--back-sub);
|
||||
}
|
||||
@@ -443,4 +443,7 @@ a {
|
||||
|
||||
.search-highlight, .search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td{
|
||||
background-color:var(--back-sub);
|
||||
}
|
||||
@@ -431,4 +431,7 @@ a {
|
||||
|
||||
.search-highlight, .search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td{
|
||||
background-color:var(--back-sub);
|
||||
}
|
||||
@@ -426,4 +426,7 @@ input[type=text], input[type=search] {
|
||||
}
|
||||
.search-highlight, .search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td{
|
||||
background-color:var(--back-sub);
|
||||
}
|
||||
@@ -438,4 +438,7 @@ a {
|
||||
|
||||
.search-highlight, .search-highlight:hover {
|
||||
background-color: #e9d15b;
|
||||
}
|
||||
.table > tbody > tr.warning > td{
|
||||
background-color:var(--back-sub);
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user