Compare commits
431 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 66f8ac1cd1 | |||
| 775df0ab60 | |||
| 687f8971b1 | |||
| bc2a455a89 | |||
| 97c28d9adc | |||
| 163b3f6c0b | |||
| 9b3df40ed6 | |||
| 1c8ee0f706 | |||
| d7c5a6af71 | |||
| 743264fd0e | |||
| f7da87520c | |||
| ec854ddc1d | |||
| 1a8b2a169b | |||
| 43acd3b488 | |||
| c3a6874b16 | |||
| 97731cd7c8 | |||
| b7a5467f8b | |||
| 2f8a435e18 | |||
| 9ca40716ce | |||
| 7518cab7c8 | |||
| 8d36971c8b | |||
| 371a5bf4d6 | |||
| cfc4229308 | |||
| 8bf01715a9 | |||
| 55f5e7866d | |||
| 9c205f63ae | |||
| 0cc7389b85 | |||
| e21d0729c1 | |||
| c46dc99e86 | |||
| 64a8d1d207 | |||
| 8de59d117f | |||
| d5e702ac74 | |||
| 6113afe36e | |||
| 305df42f92 | |||
| 9aa0356de7 | |||
| d2dcb29dcb | |||
| 39e06a8856 | |||
| 3ef578eb56 | |||
| 11a1ab971c | |||
| d226cf189b | |||
| c082d8b90e | |||
| b1985a08c4 | |||
| 9bafe795b0 | |||
| bb4c084435 | |||
| feeb1c7ac8 | |||
| c2cfd8ff53 | |||
| 20ad4fb681 | |||
| 06a1fe5b38 | |||
| b6f87633f5 | |||
| e426846c23 | |||
| 27898e660c | |||
| 0d9d02c6d6 | |||
| 7c854c0a5c | |||
| efc892cf5e | |||
| ba4c37a7f4 | |||
| f0c5560c1b | |||
| 774962c122 | |||
| 0a9fd0b867 | |||
| 5c94ca1403 | |||
| 86bc409d3a | |||
| 24841a75d4 | |||
| a02a04d601 | |||
| 3997085faf | |||
| 3ac92e1425 | |||
| 5661e69520 | |||
| cdcd19a7d8 | |||
| 489895a5fa | |||
| 1122562b4e | |||
| 65e46c914c | |||
| 4ffe13d3c2 | |||
| 5df76155ce | |||
| e1c33d4eff | |||
| 2fc7a15372 | |||
| 9056d48775 | |||
| 9fefdea9de | |||
| 2239c6f7e2 | |||
| da0efaa278 | |||
| 69bde0443e | |||
| 6400bdc266 | |||
| ffd252a00c | |||
| 7fcf6f2463 | |||
| 5103f28598 | |||
| 60d7128a5e | |||
| 2c5a0d370c | |||
| bcbe517446 | |||
| d9a9bd1c0d | |||
| 2166fcec41 | |||
| 9a5d431962 | |||
| 6dc0846f38 | |||
| 50431c046f | |||
| f0ecab7bb1 | |||
| 7cc8b39863 | |||
| ae259f36ae | |||
| cd2997b674 | |||
| b4ff07ce9e | |||
| 8122236944 | |||
| 56c4fa7c27 | |||
| 602c2698d2 | |||
| ff0b68724f | |||
| d4ac7530b6 | |||
| 4aded5e117 | |||
| 8d03ce5e2c | |||
| 15da39d44a | |||
| 077d343f01 | |||
| 47ee2a8153 | |||
| ae95ee49f1 | |||
| 2ac558494d | |||
| ede16ad2c2 | |||
| 1e34398c99 | |||
| 7a5fcfb87a | |||
| 1fa624420e | |||
| 6a9131e771 | |||
| 383bd6bb45 | |||
| 097821b818 | |||
| 2e56c9b521 | |||
| b95d24b5eb | |||
| f91e1d58ad | |||
| 7c37c70164 | |||
| 52dc5aa4ba | |||
| 23cbee9493 | |||
| 7c21158680 | |||
| 30f4af3ac2 | |||
| b1fa50cde2 | |||
| 236684ec92 | |||
| c45e777324 | |||
| 53499b1e29 | |||
| 04b6f023ae | |||
| 3c7d63c060 | |||
| 7cb1ca8754 | |||
| 52e33a8b0e | |||
| 0f5fbb6a04 | |||
| 6d5ace0458 | |||
| 6f14355cbc | |||
| eb81c290dc | |||
| 2f9e097854 | |||
| 97aeb1fcec | |||
| e6d259bac0 | |||
| 8887d40b86 | |||
| 3d8e0b707e | |||
| 71a7176a6e | |||
| def89bfa0c | |||
| f1cb7ee410 | |||
| 84c0f50266 | |||
| f51b312843 | |||
| 3d3a4b02fc | |||
| 276f534ded | |||
| 1d47d9e52b | |||
| 2106b64da6 | |||
| fa79a6c15f | |||
| 761da534f3 | |||
| b362951c95 | |||
| 25f69a7bd2 | |||
| f6a6478804 | |||
| 3282702c73 | |||
| 4e5c878b73 | |||
| 5711706367 | |||
| a930661150 | |||
| 7cb4740359 | |||
| 9f8f028484 | |||
| d0b9e956df | |||
| c1eee2cc72 | |||
| f32183d51b | |||
| 73f30c0a41 | |||
| c233d7fb1c | |||
| dea0fcefbd | |||
| 38678d4646 | |||
| 476a5cbc02 | |||
| bc4c6abe06 | |||
| 73f61ce032 | |||
| 12c7223bcd | |||
| de856d6045 | |||
| b7efb58733 | |||
| 28b0d8cf0f | |||
| 88ae8858e8 | |||
| 0bc0a116aa | |||
| e670ffe349 | |||
| a94f1c4a64 | |||
| b503b672ba | |||
| 72296eea5c | |||
| bc023a2566 | |||
| 2f7e22be1e | |||
| 9409965239 | |||
| f54c92ade2 | |||
| b1fb70cb7b | |||
| 9e08936cbc | |||
| cd385e0865 | |||
| 1e3281c76c | |||
| af4d62759f | |||
| 9452973845 | |||
| 8e23787888 | |||
| 3b16157d6b | |||
| 3ec3d38c9f | |||
| ae430959a4 | |||
| 85a85082b7 | |||
| 5acb493efd | |||
| 515b14a001 | |||
| 4eed2baa31 | |||
| 453f2c3b0e | |||
| bc78d341a0 | |||
| da579a302c | |||
| edf191b724 | |||
| 12d86bd6e2 | |||
| c4f11de90d | |||
| 8fb61cf5f8 | |||
| 4e83b06d71 | |||
| 23e613f903 | |||
| f1c82ca732 | |||
| 2543fa6b98 | |||
| 7c34652da0 | |||
| aa3f94973f | |||
| 1ec303931a | |||
| d359bcb88d | |||
| 28059c878a | |||
| b7bcfaccc9 | |||
| f4a3f896bd | |||
| 0303df4b25 | |||
| 9151868839 | |||
| 8c6aaec9ce | |||
| fb228d6ded | |||
| 1360ce90a5 | |||
| 3549afe157 | |||
| cfb780b20b | |||
| eb9f17122e | |||
| 2ef45afb2b | |||
| c8baf4c6ad | |||
| 0b20cf6d70 | |||
| ecc6bd8a24 | |||
| 3c9c89355e | |||
| 43479efed0 | |||
| 80279a95ae | |||
| ac055c01dc | |||
| 5ff72420a6 | |||
| 55b33c1042 | |||
| a499a92bb7 | |||
| e7ae7742b0 | |||
| 98f2e0271b | |||
| e721665fd8 | |||
| cd43fc50fb | |||
| 06803092c5 | |||
| 0312ecf09d | |||
| 0ed50f4e58 | |||
| 3f105cd3b2 | |||
| ab0c5bcd9d | |||
| 5ba01728d9 | |||
| ae0eb378e4 | |||
| ad8a2387f0 | |||
| 4fa01350c3 | |||
| d3161fad02 | |||
| 36eb51b52f | |||
| 8ff109e9da | |||
| 15da3b831d | |||
| 0c6441ebed | |||
| fbfc9d123c | |||
| cd942196cc | |||
| f1edbc9810 | |||
| 66e64cb136 | |||
| 1ef3eb94db | |||
| 25e4b7d59d | |||
| 9605dec22a | |||
| ca937667b4 | |||
| e9c61903f1 | |||
| 14b7319b63 | |||
| 9d641573b5 | |||
| 3605aa8f5a | |||
| 0817308822 | |||
| bdfac1a345 | |||
| f7a9be92ca | |||
| 56ba8a7e24 | |||
| cf62761d18 | |||
| d23e178c62 | |||
| 7353ecd388 | |||
| 18663c2599 | |||
| 5b8e0b3af1 | |||
| dab83091d2 | |||
| 4c0be7ec98 | |||
| 018f71a157 | |||
| 9f03f0f6f6 | |||
| da40c0ad48 | |||
| c70c8ce856 | |||
| fe49ac79d1 | |||
| 687a764fc1 | |||
| 81be84568e | |||
| 61fa0bda4d | |||
| 81d2a3acda | |||
| 931d81d825 | |||
| bcebc1e33b | |||
| ba0483b33e | |||
| 97b9f96030 | |||
| 891b5b2882 | |||
| e21660ae05 | |||
| 53392d6069 | |||
| 3469e49470 | |||
| e9224f094e | |||
| 25c10c3819 | |||
| b9419c7454 | |||
| b07c4caa37 | |||
| aa52bc6c6a | |||
| 5a7e35c0e8 | |||
| bae200edd7 | |||
| 2fd197c2db | |||
| 36484d50ef | |||
| 2b7c8cf82b | |||
| 0424308863 | |||
| 78580136f6 | |||
| 420c216973 | |||
| 9c6fa18454 | |||
| 70c766e8b3 | |||
| 0b2ce7be07 | |||
| 3d48dd19cb | |||
| 08bab4f101 | |||
| 95b49f8deb | |||
| 4f5d536e32 | |||
| 9dbc5070f8 | |||
| 055a2f827f | |||
| 8d3fe423e1 | |||
| 1377725a97 | |||
| 58ccfe9226 | |||
| 05ac9f4a68 | |||
| 0889cd61cf | |||
| 8168ca4074 | |||
| de399a9f8f | |||
| af150f0192 | |||
| c194c8a0c8 | |||
| a7b83fc531 | |||
| ef22da622d | |||
| 8443796cbe | |||
| ac996a771c | |||
| 942eaac2ee | |||
| ada2a2cd43 | |||
| 06ba9356ca | |||
| e034f7b674 | |||
| 4d14243f57 | |||
| 88a371082d | |||
| ee7e26ae8d | |||
| 9d93c72534 | |||
| 44b72e0f5f | |||
| d91d226652 | |||
| 091ef62cbe | |||
| 8316a4eb92 | |||
| b4518677bd | |||
| 23cf556a8b | |||
| c0f83a7927 | |||
| 5a1062f0f4 | |||
| c32676596c | |||
| f75917d34d | |||
| c55f2d5417 | |||
| e267f5491a | |||
| 571ce5b741 | |||
| 733b0750a2 | |||
| 9369165007 | |||
| f75d348dc0 | |||
| dcab1381e7 | |||
| 0924d2144b | |||
| 9cae4f1d1b | |||
| ca70988879 | |||
| 421c9baecc | |||
| 5c9e84f663 | |||
| fbb5f1445a | |||
| 07e0fec1de | |||
| c6cbf3712e | |||
| 0f777b3168 | |||
| 62ad3fad1c | |||
| eb1e287c15 | |||
| 3eab44f748 | |||
| 1885e73704 | |||
| 24910433a1 | |||
| 1899e4d1e8 | |||
| 481eb2c7f0 | |||
| 51d7f2b97b | |||
| 9b2eda2d70 | |||
| 41b75704e3 | |||
| 20220764bb | |||
| abd2349604 | |||
| ac4f91918e | |||
| 28f0b72bcd | |||
| ad7bc6f38a | |||
| 72feaee6c0 | |||
| 4ac3650d64 | |||
| 3877770160 | |||
| 3192a68b06 | |||
| 284b4d869f | |||
| 6b6a079440 | |||
| a0624fe179 | |||
| d598f75721 | |||
| d51eca20f0 | |||
| 9b5790b7e6 | |||
| a8a00f0a79 | |||
| cbd16174d8 | |||
| 448aefac28 | |||
| b23cd6d4f0 | |||
| b0ea1a31dc | |||
| 11a2f96b4f | |||
| 7361977cdc | |||
| 659703bd7d | |||
| 3aff97ace1 | |||
| 6e82de2f47 | |||
| ae505ef44d | |||
| e86e96e159 | |||
| 93428e1ed4 | |||
| 61e1650542 | |||
| ab54ac9408 | |||
| dcbd407698 | |||
| 4e7fea3468 | |||
| 3ef25c3a4d | |||
| 22596f4bb8 | |||
| 8fdca7f42b | |||
| 1f04cfdb44 | |||
| 04c130e596 | |||
| 7fa9214beb | |||
| ea63049b4b | |||
| e94b5ac435 | |||
| 9cf5f30c77 | |||
| e8f2e50ada | |||
| 3527902ba3 | |||
| f60ea9581d | |||
| 74fe3dc733 | |||
| 96ec96ff7f | |||
| 4fd1827576 | |||
| 0d4e9c183b | |||
| 1ff2d15c4a | |||
| 482a7b2a3a | |||
| e5cc6ec972 | |||
| 07585809b3 | |||
| a33ca39237 | |||
| 98bcd82108 | |||
| d2c486bb1e | |||
| 267997f0a6 | |||
| 0172fe6403 | |||
| 509bbbc685 | |||
| 309229619b | |||
| 157944b774 |
@@ -2702,6 +2702,123 @@
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "dsferruzza",
|
||||
"name": "David Sferruzza",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1931963?v=4",
|
||||
"profile": "https://david.sferruzza.fr/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "rnelsonee",
|
||||
"name": "Rick Nelson",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/19511639?v=4",
|
||||
"profile": "https://github.com/rnelsonee",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "BasO12",
|
||||
"name": "BasO12",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/94169344?v=4",
|
||||
"profile": "https://github.com/BasO12",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "Vautia",
|
||||
"name": "Vautia",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/111710123?v=4",
|
||||
"profile": "https://github.com/Vautia",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "chartjes",
|
||||
"name": "Chris Hartjes",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/28321?v=4",
|
||||
"profile": "http://www.littlehart.net/atthekeyboard",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "geo-chen",
|
||||
"name": "geo-chen",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/2404584?v=4",
|
||||
"profile": "https://github.com/geo-chen",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "nh314",
|
||||
"name": "Phan Nguyen",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/6006620?v=4",
|
||||
"profile": "https://github.com/nh314",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "StarlessNights",
|
||||
"name": "Iisakki Jaakkola",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/115993812?v=4",
|
||||
"profile": "https://github.com/StarlessNights",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "eltociear",
|
||||
"name": "Ikko Ashimine",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/22633385?v=4",
|
||||
"profile": "https://bandism.net/",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "lukasfehling",
|
||||
"name": "Lukas Fehling",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/56871540?v=4",
|
||||
"profile": "https://github.com/lukasfehling",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "fernando-almeida",
|
||||
"name": "Fernando Almeida",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/1975990?v=4",
|
||||
"profile": "https://github.com/fernando-almeida",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "akemidx",
|
||||
"name": "akemidx",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/116301219?v=4",
|
||||
"profile": "https://github.com/akemidx",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
},
|
||||
{
|
||||
"login": "oguzbilgic",
|
||||
"name": "Oguz Bilgic",
|
||||
"avatar_url": "https://avatars.githubusercontent.com/u/144778?v=4",
|
||||
"profile": "http://oguz.site",
|
||||
"contributions": [
|
||||
"code"
|
||||
]
|
||||
}
|
||||
]
|
||||
}
|
||||
|
||||
+1
-1
@@ -21,7 +21,7 @@ PUBLIC_FILESYSTEM_DISK=local_public
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3309
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=snipeit-local
|
||||
DB_USERNAME=snipeit-local
|
||||
DB_PASSWORD=snipeit-local
|
||||
|
||||
+8
-1
@@ -24,7 +24,7 @@ PUBLIC_FILESYSTEM_DISK=local_public
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_PORT=3309
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=null
|
||||
DB_USERNAME=null
|
||||
DB_PASSWORD=null
|
||||
@@ -173,3 +173,10 @@ IMPORT_MEMORY_LIMIT=500M
|
||||
REPORT_TIME_LIMIT=12000
|
||||
REQUIRE_SAML=false
|
||||
API_THROTTLE_PER_MINUTE=120
|
||||
CSV_ESCAPE_FORMULAS=true
|
||||
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: SCIM
|
||||
# --------------------------------------------
|
||||
SCIM_TRACE=false
|
||||
SCIM_STANDARDS_COMPLIANCE=false
|
||||
+1
-1
@@ -14,7 +14,7 @@ FILESYSTEM_DISK=local
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=sqlite_testing
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3309
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=testing.sqlite
|
||||
DB_USERNAME=null
|
||||
DB_PASSWORD=null
|
||||
|
||||
+2
-2
@@ -14,7 +14,7 @@ FILESYSTEM_DISK=local
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=sqlite
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3309
|
||||
DB_PORT=3306
|
||||
DB_DATABASE='sqlite_testing'
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=null
|
||||
@@ -35,4 +35,4 @@ IMAGE_LIB=gd
|
||||
# --------------------------------------------
|
||||
# OPTIONAL: APP LOG FORMAT
|
||||
# --------------------------------------------
|
||||
LOG_CHANNEL=single
|
||||
LOG_CHANNEL=single
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ APP_URL=http://snipe-it.localapp
|
||||
DB_CONNECTION=mysql
|
||||
DB_DEFAULT=mysql
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3309
|
||||
DB_PORT=3306
|
||||
DB_DATABASE=snipeittests
|
||||
DB_USERNAME=snipeit
|
||||
DB_PASSWORD=snipe
|
||||
|
||||
+1
-1
@@ -4,7 +4,7 @@ APP_URL=http://snipe-it.localapp
|
||||
DB_CONNECTION=sqlite_testing
|
||||
DB_DEFAULT=sqlite_testing
|
||||
DB_HOST=localhost
|
||||
DB_PORT=3309
|
||||
DB_PORT=3306
|
||||
APP_KEY=base64:tu9NRh/a6+dCXBDGvg0Gv/0TcABnFsbT4AKxrr8mwQo=
|
||||
|
||||
|
||||
|
||||
@@ -26,7 +26,7 @@ jobs:
|
||||
language: [ 'javascript' ]
|
||||
steps:
|
||||
- name: Checkout repository
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3.1.0
|
||||
|
||||
# Initializes the CodeQL tools for scanning.
|
||||
- name: Initialize CodeQL
|
||||
|
||||
@@ -32,11 +32,11 @@ jobs:
|
||||
steps:
|
||||
# Checkout the repository to the GitHub Actions runner
|
||||
- name: Checkout code
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3.1.0
|
||||
|
||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||
- name: Run Codacy Analysis CLI
|
||||
uses: codacy/codacy-analysis-cli-action@v4.1.0
|
||||
uses: codacy/codacy-analysis-cli-action@v4.2.0
|
||||
with:
|
||||
# Check https://github.com/codacy/codacy-analysis-cli#project-token to get your project token from your Codacy repository
|
||||
# You can also omit the token and run the tools that support default configurations
|
||||
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
steps:
|
||||
# https://github.com/actions/checkout
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3.1.0
|
||||
|
||||
# https://github.com/docker/setup-buildx-action
|
||||
- name: Setup Docker Buildx
|
||||
|
||||
@@ -41,7 +41,7 @@ jobs:
|
||||
steps:
|
||||
# https://github.com/actions/checkout
|
||||
- name: Checkout codebase
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3.1.0
|
||||
|
||||
# https://github.com/docker/setup-buildx-action
|
||||
- name: Setup Docker Buildx
|
||||
|
||||
+2
-1
@@ -24,6 +24,7 @@ php7.4-mbstring \
|
||||
php7.4-zip \
|
||||
php7.4-bcmath \
|
||||
php7.4-redis \
|
||||
php-memcached \
|
||||
patch \
|
||||
curl \
|
||||
wget \
|
||||
@@ -139,4 +140,4 @@ RUN chmod +x /startup.sh /usr/bin/supervisor-exit-event-listener
|
||||
CMD ["/startup.sh"]
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 443
|
||||
EXPOSE 443
|
||||
|
||||
+2
-1
@@ -28,6 +28,7 @@ RUN apk add --no-cache \
|
||||
php7-xmlreader \
|
||||
php7-sodium \
|
||||
php7-redis \
|
||||
php7-pecl-memcached \
|
||||
curl \
|
||||
wget \
|
||||
vim \
|
||||
@@ -85,4 +86,4 @@ ENTRYPOINT ["/sbin/tini", "--"]
|
||||
|
||||
CMD ["/entrypoint.sh"]
|
||||
|
||||
EXPOSE 80
|
||||
EXPOSE 80
|
||||
|
||||
@@ -75,14 +75,14 @@ RUN set -eux; \
|
||||
rm snipeit.tar.gz; \
|
||||
# Install composer php dependencies
|
||||
if [ "$ENVIRONMENT" = "production" ]; then \
|
||||
echo "production enviroment detected!"; \
|
||||
echo "production environment detected!"; \
|
||||
composer update \
|
||||
--no-cache \
|
||||
--no-dev \
|
||||
--optimize-autoloader \
|
||||
--working-dir=/var/www/html; \
|
||||
else \
|
||||
echo "development enviroment detected!"; \
|
||||
echo "development environment detected!"; \
|
||||
apk add --no-cache \
|
||||
${DEV_PACKAGES}; \
|
||||
composer update \
|
||||
@@ -100,4 +100,4 @@ COPY --chown=www-data:www-data docker/docker-secrets.env /var/www/html/.env
|
||||
COPY --chmod=655 docker/docker-entrypoint.sh /usr/local/bin/docker-snipeit-entrypoint
|
||||
COPY docker/column-statistics.cnf /etc/mysql/conf.d/column-statistics.cnf
|
||||
ENTRYPOINT [ "/usr/local/bin/docker-snipeit-entrypoint" ]
|
||||
CMD [ "/usr/local/bin/docker-php-entrypoint", "php-fpm" ]
|
||||
CMD [ "/usr/local/bin/docker-php-entrypoint", "php-fpm" ]
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
 [](https://crowdin.com/project/snipe-it) [](https://hub.docker.com/r/snipe/snipe-it/) [](https://twitter.com/snipeitapp) [](https://www.codacy.com/app/snipe/snipe-it?utm_source=github.com&utm_medium=referral&utm_content=snipe/snipe-it&utm_campaign=Badge_Grade)
|
||||
[](#contributors) [](https://discord.gg/yZFtShAcKk) [](https://huntr.dev)
|
||||
[](#contributors) [](https://discord.gg/yZFtShAcKk) [](https://huntr.dev)
|
||||
|
||||
## Snipe-IT - Open Source Asset Management System
|
||||
|
||||
@@ -59,7 +59,7 @@ Since the release of the JSON REST API, several third-party developers have been
|
||||
- [SnipeSharp - .NET module in C#](https://github.com/barrycarey/SnipeSharp) by [@barrycarey](https://github.com/barrycarey)
|
||||
- [InQRy -unmaintained-](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
|
||||
- [SnipeitPS](https://github.com/snazy2000/SnipeitPS) by [@snazy2000](https://github.com/snazy2000) - Powershell API Wrapper for Snipe-it
|
||||
- [jamf2snipe](https://github.com/ParadoxGuitarist/jamf2snipe) by [@ParadoxGuitarist](https://github.com/ParadoxGuitarist) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance
|
||||
- [jamf2snipe](https://github.com/grokability/jamf2snipe) - Python script to sync assets between a JAMFPro instance and a Snipe-IT instance
|
||||
- [Marksman](https://github.com/Scope-IT/marksman) - A Windows agent for Snipe-IT
|
||||
- [Snipe-IT plugin for Jira Service Desk](https://marketplace.atlassian.com/apps/1220964/snipe-it-for-jira)
|
||||
- [Python 3 CSV importer](https://github.com/gastamper/snipeit-csvimporter) - allows importing assets into Snipe-IT based on Item Name rather than Asset Tag.
|
||||
@@ -137,7 +137,9 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||
| [<img src="https://avatars.githubusercontent.com/u/1911435?v=4" width="110px;"/><br /><sub>Adam</sub>](http://www.aboutcher.co.uk)<br />[💻](https://github.com/snipe/snipe-it/commits?author=adamboutcher "Code") | [<img src="https://avatars.githubusercontent.com/u/16104273?v=4" width="110px;"/><br /><sub>Ian</sub>](https://snksrv.com)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sneak-it "Code") | [<img src="https://avatars.githubusercontent.com/u/4023909?v=4" width="110px;"/><br /><sub>Shao Yu-Lung (Allen)</sub>](http://blog.bestlong.idv.tw/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=bestlong "Code") | [<img src="https://avatars.githubusercontent.com/u/76475453?v=4" width="110px;"/><br /><sub>Haxatron</sub>](https://github.com/Haxatron)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Haxatron "Code") | [<img src="https://avatars.githubusercontent.com/u/88776392?v=4" width="110px;"/><br /><sub>PlaneNuts</sub>](https://github.com/PlaneNuts)<br />[💻](https://github.com/snipe/snipe-it/commits?author=PlaneNuts "Code") | [<img src="https://avatars.githubusercontent.com/u/3842948?v=4" width="110px;"/><br /><sub>Bradley Coudriet</sub>](http://bjcpgd.cias.rit.edu)<br />[💻](https://github.com/snipe/snipe-it/commits?author=exula "Code") | [<img src="https://avatars.githubusercontent.com/u/21966173?v=4" width="110px;"/><br /><sub>Dalton Durst</sub>](https://daltondur.st)<br />[💻](https://github.com/snipe/snipe-it/commits?author=UniversalSuperBox "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/38761237?v=4" width="110px;"/><br /><sub>Alex Janes</sub>](https://adagiohealth.org)<br />[💻](https://github.com/snipe/snipe-it/commits?author=adagioajanes "Code") | [<img src="https://avatars.githubusercontent.com/u/32387849?v=4" width="110px;"/><br /><sub>Nuraeil</sub>](https://github.com/nuraeil)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nuraeil "Code") | [<img src="https://avatars.githubusercontent.com/u/48162670?v=4" width="110px;"/><br /><sub>TenOfTens</sub>](https://github.com/TenOfTens)<br />[💻](https://github.com/snipe/snipe-it/commits?author=TenOfTens "Code") | [<img src="https://avatars.githubusercontent.com/u/9415391?v=4" width="110px;"/><br /><sub>waffle</sub>](https://ditisjens.be/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=insert-waffle "Code") | [<img src="https://avatars.githubusercontent.com/u/19945501?v=4" width="110px;"/><br /><sub>Yevhenii Huzii</sub>](https://github.com/QveenSi)<br />[💻](https://github.com/snipe/snipe-it/commits?author=QveenSi "Code") | [<img src="https://avatars.githubusercontent.com/u/3839381?v=4" width="110px;"/><br /><sub>Achmad Fienan Rahardianto</sub>](https://github.com/veenone)<br />[💻](https://github.com/snipe/snipe-it/commits?author=veenone "Code") | [<img src="https://avatars.githubusercontent.com/u/19945501?v=4" width="110px;"/><br /><sub>Yevhenii Huzii</sub>](https://github.com/QveenSi)<br />[💻](https://github.com/snipe/snipe-it/commits?author=QveenSi "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/97299851?v=4" width="110px;"/><br /><sub>Christian Weirich</sub>](https://github.com/chrisweirich)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chrisweirich "Code") | [<img src="https://avatars.githubusercontent.com/u/1294403?v=4" width="110px;"/><br /><sub>denzfarid</sub>](https://github.com/denzfarid)<br /> | [<img src="https://avatars.githubusercontent.com/u/94018771?v=4" width="110px;"/><br /><sub>ntbutler-nbcs</sub>](https://github.com/ntbutler-nbcs)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ntbutler-nbcs "Code") | [<img src="https://avatars.githubusercontent.com/u/172697?v=4" width="110px;"/><br /><sub>Naveen</sub>](https://naveensrinivasan.dev)<br />[💻](https://github.com/snipe/snipe-it/commits?author=naveensrinivasan "Code") | [<img src="https://avatars.githubusercontent.com/u/55674383?v=4" width="110px;"/><br /><sub>Mike Roquemore</sub>](https://github.com/mikeroq)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mikeroq "Code") | [<img src="https://avatars.githubusercontent.com/u/7991086?v=4" width="110px;"/><br /><sub>Daniel Reeder</sub>](https://github.com/reederda)<br />[🌍](#translation-reederda "Translation") [🌍](#translation-reederda "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=reederda "Code") | [<img src="https://avatars.githubusercontent.com/u/109422491?v=4" width="110px;"/><br /><sub>vickyjaura183</sub>](https://github.com/vickyjaura183)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vickyjaura183 "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/32363424?v=4" width="110px;"/><br /><sub>Peace</sub>](https://github.com/julian-piehl)<br />[💻](https://github.com/snipe/snipe-it/commits?author=julian-piehl "Code") | [<img src="https://avatars.githubusercontent.com/u/231528?v=4" width="110px;"/><br /><sub>Kyle Gordon</sub>](https://github.com/kylegordon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kylegordon "Code") | [<img src="https://avatars.githubusercontent.com/u/53009155?v=4" width="110px;"/><br /><sub>Katharina Drexel</sub>](http://www.bfh.ch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sunflowerbofh "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/32363424?v=4" width="110px;"/><br /><sub>Peace</sub>](https://github.com/julian-piehl)<br />[💻](https://github.com/snipe/snipe-it/commits?author=julian-piehl "Code") | [<img src="https://avatars.githubusercontent.com/u/231528?v=4" width="110px;"/><br /><sub>Kyle Gordon</sub>](https://github.com/kylegordon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kylegordon "Code") | [<img src="https://avatars.githubusercontent.com/u/53009155?v=4" width="110px;"/><br /><sub>Katharina Drexel</sub>](http://www.bfh.ch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sunflowerbofh "Code") | [<img src="https://avatars.githubusercontent.com/u/1931963?v=4" width="110px;"/><br /><sub>David Sferruzza</sub>](https://david.sferruzza.fr/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dsferruzza "Code") | [<img src="https://avatars.githubusercontent.com/u/19511639?v=4" width="110px;"/><br /><sub>Rick Nelson</sub>](https://github.com/rnelsonee)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rnelsonee "Code") | [<img src="https://avatars.githubusercontent.com/u/94169344?v=4" width="110px;"/><br /><sub>BasO12</sub>](https://github.com/BasO12)<br />[💻](https://github.com/snipe/snipe-it/commits?author=BasO12 "Code") | [<img src="https://avatars.githubusercontent.com/u/111710123?v=4" width="110px;"/><br /><sub>Vautia</sub>](https://github.com/Vautia)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Vautia "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/28321?v=4" width="110px;"/><br /><sub>Chris Hartjes</sub>](http://www.littlehart.net/atthekeyboard)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chartjes "Code") | [<img src="https://avatars.githubusercontent.com/u/2404584?v=4" width="110px;"/><br /><sub>geo-chen</sub>](https://github.com/geo-chen)<br />[💻](https://github.com/snipe/snipe-it/commits?author=geo-chen "Code") | [<img src="https://avatars.githubusercontent.com/u/6006620?v=4" width="110px;"/><br /><sub>Phan Nguyen</sub>](https://github.com/nh314)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nh314 "Code") | [<img src="https://avatars.githubusercontent.com/u/115993812?v=4" width="110px;"/><br /><sub>Iisakki Jaakkola</sub>](https://github.com/StarlessNights)<br />[💻](https://github.com/snipe/snipe-it/commits?author=StarlessNights "Code") | [<img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="110px;"/><br /><sub>Ikko Ashimine</sub>](https://bandism.net/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=eltociear "Code") | [<img src="https://avatars.githubusercontent.com/u/56871540?v=4" width="110px;"/><br /><sub>Lukas Fehling</sub>](https://github.com/lukasfehling)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lukasfehling "Code") | [<img src="https://avatars.githubusercontent.com/u/1975990?v=4" width="110px;"/><br /><sub>Fernando Almeida</sub>](https://github.com/fernando-almeida)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fernando-almeida "Code") |
|
||||
| [<img src="https://avatars.githubusercontent.com/u/116301219?v=4" width="110px;"/><br /><sub>akemidx</sub>](https://github.com/akemidx)<br />[💻](https://github.com/snipe/snipe-it/commits?author=akemidx "Code") | [<img src="https://avatars.githubusercontent.com/u/144778?v=4" width="110px;"/><br /><sub>Oguz Bilgic</sub>](http://oguz.site)<br />[💻](https://github.com/snipe/snipe-it/commits?author=oguzbilgic "Code") |
|
||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||
|
||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||
|
||||
+65
@@ -0,0 +1,65 @@
|
||||
# Using the Test Suite
|
||||
|
||||
This document is targeted at developers looking to make modifications to
|
||||
this application's code base and want to run the existing test suite.
|
||||
|
||||
|
||||
## Setup
|
||||
|
||||
Follow the instructions for installing the application locally,
|
||||
making sure to have also run the [database migrations](link to db migrations).
|
||||
|
||||
|
||||
## Unit Tests
|
||||
|
||||
The application will use values in the `.env.testing` file located
|
||||
in the root directory to override the
|
||||
default settings and/or other values that exist in your `.env` files.
|
||||
|
||||
Make sure to modify the section in `.env.testing` that has the
|
||||
database settings. In the example below, it is connecting to the
|
||||
[MariaDB](link-to-maria-db) server that is used if you install the
|
||||
application using [Docker](https://docker.com).
|
||||
|
||||
```dotenv
|
||||
# --------------------------------------------
|
||||
# REQUIRED: DATABASE SETTINGS
|
||||
# --------------------------------------------
|
||||
DB_CONNECTION=mysql
|
||||
DB_HOST=127.0.0.1
|
||||
DB_DATABASE=snipeit
|
||||
DB_USERNAME=root
|
||||
DB_PASSWORD=changeme1234
|
||||
```
|
||||
|
||||
To run the entire unit test suite, use the following command from your terminal:
|
||||
|
||||
`php artisan test --env=testing`
|
||||
|
||||
To run individual test files, you can pass the path to the test that
|
||||
you want to run.
|
||||
|
||||
`php artisan test --env=testing tests/Unit/AccessoryTest.php`
|
||||
|
||||
## Browser Tests
|
||||
|
||||
The browser tests use [Dusk](https://laravel.com/docs/8.x/dusk) to run them.
|
||||
When troubleshooting any problems, make sure that your `.env` file is configured
|
||||
correctly to run the existing application.
|
||||
|
||||
### Test Setup
|
||||
|
||||
Your application needs to be configued and up and running in order for the browser
|
||||
tests to actually run. When running the tests locally, you can start the application
|
||||
using the following command:
|
||||
|
||||
`php artisan serve`
|
||||
|
||||
|
||||
To run the test suite use the following command from another terminal tab or window:
|
||||
|
||||
`php artisan dusk`
|
||||
|
||||
To run individual test files, you can pass the path to the test that you want to run.
|
||||
|
||||
`php artisan dusk tests/Browser/LoginTest.php`
|
||||
@@ -148,7 +148,7 @@
|
||||
"image": "heroku/php",
|
||||
"addons": [
|
||||
"cleardb:ignite",
|
||||
"heroku-redis:hobby-dev",
|
||||
"heroku-redis:mini",
|
||||
"papertrail:choklad"
|
||||
]
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,7 +22,7 @@ class CheckoutLicenseToAllUsers extends Command
|
||||
*
|
||||
* @var string
|
||||
*/
|
||||
protected $description = 'Command description';
|
||||
protected $description = 'Checks out licenses to all users';
|
||||
|
||||
/**
|
||||
* Create a new command instance.
|
||||
|
||||
@@ -175,6 +175,8 @@ class LdapSync extends Command
|
||||
$tmp_pass = substr(str_shuffle('0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ'), 0, 20);
|
||||
$pass = bcrypt($tmp_pass);
|
||||
|
||||
$manager_cache = [];
|
||||
|
||||
for ($i = 0; $i < $results['count']; $i++) {
|
||||
$item = [];
|
||||
$item['username'] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : '';
|
||||
@@ -217,20 +219,42 @@ class LdapSync extends Command
|
||||
$user->department_id = $department->id;
|
||||
|
||||
if($item['manager'] != null) {
|
||||
// Get the LDAP Manager
|
||||
$ldap_manager = Ldap::findLdapUsers($item['manager'], -1, $this->option('filter'));
|
||||
|
||||
if($ldap_manager["count"] > 0) {
|
||||
// Get the Managers username
|
||||
$ldapManagerUsername = $ldap_manager[0][$ldap_result_username][0];
|
||||
|
||||
// Get User from Manager username.
|
||||
$ldap_manager = User::where('username', $ldapManagerUsername)->first();
|
||||
|
||||
if ( $ldap_manager && isset($ldap_manager->id) ) {
|
||||
// Link user to manager id.
|
||||
$user->manager_id = $ldap_manager->id;
|
||||
// Check Cache first
|
||||
if (isset($manager_cache[$item['manager']])) {
|
||||
// found in cache; use that and avoid extra lookups
|
||||
$user->manager_id = $manager_cache[$item['manager']];
|
||||
} else {
|
||||
// Get the LDAP Manager
|
||||
try {
|
||||
$ldap_manager = Ldap::findLdapUsers($item['manager'], -1, $this->option('filter'));
|
||||
} catch (\Exception $e) {
|
||||
\Log::warning("Manager lookup caused an exception: " . $e->getMessage() . ". Falling back to direct username lookup");
|
||||
// Hail-mary for Okta manager 'shortnames' - will only work if
|
||||
// Okta configuration is using full email-address-style usernames
|
||||
$ldap_manager = [
|
||||
"count" => 1,
|
||||
0 => [
|
||||
$ldap_result_username => [$item['manager']]
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
if ($ldap_manager["count"] > 0) {
|
||||
|
||||
// Get the Manager's username
|
||||
// PHP LDAP returns every LDAP attribute as an array, and 90% of the time it's an array of just one item. But, hey, it's an array.
|
||||
$ldapManagerUsername = $ldap_manager[0][$ldap_result_username][0];
|
||||
|
||||
// Get User from Manager username.
|
||||
$ldap_manager = User::where('username', $ldapManagerUsername)->first();
|
||||
|
||||
if ($ldap_manager && isset($ldap_manager->id)) {
|
||||
// Link user to manager id.
|
||||
$user->manager_id = $ldap_manager->id;
|
||||
}
|
||||
}
|
||||
$manager_cache[$item['manager']] = $ldap_manager && isset($ldap_manager->id) ? $ldap_manager->id : null; // Store results in cache, even if 'failed'
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -22,12 +22,13 @@ class Helper
|
||||
* @since [v2.0]
|
||||
* @return string
|
||||
*/
|
||||
public static function parseEscapedMarkedown($str)
|
||||
public static function parseEscapedMarkedown($str = null)
|
||||
{
|
||||
$Parsedown = new \Parsedown();
|
||||
$Parsedown->setSafeMode(true);
|
||||
|
||||
if ($str) {
|
||||
return $Parsedown->text(e($str));
|
||||
return $Parsedown->text($str);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,186 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Accessories;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Accessory;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Accessory\HttpFoundation\JsonResponse;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class AccessoriesFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a accessory.
|
||||
*
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param AssetFileRequest $request
|
||||
* @param int $accessoryId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $accessoryId = null)
|
||||
{
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('accessories.show', ['accessory'=>$accessoryId])->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
|
||||
$accessory = Accessory::find($accessoryId);
|
||||
|
||||
if (isset($accessory->id)) {
|
||||
$this->authorize('accessories.files', $accessory);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/accessories')) {
|
||||
Storage::makeDirectory('private_uploads/accessories', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'accessory-'.$accessory->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension == 'svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
\Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/accessories/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Storage::put('private_uploads/accessories/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
|
||||
//Log the upload to the log
|
||||
$accessory->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('accessories.show', $accessory->id)->with('success', trans('general.file_upload_success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.show', $accessory->id)->with('error', trans('general.no_files_uploaded'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('accessories.index')
|
||||
->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected accessory file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $accessoryId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($accessoryId = null, $fileId = null)
|
||||
{
|
||||
$accessory = Accessory::find($accessoryId);
|
||||
|
||||
// the asset is valid
|
||||
if (isset($accessory->id)) {
|
||||
$this->authorize('update', $accessory);
|
||||
$log = Actionlog::find($fileId);
|
||||
|
||||
// Remove the file if one exists
|
||||
if (Storage::exists('accessories/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('accessories/'.$log->filename);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $accessoryId
|
||||
* @param int $fileId
|
||||
* @return \Symfony\Accessory\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($accessoryId = null, $fileId = null, $download = true)
|
||||
{
|
||||
|
||||
\Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||
$accessory = Accessory::find($accessoryId);
|
||||
|
||||
|
||||
|
||||
// the accessory is valid
|
||||
if (isset($accessory->id)) {
|
||||
$this->authorize('view', $accessory);
|
||||
$this->authorize('accessories.files', $accessory);
|
||||
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
$file = 'private_uploads/accessories/'.$log->filename;
|
||||
|
||||
if (Storage::missing($file)) {
|
||||
\Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||
\Log::debug('URL should be '.Storage::url($file));
|
||||
|
||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
|
||||
// won't work, as they're not accessible via the web
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
} else {
|
||||
if ($download != 'true') {
|
||||
\Log::debug('display the file');
|
||||
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
|
||||
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
|
||||
}
|
||||
|
||||
return JsonResponse::create(['error' => 'Failed validation: '], 500);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('accessories.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
}
|
||||
}
|
||||
@@ -19,6 +19,8 @@ use App\Models\Accessory;
|
||||
use App\Models\License;
|
||||
use App\Models\Component;
|
||||
use App\Models\Consumable;
|
||||
use App\Notifications\AcceptanceAssetAcceptedNotification;
|
||||
use App\Notifications\AcceptanceAssetDeclinedNotification;
|
||||
use Illuminate\Http\Request;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Illuminate\Support\Facades\DB;
|
||||
@@ -236,12 +238,49 @@ class AcceptanceController extends Controller
|
||||
}
|
||||
|
||||
$acceptance->accept($sig_filename, $item->getEula(), $pdf_filename);
|
||||
$acceptance->notify(new AcceptanceAssetAcceptedNotification($data));
|
||||
event(new CheckoutAccepted($acceptance));
|
||||
|
||||
$return_msg = trans('admin/users/message.accepted');
|
||||
|
||||
} else {
|
||||
// Format the data to send the declined notification
|
||||
$branding_settings = SettingsController::getPDFBranding();
|
||||
|
||||
// This is the most horriblest
|
||||
switch($acceptance->checkoutable_type){
|
||||
case 'App\Models\Asset':
|
||||
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
||||
break;
|
||||
|
||||
case 'App\Models\Accessory':
|
||||
$assigned_to = User::find($item->assignedTo);
|
||||
break;
|
||||
|
||||
case 'App\Models\LicenseSeat':
|
||||
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
||||
break;
|
||||
|
||||
case 'App\Models\Component':
|
||||
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
||||
break;
|
||||
|
||||
case 'App\Models\Consumable':
|
||||
$assigned_to = User::find($acceptance->assigned_to_id)->present()->fullName;
|
||||
break;
|
||||
}
|
||||
$data = [
|
||||
'item_tag' => $item->asset_tag,
|
||||
'item_model' => $display_model,
|
||||
'item_serial' => $item->serial,
|
||||
'declined_date' => Carbon::parse($acceptance->accepted_at)->format($branding_settings->date_display_format),
|
||||
'assigned_to' => $assigned_to,
|
||||
'company_name' => $branding_settings->site_name,
|
||||
'date_settings' => $branding_settings->date_display_format,
|
||||
];
|
||||
|
||||
$acceptance->decline($sig_filename);
|
||||
$acceptance->notify(new AcceptanceAssetDeclinedNotification($data));
|
||||
event(new CheckoutDeclined($acceptance));
|
||||
$return_msg = trans('admin/users/message.declined');
|
||||
}
|
||||
|
||||
@@ -120,7 +120,6 @@ class AssetsController extends Controller
|
||||
|
||||
if ($filter_non_deprecable_assets) {
|
||||
$non_deprecable_models = AssetModel::select('id')->whereNotNull('depreciation_id')->get();
|
||||
|
||||
$assets->InModelList($non_deprecable_models->toArray());
|
||||
}
|
||||
|
||||
@@ -141,6 +140,14 @@ class AssetsController extends Controller
|
||||
$assets->where('assets.status_id', '=', $request->input('status_id'));
|
||||
}
|
||||
|
||||
if ($request->filled('asset_tag')) {
|
||||
$assets->where('assets.asset_tag', '=', $request->input('asset_tag'));
|
||||
}
|
||||
|
||||
if ($request->filled('serial')) {
|
||||
$assets->where('assets.serial', '=', $request->input('serial'));
|
||||
}
|
||||
|
||||
if ($request->input('requestable') == 'true') {
|
||||
$assets->where('assets.requestable', '=', '1');
|
||||
}
|
||||
@@ -357,19 +364,28 @@ class AssetsController extends Controller
|
||||
/**
|
||||
* Returns JSON with information about an asset (by tag) for detail view.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param string $tag
|
||||
* @since [v4.2.1]
|
||||
* @return JsonResponse
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function showByTag(Request $request, $tag)
|
||||
{
|
||||
if ($asset = Asset::with('assetstatus')->with('assignedTo')->where('asset_tag', $tag)->first()) {
|
||||
$this->authorize('view', $asset);
|
||||
$this->authorize('index', Asset::class);
|
||||
$assets = Asset::where('asset_tag', $tag)->with('assetstatus')->with('assignedTo');
|
||||
|
||||
return (new AssetsTransformer)->transformAsset($asset, $request);
|
||||
// Check if they've passed ?deleted=true
|
||||
if ($request->input('deleted', 'false') == 'true') {
|
||||
$assets = $assets->withTrashed();
|
||||
}
|
||||
|
||||
$assets = $assets->get();
|
||||
|
||||
if (($assets) && ($assets->count() > 0)) {
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
} else {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
||||
|
||||
}
|
||||
|
||||
@@ -379,28 +395,24 @@ class AssetsController extends Controller
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @param string $serial
|
||||
* @since [v4.2.1]
|
||||
* @return JsonResponse
|
||||
* @return \Illuminate\Http\JsonResponse
|
||||
*/
|
||||
public function showBySerial(Request $request, $serial)
|
||||
{
|
||||
$this->authorize('index', Asset::class);
|
||||
if ($assets = Asset::with('assetstatus')->with('assignedTo')
|
||||
->withTrashed()->where('serial', $serial)->get()) {
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
}
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
||||
$assets = Asset::where('serial', $serial)->with('assetstatus')->with('assignedTo');
|
||||
|
||||
$assets = Asset::with('assetstatus')->with('assignedTo');
|
||||
|
||||
if ($request->input('deleted', 'false') === 'true') {
|
||||
// Check if they've passed ?deleted=true
|
||||
if ($request->input('deleted', 'false') == 'true') {
|
||||
$assets = $assets->withTrashed();
|
||||
}
|
||||
}
|
||||
|
||||
$assets = $assets->where('serial', $serial)->get();
|
||||
if ($assets) {
|
||||
$assets = $assets->get();
|
||||
|
||||
if (($assets) && ($assets->count() > 0)) {
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||
} else {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -228,6 +228,7 @@ class ConsumablesController extends Controller
|
||||
|
||||
foreach ($consumable->consumableAssignments as $consumable_assignment) {
|
||||
$rows[] = [
|
||||
'avatar' => ($consumable_assignment->user) ? e($consumable_assignment->user->present()->gravatar) : '',
|
||||
'name' => ($consumable_assignment->user) ? $consumable_assignment->user->present()->nameUrl() : 'Deleted User',
|
||||
'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'),
|
||||
'note' => ($consumable_assignment->note) ? e($consumable_assignment->note) : null,
|
||||
|
||||
@@ -96,7 +96,7 @@ class CustomFieldsController extends Controller
|
||||
$data = $request->all();
|
||||
$regex_format = null;
|
||||
|
||||
if (str_contains($data['format'], 'regex:')) {
|
||||
if ((array_key_exists('format', $data)) && (str_contains($data['format'], 'regex:'))) {
|
||||
$regex_format = $data['format'];
|
||||
}
|
||||
|
||||
|
||||
@@ -39,7 +39,7 @@ class LicenseSeatsController extends Controller
|
||||
}
|
||||
|
||||
$total = $seats->count();
|
||||
$offset = (($seats) && (request('offset') > $total)) ? 0 : request('offset', 0);
|
||||
$offset = (($seats) && (request('offset') >= $total)) ? 0 : request('offset', 0);
|
||||
$limit = request('limit', 50);
|
||||
|
||||
$seats = $seats->skip($offset)->take($limit)->get();
|
||||
|
||||
@@ -27,7 +27,7 @@ class LocationsController extends Controller
|
||||
$allowed_columns = [
|
||||
'id', 'name', 'address', 'address2', 'city', 'state', 'country', 'zip', 'created_at',
|
||||
'updated_at', 'manager_id', 'image',
|
||||
'assigned_assets_count', 'users_count', 'assets_count', 'currency', 'ldap_ou', ];
|
||||
'assigned_assets_count', 'users_count', 'assets_count','assigned_assets_count', 'assets_count', 'rtd_assets_count', 'currency', 'ldap_ou', ];
|
||||
|
||||
$locations = Location::with('parent', 'manager', 'children')->select([
|
||||
'locations.id',
|
||||
@@ -47,6 +47,7 @@ class LocationsController extends Controller
|
||||
'locations.currency',
|
||||
])->withCount('assignedAssets as assigned_assets_count')
|
||||
->withCount('assets as assets_count')
|
||||
->withCount('rtd_assets as rtd_assets_count')
|
||||
->withCount('users as users_count');
|
||||
|
||||
if ($request->filled('search')) {
|
||||
@@ -157,7 +158,9 @@ class LocationsController extends Controller
|
||||
])
|
||||
->withCount('assignedAssets as assigned_assets_count')
|
||||
->withCount('assets as assets_count')
|
||||
->withCount('users as users_count')->findOrFail($id);
|
||||
->withCount('rtd_assets as rtd_assets_count')
|
||||
->withCount('users as users_count')
|
||||
->findOrFail($id);
|
||||
|
||||
return (new LocationsTransformer)->transformLocation($location);
|
||||
}
|
||||
|
||||
@@ -9,6 +9,8 @@ use App\Http\Transformers\StatuslabelsTransformer;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Statuslabel;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Transformers\PieChartTransformer;
|
||||
use Illuminate\Support\Arr;
|
||||
|
||||
class StatuslabelsController extends Controller
|
||||
{
|
||||
@@ -188,43 +190,54 @@ class StatuslabelsController extends Controller
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Http\Response
|
||||
* @return array
|
||||
*/
|
||||
public function getAssetCountByStatuslabel()
|
||||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
|
||||
$statuslabels = Statuslabel::withCount('assets')->get();
|
||||
|
||||
$labels = [];
|
||||
$points = [];
|
||||
$default_color_count = 0;
|
||||
$colors_array = [];
|
||||
|
||||
foreach ($statuslabels as $statuslabel) {
|
||||
if ($statuslabel->assets_count > 0) {
|
||||
$labels[] = $statuslabel->name.' ('.number_format($statuslabel->assets_count).')';
|
||||
$points[] = $statuslabel->assets_count;
|
||||
|
||||
if ($statuslabel->color != '') {
|
||||
$colors_array[] = $statuslabel->color;
|
||||
} else {
|
||||
$colors_array[] = Helper::defaultChartColors($default_color_count);
|
||||
}
|
||||
$default_color_count++;
|
||||
$total[$statuslabel->name]['label'] = $statuslabel->name;
|
||||
$total[$statuslabel->name]['count'] = $statuslabel->assets_count;
|
||||
|
||||
if ($statuslabel->color != '') {
|
||||
$total[$statuslabel->name]['color'] = $statuslabel->color;
|
||||
}
|
||||
}
|
||||
|
||||
$result = [
|
||||
'labels' => $labels,
|
||||
'datasets' => [[
|
||||
'data' => $points,
|
||||
'backgroundColor' => $colors_array,
|
||||
'hoverBackgroundColor' => $colors_array,
|
||||
]],
|
||||
];
|
||||
return (new PieChartTransformer())->transformPieChartDate($total);
|
||||
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* Show a count of assets by meta status type for pie chart
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v6.0.11]
|
||||
* @return array
|
||||
*/
|
||||
public function getAssetCountByMetaStatus()
|
||||
{
|
||||
$this->authorize('view', Statuslabel::class);
|
||||
|
||||
$total['rtd']['label'] = trans('general.ready_to_deploy');
|
||||
$total['rtd']['count'] = Asset::RTD()->count();
|
||||
|
||||
$total['deployed']['label'] = trans('general.deployed');
|
||||
$total['deployed']['count'] = Asset::Deployed()->count();
|
||||
|
||||
$total['archived']['label'] = trans('general.archived');
|
||||
$total['archived']['count'] = Asset::Archived()->count();
|
||||
|
||||
$total['pending']['label'] = trans('general.pending');
|
||||
$total['pending']['count'] = Asset::Pending()->count();
|
||||
|
||||
$total['undeployable']['label'] = trans('general.undeployable');
|
||||
$total['undeployable']['count'] = Asset::Undeployable()->count();
|
||||
|
||||
return (new PieChartTransformer())->transformPieChartDate($total);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -15,6 +15,7 @@ use App\Models\Asset;
|
||||
use App\Models\Company;
|
||||
use App\Models\License;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CurrentInventory;
|
||||
use Auth;
|
||||
use Illuminate\Http\Request;
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
@@ -66,6 +67,8 @@ class UsersController extends Controller
|
||||
'users.zip',
|
||||
'users.remote',
|
||||
'users.ldap_import',
|
||||
'users.start_date',
|
||||
'users.end_date',
|
||||
|
||||
])->with('manager', 'groups', 'userloc', 'company', 'department', 'assets', 'licenses', 'accessories', 'consumables', 'createdBy',)
|
||||
->withCount('assets as assets_count', 'licenses as licenses_count', 'accessories as accessories_count', 'consumables as consumables_count');
|
||||
@@ -146,6 +149,15 @@ class UsersController extends Controller
|
||||
$users = $users->where('remote', '=', $request->input('remote'));
|
||||
}
|
||||
|
||||
if ($request->filled('start_date')) {
|
||||
$users = $users->where('users.start_date', '=', $request->input('start_date'));
|
||||
}
|
||||
|
||||
if ($request->filled('end_date')) {
|
||||
$users = $users->where('users.end_date', '=', $request->input('end_date'));
|
||||
}
|
||||
|
||||
|
||||
if ($request->filled('assets_count')) {
|
||||
$users->has('assets', '=', $request->input('assets_count'));
|
||||
}
|
||||
@@ -200,7 +212,7 @@ class UsersController extends Controller
|
||||
'assets', 'accessories', 'consumables', 'licenses', 'groups', 'activated', 'created_at',
|
||||
'two_factor_enrolled', 'two_factor_optin', 'last_login', 'assets_count', 'licenses_count',
|
||||
'consumables_count', 'accessories_count', 'phone', 'address', 'city', 'state',
|
||||
'country', 'zip', 'id', 'ldap_import', 'remote',
|
||||
'country', 'zip', 'id', 'ldap_import', 'remote', 'start_date', 'end_date',
|
||||
];
|
||||
|
||||
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name';
|
||||
@@ -479,6 +491,26 @@ class UsersController extends Controller
|
||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notify a specific user via email with all of their assigned assets.
|
||||
*
|
||||
* @author [Lukas Fehling] [<lukas.fehling@adabay.rocks>]
|
||||
* @since [v6.0.13]
|
||||
* @param Request $request
|
||||
* @param $id
|
||||
* @return string JSON
|
||||
*/
|
||||
public function emailAssetList(Request $request, $id)
|
||||
{
|
||||
$user = User::findOrFail($id);
|
||||
|
||||
if (empty($user->email)) {
|
||||
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/users/message.inventorynotification.error')));
|
||||
}
|
||||
|
||||
return response()->Helper::formatStandardApiResponse('success', null, trans('admin/users/message.inventorynotification.success'));
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Return JSON containing a list of consumables assigned to a user.
|
||||
|
||||
@@ -471,7 +471,7 @@ class AssetModelsController extends Controller
|
||||
// (we are at model level, the rule still applies when creating a new asset using this model)
|
||||
$index = array_search('required', $validation);
|
||||
if ($index !== false){
|
||||
unset($validation[$index]);
|
||||
$validation[$index] = 'nullable';
|
||||
}
|
||||
$rules[$fieldset] = $validation;
|
||||
}
|
||||
|
||||
@@ -62,7 +62,7 @@ class AssetModelsFilesController extends Controller
|
||||
$model->logUpload($file_name, e($request->get('notes')));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('success', trans('admin/hardware/message.upload.success'));
|
||||
return redirect()->back()->with('success', trans('general.file_upload_success'));
|
||||
}
|
||||
|
||||
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
|
||||
|
||||
@@ -33,7 +33,6 @@ class BulkAssetsController extends Controller
|
||||
|
||||
if (! $request->filled('ids')) {
|
||||
return redirect()->back()->with('error', trans('admin/hardware/message.update.no_assets_selected'));
|
||||
|
||||
}
|
||||
|
||||
// Figure out where we need to send the user after the update is complete, and store that in the session
|
||||
|
||||
@@ -473,6 +473,11 @@ class LoginController extends Controller
|
||||
}
|
||||
|
||||
$request->session()->regenerate(true);
|
||||
|
||||
if ($request->session()->has('password_hash_'.Auth::getDefaultDriver())){
|
||||
$request->session()->remove('password_hash_'.Auth::getDefaultDriver());
|
||||
}
|
||||
|
||||
Auth::logout();
|
||||
|
||||
if (! empty($sloRedirectUrl)) {
|
||||
|
||||
@@ -41,6 +41,7 @@ class ResetPasswordController extends Controller
|
||||
public function __construct()
|
||||
{
|
||||
$this->middleware('guest');
|
||||
$this->middleware('throttle:10,1');
|
||||
}
|
||||
|
||||
protected function rules()
|
||||
@@ -116,7 +117,7 @@ class ResetPasswordController extends Controller
|
||||
}
|
||||
|
||||
\Log::debug('Password reset for '.$user->username.' FAILED - this user exists but the token is not valid');
|
||||
return redirect()->back()->withInput($request->only('email'))->with('error', trans('passwords.token'));
|
||||
return redirect()->back()->withInput($request->only('email'))->with('success', trans('passwords.reset'));
|
||||
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Components;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Component;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Component\HttpFoundation\JsonResponse;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class ComponentsFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a component.
|
||||
*
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param AssetFileRequest $request
|
||||
* @param int $componentId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $componentId = null)
|
||||
{
|
||||
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('components.show', ['component'=>$componentId])->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
$component = Component::find($componentId);
|
||||
|
||||
if (isset($component->id)) {
|
||||
$this->authorize('update', $component);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/components')) {
|
||||
Storage::makeDirectory('private_uploads/components', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'component-'.$component->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension == 'svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
\Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/components/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Storage::put('private_uploads/components/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
|
||||
//Log the upload to the log
|
||||
$component->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('components.show', $component->id)->with('success', trans('general.file_upload_success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('components.show', $component->id)->with('error', trans('general.no_files_uploaded'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('components.index')
|
||||
->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected component file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $componentId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($componentId = null, $fileId = null)
|
||||
{
|
||||
$component = Component::find($componentId);
|
||||
|
||||
// the asset is valid
|
||||
if (isset($component->id)) {
|
||||
$this->authorize('update', $component);
|
||||
$log = Actionlog::find($fileId);
|
||||
|
||||
// Remove the file if one exists
|
||||
if (Storage::exists('components/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('components/'.$log->filename);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $componentId
|
||||
* @param int $fileId
|
||||
* @return \Symfony\Component\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($componentId = null, $fileId = null, $download = true)
|
||||
{
|
||||
\Log::debug('Private filesystem is: '.config('filesystems.default'));
|
||||
$component = Component::find($componentId);
|
||||
|
||||
// the component is valid
|
||||
if (isset($component->id)) {
|
||||
$this->authorize('view', $component);
|
||||
$this->authorize('components.files', $component);
|
||||
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
$file = 'private_uploads/components/'.$log->filename;
|
||||
|
||||
if (Storage::missing($file)) {
|
||||
\Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||
\Log::debug('URL should be '.Storage::url($file));
|
||||
|
||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
} else {
|
||||
if ($download != 'true') {
|
||||
\Log::debug('display the file');
|
||||
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
|
||||
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
|
||||
}
|
||||
|
||||
return JsonResponse::create(['error' => 'Failed validation: '], 500);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('components.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,180 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Controllers\Consumables;
|
||||
|
||||
use App\Helpers\StorageHelper;
|
||||
use App\Http\Controllers\Controller;
|
||||
use App\Http\Requests\AssetFileRequest;
|
||||
use App\Models\Actionlog;
|
||||
use App\Models\Consumable;
|
||||
use Illuminate\Support\Facades\Response;
|
||||
use Illuminate\Support\Facades\Storage;
|
||||
use Symfony\Consumable\HttpFoundation\JsonResponse;
|
||||
use enshrined\svgSanitize\Sanitizer;
|
||||
|
||||
class ConsumablesFilesController extends Controller
|
||||
{
|
||||
/**
|
||||
* Validates and stores files associated with a consumable.
|
||||
*
|
||||
* @todo Switch to using the AssetFileRequest form request validator.
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param AssetFileRequest $request
|
||||
* @param int $consumableId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function store(AssetFileRequest $request, $consumableId = null)
|
||||
{
|
||||
if (config('app.lock_passwords')) {
|
||||
return redirect()->route('consumables.show', ['consumable'=>$consumableId])->with('error', trans('general.feature_disabled'));
|
||||
}
|
||||
|
||||
$consumable = Consumable::find($consumableId);
|
||||
|
||||
if (isset($consumable->id)) {
|
||||
$this->authorize('update', $consumable);
|
||||
|
||||
if ($request->hasFile('file')) {
|
||||
if (! Storage::exists('private_uploads/consumables')) {
|
||||
Storage::makeDirectory('private_uploads/consumables', 775);
|
||||
}
|
||||
|
||||
foreach ($request->file('file') as $file) {
|
||||
|
||||
$extension = $file->getClientOriginalExtension();
|
||||
$file_name = 'consumable-'.$consumable->id.'-'.str_random(8).'-'.str_slug(basename($file->getClientOriginalName(), '.'.$extension)).'.'.$extension;
|
||||
|
||||
|
||||
// Check for SVG and sanitize it
|
||||
if ($extension == 'svg') {
|
||||
\Log::debug('This is an SVG');
|
||||
\Log::debug($file_name);
|
||||
|
||||
$sanitizer = new Sanitizer();
|
||||
$dirtySVG = file_get_contents($file->getRealPath());
|
||||
$cleanSVG = $sanitizer->sanitize($dirtySVG);
|
||||
|
||||
try {
|
||||
Storage::put('private_uploads/consumables/'.$file_name, $cleanSVG);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug('Upload no workie :( ');
|
||||
\Log::debug($e);
|
||||
}
|
||||
|
||||
} else {
|
||||
Storage::put('private_uploads/consumables/'.$file_name, file_get_contents($file));
|
||||
}
|
||||
|
||||
//Log the upload to the log
|
||||
$consumable->logUpload($file_name, e($request->input('notes')));
|
||||
}
|
||||
|
||||
|
||||
return redirect()->route('consumables.show', $consumable->id)->with('success', trans('general.file_upload_success'));
|
||||
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.show', $consumable->id)->with('error', trans('general.no_files_uploaded'));
|
||||
}
|
||||
// Prepare the error message
|
||||
return redirect()->route('consumables.index')
|
||||
->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Deletes the selected consumable file.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.0]
|
||||
* @param int $consumableId
|
||||
* @param int $fileId
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function destroy($consumableId = null, $fileId = null)
|
||||
{
|
||||
$consumable = Consumable::find($consumableId);
|
||||
|
||||
// the asset is valid
|
||||
if (isset($consumable->id)) {
|
||||
$this->authorize('update', $consumable);
|
||||
$log = Actionlog::find($fileId);
|
||||
|
||||
// Remove the file if one exists
|
||||
if (Storage::exists('consumables/'.$log->filename)) {
|
||||
try {
|
||||
Storage::delete('consumables/'.$log->filename);
|
||||
} catch (\Exception $e) {
|
||||
\Log::debug($e);
|
||||
}
|
||||
}
|
||||
|
||||
$log->delete();
|
||||
|
||||
return redirect()->back()
|
||||
->with('success', trans('admin/hardware/message.deletefile.success'));
|
||||
}
|
||||
|
||||
// Redirect to the licence management page
|
||||
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist'));
|
||||
}
|
||||
|
||||
/**
|
||||
* Allows the selected file to be viewed.
|
||||
*
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
* @since [v1.4]
|
||||
* @param int $consumableId
|
||||
* @param int $fileId
|
||||
* @return \Symfony\Consumable\HttpFoundation\Response
|
||||
* @throws \Illuminate\Auth\Access\AuthorizationException
|
||||
*/
|
||||
public function show($consumableId = null, $fileId = null, $download = true)
|
||||
{
|
||||
$consumable = Consumable::find($consumableId);
|
||||
|
||||
// the consumable is valid
|
||||
if (isset($consumable->id)) {
|
||||
$this->authorize('view', $consumable);
|
||||
$this->authorize('consumables.files', $consumable);
|
||||
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
->header('Content-Type', 'text/plain');
|
||||
}
|
||||
|
||||
$file = 'private_uploads/consumables/'.$log->filename;
|
||||
|
||||
if (Storage::missing($file)) {
|
||||
\Log::debug('FILE DOES NOT EXISTS for '.$file);
|
||||
\Log::debug('URL should be '.Storage::url($file));
|
||||
|
||||
return response('File '.$file.' ('.Storage::url($file).') not found on server', 404)
|
||||
->header('Content-Type', 'text/plain');
|
||||
} else {
|
||||
|
||||
// We have to override the URL stuff here, since local defaults in Laravel's Flysystem
|
||||
// won't work, as they're not accessible via the web
|
||||
if (config('filesystems.default') == 'local') { // TODO - is there any way to fix this at the StorageHelper layer?
|
||||
return StorageHelper::downloader($file);
|
||||
} else {
|
||||
if ($download != 'true') {
|
||||
\Log::debug('display the file');
|
||||
if ($contents = file_get_contents(Storage::url($file))) { // TODO - this will fail on private S3 files or large public ones
|
||||
return Response::make(Storage::url($file)->header('Content-Type', mime_content_type($file)));
|
||||
}
|
||||
|
||||
return JsonResponse::create(['error' => 'Failed validation: '], 500);
|
||||
}
|
||||
|
||||
return StorageHelper::downloader($file);
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('consumables.index')->with('error', trans('general.file_does_not_exist', ['id' => $fileId]));
|
||||
}
|
||||
}
|
||||
@@ -86,14 +86,24 @@ class CustomFieldsController extends Controller
|
||||
{
|
||||
$this->authorize('create', CustomField::class);
|
||||
|
||||
$show_in_email = $request->get("show_in_email", 0);
|
||||
$display_in_user_view = $request->get("display_in_user_view", 0);
|
||||
|
||||
// Override the display settings if the field is encrypted
|
||||
if ($request->get("field_encrypted") == '1') {
|
||||
$show_in_email = '0';
|
||||
$display_in_user_view = '0';
|
||||
}
|
||||
|
||||
$field = new CustomField([
|
||||
"name" => trim($request->get("name")),
|
||||
"element" => $request->get("element"),
|
||||
"help_text" => $request->get("help_text"),
|
||||
"field_values" => $request->get("field_values"),
|
||||
"field_encrypted" => $request->get("field_encrypted", 0),
|
||||
"show_in_email" => $request->get("show_in_email", 0),
|
||||
"show_in_email" => $show_in_email,
|
||||
"is_unique" => $request->get("is_unique", 0),
|
||||
"display_in_user_view" => $display_in_user_view,
|
||||
"user_id" => Auth::id()
|
||||
]);
|
||||
|
||||
@@ -221,13 +231,24 @@ class CustomFieldsController extends Controller
|
||||
|
||||
$this->authorize('update', $field);
|
||||
|
||||
|
||||
$show_in_email = $request->get("show_in_email", 0);
|
||||
$display_in_user_view = $request->get("display_in_user_view", 0);
|
||||
|
||||
// Override the display settings if the field is encrypted
|
||||
if ($request->get("field_encrypted") == '1') {
|
||||
$show_in_email = '0';
|
||||
$display_in_user_view = '0';
|
||||
}
|
||||
|
||||
$field->name = trim(e($request->get("name")));
|
||||
$field->element = e($request->get("element"));
|
||||
$field->field_values = e($request->get("field_values"));
|
||||
$field->user_id = Auth::id();
|
||||
$field->help_text = $request->get("help_text");
|
||||
$field->show_in_email = $request->get("show_in_email", 0);
|
||||
$field->show_in_email = $show_in_email;
|
||||
$field->is_unique = $request->get("is_unique", 0);
|
||||
$field->display_in_user_view = $display_in_user_view;
|
||||
|
||||
if ($request->get('format') == 'CUSTOM REGEX') {
|
||||
$field->format = e($request->get('custom_format'));
|
||||
@@ -235,6 +256,10 @@ class CustomFieldsController extends Controller
|
||||
$field->format = e($request->get('format'));
|
||||
}
|
||||
|
||||
if($field->element == 'checkbox' || $field->element == 'radio'){
|
||||
$field->format = 'ANY';
|
||||
}
|
||||
|
||||
if ($field->save()) {
|
||||
return redirect()->route('fields.index')->with('success', trans('admin/custom_fields/message.field.update.success'));
|
||||
}
|
||||
|
||||
@@ -61,6 +61,7 @@ class LicenseCheckoutController extends Controller
|
||||
|
||||
$licenseSeat = $this->findLicenseSeatToCheckout($license, $seatId);
|
||||
$licenseSeat->user_id = Auth::id();
|
||||
|
||||
|
||||
$checkoutMethod = 'checkoutTo'.ucwords(request('checkout_to_type'));
|
||||
if ($this->$checkoutMethod($licenseSeat)) {
|
||||
@@ -76,14 +77,14 @@ class LicenseCheckoutController extends Controller
|
||||
|
||||
if (! $licenseSeat) {
|
||||
if ($seatId) {
|
||||
return redirect()->route('licenses.index')->with('error', 'This Seat is not available for checkout.');
|
||||
throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', 'This Seat is not available for checkout.'));
|
||||
}
|
||||
|
||||
return redirect()->route('licenses.index')->with('error', 'There are no available seats for this license');
|
||||
|
||||
throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', 'There are no available seats for this license.'));
|
||||
}
|
||||
|
||||
if (! $licenseSeat->license->is($license)) {
|
||||
return redirect()->route('licenses.index')->with('error', 'The license seat provided does not match the license.');
|
||||
throw new \Illuminate\Http\Exceptions\HttpResponseException(redirect()->route('licenses.index')->with('error', 'The license seat provided does not match the license.'));
|
||||
}
|
||||
|
||||
return $licenseSeat;
|
||||
|
||||
@@ -135,6 +135,7 @@ class LicenseFilesController extends Controller
|
||||
// the license is valid
|
||||
if (isset($license->id)) {
|
||||
$this->authorize('view', $license);
|
||||
$this->authorize('licenses.files', $license);
|
||||
|
||||
if (! $log = Actionlog::find($fileId)) {
|
||||
return response('No matching record for that asset/file', 500)
|
||||
@@ -171,6 +172,6 @@ class LicenseFilesController extends Controller
|
||||
}
|
||||
}
|
||||
|
||||
return redirect()->route('license.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
|
||||
return redirect()->route('licenses.index')->with('error', trans('admin/licenses/message.does_not_exist', ['id' => $fileId]));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,7 +3,10 @@
|
||||
namespace App\Http\Controllers;
|
||||
|
||||
use App\Http\Requests\ImageUploadRequest;
|
||||
use App\Models\Asset;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Notifications\CurrentInventory;
|
||||
use Illuminate\Support\Facades\Auth;
|
||||
use Gate;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -161,7 +164,7 @@ class ProfileController extends Controller
|
||||
$validator = \Validator::make($request->all(), $rules);
|
||||
$validator->after(function ($validator) use ($request, $user) {
|
||||
if (! Hash::check($request->input('current_password'), $user->password)) {
|
||||
$validator->errors()->add('current_password', trans('validation.hashed_pass'));
|
||||
$validator->errors()->add('current_password', trans('validation.custom.hashed_pass'));
|
||||
}
|
||||
|
||||
// This checks to make sure that the user's password isn't the same as their username,
|
||||
@@ -216,4 +219,47 @@ class ProfileController extends Controller
|
||||
$request->session()->put('menu_state', 'closed');
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Print inventory
|
||||
*
|
||||
* @author A. Gianotto
|
||||
* @since [v6.0.12]
|
||||
* @return Illuminate\View\View
|
||||
*/
|
||||
public function printInventory()
|
||||
{
|
||||
$show_user = Auth::user();
|
||||
|
||||
return view('users/print')
|
||||
->with('assets', Auth::user()->assets)
|
||||
->with('licenses', $show_user->licenses()->get())
|
||||
->with('accessories', $show_user->accessories()->get())
|
||||
->with('consumables', $show_user->consumables()->get())
|
||||
->with('show_user', $show_user)
|
||||
->with('settings', Setting::getSettings());
|
||||
}
|
||||
|
||||
/**
|
||||
* Emails user a list of assigned assets
|
||||
*
|
||||
* @author A. Gianotto
|
||||
* @since [v6.0.12]
|
||||
* @return \Illuminate\Http\RedirectResponse
|
||||
*/
|
||||
public function emailAssetList()
|
||||
{
|
||||
|
||||
if (!$user = User::find(Auth::user()->id)) {
|
||||
return redirect()->back()
|
||||
->with('error', trans('admin/users/message.user_not_found', ['id' => $id]));
|
||||
}
|
||||
if (empty($user->email)) {
|
||||
return redirect()->back()->with('error', trans('admin/users/message.user_has_no_email'));
|
||||
}
|
||||
|
||||
$user->notify((new CurrentInventory($user)));
|
||||
return redirect()->back()->with('success', trans('admin/users/general.user_notified'));
|
||||
}
|
||||
}
|
||||
|
||||
@@ -22,6 +22,8 @@ use Illuminate\Support\Facades\View;
|
||||
use Input;
|
||||
use League\Csv\Reader;
|
||||
use Symfony\Component\HttpFoundation\StreamedResponse;
|
||||
use League\Csv\EscapeFormula;
|
||||
|
||||
|
||||
/**
|
||||
* This controller handles all actions related to Reports for
|
||||
@@ -411,6 +413,7 @@ class ReportsController extends Controller
|
||||
$customfields = CustomField::get();
|
||||
$response = new StreamedResponse(function () use ($customfields, $request) {
|
||||
\Log::debug('Starting streamed response');
|
||||
\Log::debug('CSV escaping is set to: '.config('app.escape_formulas'));
|
||||
|
||||
// Open output stream
|
||||
$handle = fopen('php://output', 'w');
|
||||
@@ -589,7 +592,7 @@ class ReportsController extends Controller
|
||||
\Log::debug('Added headers: '.$executionTime);
|
||||
|
||||
$assets = \App\Models\Company::scopeCompanyables(Asset::select('assets.*'))->with(
|
||||
'location', 'assetstatus', 'assetlog', 'company', 'defaultLoc', 'assignedTo',
|
||||
'location', 'assetstatus', 'company', 'defaultLoc', 'assignedTo',
|
||||
'model.category', 'model.manufacturer', 'supplier');
|
||||
|
||||
if ($request->filled('by_location_id')) {
|
||||
@@ -666,6 +669,9 @@ class ReportsController extends Controller
|
||||
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
|
||||
\Log::debug('Walking results: '.$executionTime);
|
||||
$count = 0;
|
||||
|
||||
$formatter = new EscapeFormula("`");
|
||||
|
||||
foreach ($assets as $asset) {
|
||||
$count++;
|
||||
$row = [];
|
||||
@@ -855,7 +861,17 @@ class ReportsController extends Controller
|
||||
$row[] = $asset->$column_name;
|
||||
}
|
||||
}
|
||||
fputcsv($handle, $row);
|
||||
|
||||
|
||||
// CSV_ESCAPE_FORMULAS is set to false in the .env
|
||||
if (config('app.escape_formulas') === false) {
|
||||
fputcsv($handle, $row);
|
||||
|
||||
// CSV_ESCAPE_FORMULAS is set to true or is not set in the .env
|
||||
} else {
|
||||
fputcsv($handle, $formatter->escapeRecord($row));
|
||||
}
|
||||
|
||||
$executionTime = microtime(true) - $_SERVER['REQUEST_TIME_FLOAT'];
|
||||
\Log::debug('-- Record '.$count.' Asset ID:'.$asset->id.' in '.$executionTime);
|
||||
}
|
||||
@@ -1006,7 +1022,11 @@ class ReportsController extends Controller
|
||||
}
|
||||
$assetItem = $acceptance->checkoutable;
|
||||
|
||||
$logItem = $assetItem->checkouts()->where('created_at', '=', $acceptance->created_at)->get()[0];
|
||||
if (is_null($acceptance->created_at)){
|
||||
return redirect()->route('reports/unaccepted_assets')->with('error', trans('general.bad_data'));
|
||||
} else {
|
||||
$logItem = $assetItem->checkouts()->where('created_at', '=', $acceptance->created_at)->get()[0];
|
||||
}
|
||||
|
||||
if(!$assetItem->assignedTo->locale){
|
||||
Notification::locale(Setting::getSettings()->locale)->send(
|
||||
@@ -1063,9 +1083,9 @@ class ReportsController extends Controller
|
||||
* Get all assets with pending checkout acceptances
|
||||
*/
|
||||
if($showDeleted) {
|
||||
$acceptances = CheckoutAcceptance::pending()->withTrashed()->with(['assignedTo', 'checkoutable.assignedTo', 'checkoutable.model'])->get();
|
||||
$acceptances = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')->withTrashed()->with(['assignedTo', 'checkoutable.assignedTo', 'checkoutable.model'])->get();
|
||||
} else {
|
||||
$acceptances = CheckoutAcceptance::pending()->with(['assignedTo', 'checkoutable.assignedTo', 'checkoutable.model'])->get();
|
||||
$acceptances = CheckoutAcceptance::pending()->where('checkoutable_type', 'App\Models\Asset')->with(['assignedTo', 'checkoutable.assignedTo', 'checkoutable.model'])->get();
|
||||
}
|
||||
|
||||
$assetsForReport = $acceptances
|
||||
|
||||
@@ -349,6 +349,7 @@ class SettingsController extends Controller
|
||||
$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');
|
||||
|
||||
if ($request->input('per_page') != '') {
|
||||
$setting->per_page = $request->input('per_page');
|
||||
@@ -922,8 +923,8 @@ class SettingsController extends Controller
|
||||
|
||||
$validator = Validator::make($setting->toArray(), [
|
||||
'ldap_username_field' => 'not_in:sAMAccountName',
|
||||
'ldap_auth_filter_query' => 'not_in:uid=samaccountname',
|
||||
'ldap_filter' => 'regex:"^[^(]"',
|
||||
'ldap_auth_filter_query' => 'not_in:uid=samaccountname|required_if:ldap_enabled,1',
|
||||
'ldap_filter' => 'nullable|regex:"^[^(]"|required_if:ldap_enabled,1',
|
||||
], $messages);
|
||||
|
||||
|
||||
|
||||
@@ -197,6 +197,7 @@ class BulkUsersController extends Controller
|
||||
'status_id' => e(request('status_id')),
|
||||
'assigned_to' => null,
|
||||
'assigned_type' => null,
|
||||
'expected_checkin' => null,
|
||||
]);
|
||||
|
||||
|
||||
@@ -231,8 +232,14 @@ class BulkUsersController extends Controller
|
||||
protected function logItemCheckinAndDelete($items, $itemType)
|
||||
{
|
||||
foreach ($items as $item) {
|
||||
$item_id = $item->id;
|
||||
$logAction = new Actionlog();
|
||||
$logAction->item_id = $item->id;
|
||||
|
||||
if ($itemType == License::class){
|
||||
$item_id = $item->license_id;
|
||||
}
|
||||
|
||||
$logAction->item_id = $item_id;
|
||||
// We can't rely on get_class here because the licenses/accessories fetched above are not eloquent models, but simply arrays.
|
||||
$logAction->item_type = $itemType;
|
||||
$logAction->target_id = $item->assigned_to;
|
||||
|
||||
@@ -119,6 +119,8 @@ class UsersController extends Controller
|
||||
$user->remote = $request->input('remote', 0);
|
||||
$user->website = $request->input('website', null);
|
||||
$user->created_by = Auth::user()->id;
|
||||
$user->start_date = $request->input('start_date', null);
|
||||
$user->end_date = $request->input('end_date', null);
|
||||
|
||||
// Strip out the superuser permission if the user isn't a superadmin
|
||||
$permissions_array = $request->input('permission');
|
||||
@@ -270,6 +272,8 @@ class UsersController extends Controller
|
||||
$user->zip = $request->input('zip', null);
|
||||
$user->remote = $request->input('remote', 0);
|
||||
$user->website = $request->input('website', null);
|
||||
$user->start_date = $request->input('start_date', null);
|
||||
$user->end_date = $request->input('end_date', null);
|
||||
|
||||
// Update the location of any assets checked out to this user
|
||||
Asset::where('assigned_type', User::class)
|
||||
@@ -594,7 +598,7 @@ class UsersController extends Controller
|
||||
}
|
||||
|
||||
/**
|
||||
* LDAP form processing.
|
||||
* Print inventory
|
||||
*
|
||||
* @author Aladin Alaily
|
||||
* @since [v1.8]
|
||||
|
||||
@@ -8,6 +8,7 @@ use App\Models\AssetModel;
|
||||
use App\Models\Company;
|
||||
use App\Models\Setting;
|
||||
use App\Models\User;
|
||||
use App\Models\CustomField;
|
||||
use App\Notifications\RequestAssetCancelation;
|
||||
use App\Notifications\RequestAssetNotification;
|
||||
use Illuminate\Http\Request;
|
||||
@@ -29,23 +30,41 @@ class ViewAssetsController extends Controller
|
||||
public function getIndex()
|
||||
{
|
||||
$user = User::with(
|
||||
'assets',
|
||||
'assets.model',
|
||||
'assets.model.fieldset.fields',
|
||||
'consumables',
|
||||
'accessories',
|
||||
'licenses',
|
||||
'userloc',
|
||||
'userlog'
|
||||
)->withTrashed()->find(Auth::user()->id);
|
||||
)->find(Auth::user()->id);
|
||||
|
||||
$userlog = $user->userlog->load('item', 'user', 'target');
|
||||
$field_array = array();
|
||||
|
||||
// Loop through all the custom fields that are applied to any model the user has assigned
|
||||
foreach ($user->assets as $asset) {
|
||||
|
||||
// Make sure the model has a custom fieldset before trying to loop through the associated fields
|
||||
if ($asset->model->fieldset) {
|
||||
|
||||
foreach ($asset->model->fieldset->fields as $field) {
|
||||
// check and make sure they're allowed to see the value of the custom field
|
||||
if ($field->display_in_user_view == '1') {
|
||||
$field_array[$field->db_column] = $field->name;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// Since some models may re-use the same fieldsets/fields, let's make the array unique so we don't repeat columns
|
||||
array_unique($field_array);
|
||||
|
||||
if (isset($user->id)) {
|
||||
return view('account/view-assets', compact('user', 'userlog'))
|
||||
return view('account/view-assets', compact('user', 'field_array' ))
|
||||
->with('settings', Setting::getSettings());
|
||||
} else {
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')->with('error', trans('admin/users/message.user_not_found', compact('id')));
|
||||
}
|
||||
|
||||
// Redirect to the user management page
|
||||
return redirect()->route('users.index')
|
||||
->with('error', trans('admin/users/message.user_not_found', $user->id));
|
||||
|
||||
@@ -85,6 +85,7 @@ class ActionlogsTransformer
|
||||
'id' => (int) $actionlog->item->id,
|
||||
'name' => ($actionlog->itemType()=='user') ? e($actionlog->item->getFullNameAttribute()) : e($actionlog->item->getDisplayNameAttribute()),
|
||||
'type' => e($actionlog->itemType()),
|
||||
'serial' =>e($actionlog->item->serial) ? e($actionlog->item->serial) : null
|
||||
] : null,
|
||||
'location' => ($actionlog->location) ? [
|
||||
'id' => (int) $actionlog->location->id,
|
||||
|
||||
@@ -131,7 +131,7 @@ class AssetsTransformer
|
||||
$array['custom_fields'] = $fields_array;
|
||||
}
|
||||
} else {
|
||||
$array['custom_fields'] = [];
|
||||
$array['custom_fields'] = new \stdClass; // HACK to force generation of empty object instead of empty list
|
||||
}
|
||||
|
||||
$permissions_array['available_actions'] = [
|
||||
|
||||
@@ -47,6 +47,7 @@ class CustomFieldsTransformer
|
||||
'field_values_array' => ($field->field_values) ? explode("\r\n", e($field->field_values)) : null,
|
||||
'type' => e($field->element),
|
||||
'required' => (($field->pivot) && ($field->pivot->required=='1')) ? true : false,
|
||||
'display_in_user_view' => ($field->display_in_user_view =='1') ? true : false,
|
||||
'created_at' => Helper::getFormattedDateObject($field->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($field->updated_at, 'datetime'),
|
||||
];
|
||||
|
||||
@@ -3,6 +3,7 @@
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Depreciable;
|
||||
use App\Models\Depreciation;
|
||||
use Gate;
|
||||
use Illuminate\Database\Eloquent\Collection;
|
||||
|
||||
@@ -45,6 +45,7 @@ class LocationsTransformer
|
||||
'zip' => ($location->zip) ? e($location->zip) : null,
|
||||
'assigned_assets_count' => (int) $location->assigned_assets_count,
|
||||
'assets_count' => (int) $location->assets_count,
|
||||
'rtd_assets_count' => (int) $location->rtd_assets_count,
|
||||
'users_count' => (int) $location->users_count,
|
||||
'currency' => ($location->currency) ? e($location->currency) : null,
|
||||
'ldap_ou' => ($location->ldap_ou) ? e($location->ldap_ou) : null,
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<?php
|
||||
|
||||
namespace App\Http\Transformers;
|
||||
|
||||
|
||||
use App\Helpers\Helper;
|
||||
/**
|
||||
* Class PieChartTransformer
|
||||
*
|
||||
* This handles the standardized formatting of the API response we need to provide for
|
||||
* the pie charts
|
||||
*
|
||||
* @return \Illuminate\Http\Response
|
||||
* @since [v6.0.11]
|
||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||
*/
|
||||
class PieChartTransformer
|
||||
{
|
||||
public function transformPieChartDate($totals)
|
||||
{
|
||||
|
||||
$labels = [];
|
||||
$counts = [];
|
||||
$default_color_count = 0;
|
||||
$colors_array = [];
|
||||
|
||||
foreach ($totals as $total) {
|
||||
|
||||
if ($total['count'] > 0) {
|
||||
|
||||
$labels[] = $total['label']." (".$total['count'].")";
|
||||
$counts[] = $total['count'];
|
||||
|
||||
if (isset($total['color'])) {
|
||||
$colors_array[] = $total['color'];
|
||||
} else {
|
||||
$colors_array[] = Helper::defaultChartColors($default_color_count);
|
||||
$default_color_count++;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
$results = [
|
||||
'labels' => $labels,
|
||||
'datasets' => [[
|
||||
'data' => $counts,
|
||||
'backgroundColor' => $colors_array,
|
||||
'hoverBackgroundColor' => $colors_array,
|
||||
]],
|
||||
];
|
||||
|
||||
|
||||
return $results;
|
||||
}
|
||||
}
|
||||
@@ -30,7 +30,7 @@ class UsersTransformer
|
||||
'username' => e($user->username),
|
||||
'remote' => ($user->remote == '1') ? true : false,
|
||||
'locale' => ($user->locale) ? e($user->locale) : null,
|
||||
'employee_num' => e($user->employee_num),
|
||||
'employee_num' => ($user->employee_num) ? e($user->employee_num) : null,
|
||||
'manager' => ($user->manager) ? [
|
||||
'id' => (int) $user->manager->id,
|
||||
'name'=> e($user->manager->first_name).' '.e($user->manager->last_name),
|
||||
@@ -43,7 +43,7 @@ class UsersTransformer
|
||||
'state' => ($user->state) ? e($user->state) : null,
|
||||
'country' => ($user->country) ? e($user->country) : null,
|
||||
'zip' => ($user->zip) ? e($user->zip) : null,
|
||||
'email' => e($user->email),
|
||||
'email' => ($user->email) ? e($user->email) : null,
|
||||
'department' => ($user->department) ? [
|
||||
'id' => (int) $user->department->id,
|
||||
'name'=> e($user->department->name),
|
||||
@@ -69,6 +69,8 @@ class UsersTransformer
|
||||
] : null,
|
||||
'created_at' => Helper::getFormattedDateObject($user->created_at, 'datetime'),
|
||||
'updated_at' => Helper::getFormattedDateObject($user->updated_at, 'datetime'),
|
||||
'start_date' => Helper::getFormattedDateObject($user->start_date, 'date'),
|
||||
'end_date' => Helper::getFormattedDateObject($user->end_date, 'date'),
|
||||
'last_login' => Helper::getFormattedDateObject($user->last_login, 'datetime'),
|
||||
'deleted_at' => ($user->deleted_at) ? Helper::getFormattedDateObject($user->deleted_at, 'datetime') : null,
|
||||
];
|
||||
|
||||
@@ -43,6 +43,7 @@ class AccessoryImporter extends ItemImporter
|
||||
$this->log('No Matching Accessory, Creating a new one');
|
||||
$accessory = new Accessory();
|
||||
$this->item['model_number'] = $this->findCsvMatch($row, "model_number");
|
||||
$this->item['min_amt'] = $this->findCsvMatch($row, "min_amt");
|
||||
$accessory->fill($this->sanitizeItemForStoring($accessory));
|
||||
|
||||
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
|
||||
|
||||
@@ -43,6 +43,7 @@ class ConsumableImporter extends ItemImporter
|
||||
$consumable = new Consumable();
|
||||
$this->item['model_number'] = $this->findCsvMatch($row, 'model_number');
|
||||
$this->item['item_no'] = $this->findCsvMatch($row, 'item_number');
|
||||
$this->item['min_amt'] = $this->findCsvMatch($row, "min_amt");
|
||||
$consumable->fill($this->sanitizeItemForStoring($consumable));
|
||||
//FIXME: this disables model validation. Need to find a way to avoid double-logs without breaking everything.
|
||||
$consumable->unsetEventDispatcher();
|
||||
|
||||
@@ -112,7 +112,7 @@ class ItemImporter extends Importer
|
||||
return $this->createOrFetchUser($row);
|
||||
}
|
||||
|
||||
if (strtolower($this->item['checkout_class']) === 'location') {
|
||||
if (strtolower($this->item['checkout_class']) === 'location' && $this->findCsvMatch($row, 'checkout_location') != null ) {
|
||||
return Location::findOrFail($this->createOrFetchLocation($this->findCsvMatch($row, 'checkout_location')));
|
||||
}
|
||||
|
||||
|
||||
@@ -20,6 +20,8 @@ use App\Notifications\CheckoutConsumableNotification;
|
||||
use App\Notifications\CheckoutLicenseNotification;
|
||||
use App\Notifications\CheckoutLicenseSeatNotification;
|
||||
use Illuminate\Support\Facades\Notification;
|
||||
use Exception;
|
||||
use Log;
|
||||
|
||||
class CheckoutableListener
|
||||
{
|
||||
@@ -43,16 +45,20 @@ class CheckoutableListener
|
||||
*/
|
||||
$acceptance = $this->getCheckoutAcceptance($event);
|
||||
|
||||
if (! $event->checkedOutTo->locale) {
|
||||
Notification::locale(Setting::getSettings()->locale)->send(
|
||||
$this->getNotifiables($event),
|
||||
$this->getCheckoutNotification($event, $acceptance)
|
||||
);
|
||||
} else {
|
||||
Notification::send(
|
||||
$this->getNotifiables($event),
|
||||
$this->getCheckoutNotification($event, $acceptance)
|
||||
);
|
||||
try {
|
||||
if (! $event->checkedOutTo->locale) {
|
||||
Notification::locale(Setting::getSettings()->locale)->send(
|
||||
$this->getNotifiables($event),
|
||||
$this->getCheckoutNotification($event, $acceptance)
|
||||
);
|
||||
} else {
|
||||
Notification::send(
|
||||
$this->getNotifiables($event),
|
||||
$this->getCheckoutNotification($event, $acceptance)
|
||||
);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Log::error("Exception caught during checkout notification: ".$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -83,17 +89,21 @@ class CheckoutableListener
|
||||
}
|
||||
}
|
||||
|
||||
// Use default locale
|
||||
if (! $event->checkedOutTo->locale) {
|
||||
Notification::locale(Setting::getSettings()->locale)->send(
|
||||
$this->getNotifiables($event),
|
||||
$this->getCheckinNotification($event)
|
||||
);
|
||||
} else {
|
||||
Notification::send(
|
||||
$this->getNotifiables($event),
|
||||
$this->getCheckinNotification($event)
|
||||
);
|
||||
try {
|
||||
// Use default locale
|
||||
if (! $event->checkedOutTo->locale) {
|
||||
Notification::locale(Setting::getSettings()->locale)->send(
|
||||
$this->getNotifiables($event),
|
||||
$this->getCheckinNotification($event)
|
||||
);
|
||||
} else {
|
||||
Notification::send(
|
||||
$this->getNotifiables($event),
|
||||
$this->getCheckinNotification($event)
|
||||
);
|
||||
}
|
||||
} catch (Exception $e) {
|
||||
Log::error("Exception caught during checkin notification: ".$e->getMessage());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Traits\Acceptable;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
@@ -100,6 +101,23 @@ class Accessory extends SnipeModel
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the accessories -> action logs -> uploads relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v6.1.13]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function uploads()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Actionlog::class, 'item_id')
|
||||
->where('item_type', '=', self::class)
|
||||
->where('action_type', '=', 'uploaded')
|
||||
->whereNotNull('filename')
|
||||
->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the accessory -> supplier relationship
|
||||
*
|
||||
@@ -299,15 +317,14 @@ class Accessory extends SnipeModel
|
||||
*/
|
||||
public function getEula()
|
||||
{
|
||||
$Parsedown = new \Parsedown();
|
||||
|
||||
if ($this->category->eula_text) {
|
||||
return $Parsedown->text(e($this->category->eula_text));
|
||||
return Helper::parseEscapedMarkedown($this->category->eula_text);
|
||||
} elseif ((Setting::getSettings()->default_eula_text) && ($this->category->use_default_eula == '1')) {
|
||||
return $Parsedown->text(e(Setting::getSettings()->default_eula_text));
|
||||
return Helper::parseEscapedMarkedown(Setting::getSettings()->default_eula_text);
|
||||
}
|
||||
|
||||
return null;
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -5,6 +5,7 @@ namespace App\Models;
|
||||
use App\Events\AssetCheckedOut;
|
||||
use App\Events\CheckoutableCheckedOut;
|
||||
use App\Exceptions\CheckoutNotAllowed;
|
||||
use App\Helpers\Helper;
|
||||
use App\Http\Traits\UniqueSerialTrait;
|
||||
use App\Http\Traits\UniqueUndeletedTrait;
|
||||
use App\Models\Traits\Acceptable;
|
||||
@@ -694,15 +695,15 @@ class Asset extends Depreciable
|
||||
public static function getExpiringWarrantee($days = 30)
|
||||
{
|
||||
$days = (is_null($days)) ? 30 : $days;
|
||||
|
||||
|
||||
return self::where('archived', '=', '0')
|
||||
->whereNotNull('warranty_months')
|
||||
->whereNotNull('purchase_date')
|
||||
->whereNull('deleted_at')
|
||||
->whereRaw(\DB::raw('DATE_ADD(`purchase_date`,INTERVAL `warranty_months` MONTH) <= DATE(NOW() + INTERVAL '
|
||||
->whereRaw('DATE_ADD(`purchase_date`,INTERVAL `warranty_months` MONTH) <= DATE(NOW() + INTERVAL '
|
||||
. $days
|
||||
. ' DAY) AND DATE_ADD(`purchase_date`, INTERVAL `warranty_months` MONTH) > NOW()'))
|
||||
->orderBy('purchase_date', 'ASC')
|
||||
. ' DAY) AND DATE_ADD(`purchase_date`, INTERVAL `warranty_months` MONTH) > NOW()')
|
||||
->orderByRaw('DATE_ADD(`purchase_date`,INTERVAL `warranty_months` MONTH)')
|
||||
->get();
|
||||
}
|
||||
|
||||
@@ -875,13 +876,12 @@ class Asset extends Depreciable
|
||||
*/
|
||||
public function getEula()
|
||||
{
|
||||
$Parsedown = new \Parsedown();
|
||||
|
||||
|
||||
if (($this->model) && ($this->model->category)) {
|
||||
if ($this->model->category->eula_text) {
|
||||
return $Parsedown->text(e($this->model->category->eula_text));
|
||||
return Helper::parseEscapedMarkedown($this->model->category->eula_text);
|
||||
} elseif ($this->model->category->use_default_eula == '1') {
|
||||
return $Parsedown->text(e(Setting::getSettings()->default_eula_text));
|
||||
return Helper::parseEscapedMarkedown(Setting::getSettings()->default_eula_text);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -74,7 +74,7 @@ class AssetMaintenance extends Model implements ICompanyableChild
|
||||
trans('admin/asset_maintenances/general.maintenance') => trans('admin/asset_maintenances/general.maintenance'),
|
||||
trans('admin/asset_maintenances/general.repair') => trans('admin/asset_maintenances/general.repair'),
|
||||
trans('admin/asset_maintenances/general.upgrade') => trans('admin/asset_maintenances/general.upgrade'),
|
||||
'PAT test' => 'PAT test',
|
||||
trans('admin/asset_maintenances/general.pat_test') => trans('admin/asset_maintenances/general.pat_test'),
|
||||
trans('admin/asset_maintenances/general.calibration') => trans('admin/asset_maintenances/general.calibration'),
|
||||
trans('admin/asset_maintenances/general.software_support') => trans('admin/asset_maintenances/general.software_support'),
|
||||
trans('admin/asset_maintenances/general.hardware_support') => trans('admin/asset_maintenances/general.hardware_support'),
|
||||
|
||||
@@ -9,6 +9,7 @@ use Illuminate\Database\Eloquent\Factories\HasFactory;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Support\Facades\Gate;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
use App\Helpers\Helper;
|
||||
|
||||
/**
|
||||
* Model for Categories. Categories are a higher-level group
|
||||
@@ -207,12 +208,11 @@ class Category extends SnipeModel
|
||||
*/
|
||||
public function getEula()
|
||||
{
|
||||
$Parsedown = new \Parsedown();
|
||||
|
||||
if ($this->eula_text) {
|
||||
return $Parsedown->text(e($this->eula_text));
|
||||
return Helper::parseEscapedMarkedown($this->eula_text);
|
||||
} elseif ((Setting::getSettings()->default_eula_text) && ($this->use_default_eula == '1')) {
|
||||
return $Parsedown->text(e(Setting::getSettings()->default_eula_text));
|
||||
return Helper::parseEscapedMarkedown(Setting::getSettings()->default_eula_text);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -5,16 +5,25 @@ namespace App\Models;
|
||||
use Illuminate\Database\Eloquent\Builder;
|
||||
use Illuminate\Database\Eloquent\Model;
|
||||
use Illuminate\Database\Eloquent\SoftDeletes;
|
||||
use Illuminate\Notifications\Notifiable;
|
||||
|
||||
class CheckoutAcceptance extends Model
|
||||
{
|
||||
use SoftDeletes;
|
||||
use SoftDeletes, Notifiable;
|
||||
|
||||
protected $casts = [
|
||||
'accepted_at' => 'datetime',
|
||||
'declined_at' => 'datetime',
|
||||
];
|
||||
|
||||
// Get the mail recipient from the config
|
||||
public function routeNotificationForMail(): string
|
||||
{
|
||||
// At this point the endpoint is the same for everything.
|
||||
// In the future this may want to be adapted for individual notifications.
|
||||
return (config('mail.reply_to.address')) ? config('mail.reply_to.address') : '' ;
|
||||
}
|
||||
|
||||
/**
|
||||
* The resource that was is out
|
||||
*
|
||||
|
||||
@@ -88,6 +88,24 @@ class Component extends SnipeModel
|
||||
'location' => ['name'],
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the components -> action logs -> uploads relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v6.1.13]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function uploads()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Actionlog::class, 'item_id')
|
||||
->where('item_type', '=', self::class)
|
||||
->where('action_type', '=', 'uploaded')
|
||||
->whereNotNull('filename')
|
||||
->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the component -> location relationship
|
||||
*
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Traits\Acceptable;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
@@ -95,6 +96,24 @@ class Consumable extends SnipeModel
|
||||
'manufacturer' => ['name'],
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the components -> action logs -> uploads relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v6.1.13]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function uploads()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Actionlog::class, 'item_id')
|
||||
->where('item_type', '=', self::class)
|
||||
->where('action_type', '=', 'uploaded')
|
||||
->whereNotNull('filename')
|
||||
->orderBy('created_at', 'desc');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Sets the attribute of whether or not the consumable is requestable
|
||||
*
|
||||
@@ -265,12 +284,10 @@ class Consumable extends SnipeModel
|
||||
*/
|
||||
public function getEula()
|
||||
{
|
||||
$Parsedown = new \Parsedown();
|
||||
|
||||
if ($this->category->eula_text) {
|
||||
return $Parsedown->text(e($this->category->eula_text));
|
||||
return Helper::parseEscapedMarkedown($this->category->eula_text);
|
||||
} elseif ((Setting::getSettings()->default_eula_text) && ($this->category->use_default_eula == '1')) {
|
||||
return $Parsedown->text(e(Setting::getSettings()->default_eula_text));
|
||||
return Helper::parseEscapedMarkedown(Setting::getSettings()->default_eula_text);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
|
||||
@@ -48,7 +48,11 @@ class CustomField extends Model
|
||||
*
|
||||
* @var array
|
||||
*/
|
||||
protected $rules = [];
|
||||
protected $rules = [
|
||||
'name' => 'required|unique:custom_fields',
|
||||
'element' => 'required|in:text,listbox,textarea,checkbox,radio',
|
||||
'field_encrypted' => 'nullable|boolean',
|
||||
];
|
||||
|
||||
/**
|
||||
* The attributes that are mass assignable.
|
||||
@@ -64,6 +68,7 @@ class CustomField extends Model
|
||||
'help_text',
|
||||
'show_in_email',
|
||||
'is_unique',
|
||||
'display_in_user_view',
|
||||
];
|
||||
|
||||
/**
|
||||
@@ -338,7 +343,7 @@ class CustomField extends Model
|
||||
$id = $this->id ? $this->id : 'xx';
|
||||
|
||||
if (! function_exists('transliterator_transliterate')) {
|
||||
$long_slug = '_snipeit_'.str_slug(\Patchwork\Utf8::utf8_encode(trim($name)), '_');
|
||||
$long_slug = '_snipeit_'.str_slug(mb_convert_encoding(trim($name),"UTF-8"), '_');
|
||||
} else {
|
||||
$long_slug = '_snipeit_'.Utf8Slugger::slugify($name, '_');
|
||||
}
|
||||
@@ -356,15 +361,9 @@ class CustomField extends Model
|
||||
public function validationRules($regex_format = null)
|
||||
{
|
||||
return [
|
||||
'name' => 'required|unique:custom_fields',
|
||||
'element' => [
|
||||
'required',
|
||||
Rule::in(['text', 'listbox', 'textarea', 'checkbox', 'radio']),
|
||||
],
|
||||
'format' => [
|
||||
Rule::in(array_merge(array_keys(self::PREDEFINED_FORMATS), self::PREDEFINED_FORMATS, [$regex_format])),
|
||||
],
|
||||
'field_encrypted' => 'nullable|boolean',
|
||||
]
|
||||
];
|
||||
}
|
||||
|
||||
|
||||
@@ -68,21 +68,37 @@ class Depreciable extends SnipeModel
|
||||
*/
|
||||
public function getLinearDepreciatedValue() // TODO - for testing it might be nice to have an optional $relative_to param here, defaulted to 'now'
|
||||
{
|
||||
$months_remaining = $this->time_until_depreciated()->m + 12 * $this->time_until_depreciated()->y; //UGlY
|
||||
|
||||
$current_value = round(($months_remaining / $this->get_depreciation()->months) * $this->purchase_cost, 2);
|
||||
|
||||
if($this->get_depreciation()->depreciation_min > $current_value) {
|
||||
|
||||
$current_value=round($this->get_depreciation()->depreciation_min,2);
|
||||
if ($this->purchase_date) {
|
||||
$months_passed = ($this->purchase_date->diff(now())->m)+($this->purchase_date->diff(now())->y*12);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
if ($current_value < 0) {
|
||||
$current_value = 0;
|
||||
|
||||
if ($months_passed >= $this->get_depreciation()->months){
|
||||
//if there is a floor use it
|
||||
if(!$this->get_depreciation()->depreciation_min == null) {
|
||||
|
||||
$current_value = $this->get_depreciation()->depreciation_min;
|
||||
|
||||
}else{
|
||||
$current_value = 0;
|
||||
}
|
||||
}
|
||||
else {
|
||||
// The equation here is (Purchase_Cost-Floor_min)*(Months_passed/Months_til_depreciated)
|
||||
$current_value = round(($this->purchase_cost-($this->purchase_cost - ($this->get_depreciation()->depreciation_min)) * ($months_passed / $this->get_depreciation()->months)), 2);
|
||||
|
||||
}
|
||||
|
||||
return $current_value;
|
||||
}
|
||||
|
||||
public function getMonthlyDepreciation(){
|
||||
|
||||
return ($this->purchase_cost-$this->get_depreciation()->depreciation_min)/$this->get_depreciation()->months;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* @param onlyHalfFirstYear Boolean always applied only second half of the first year
|
||||
* @return float|int
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
namespace App\Models;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Traits\Searchable;
|
||||
use App\Presenters\Presentable;
|
||||
use Carbon\Carbon;
|
||||
@@ -337,12 +338,11 @@ class License extends Depreciable
|
||||
*/
|
||||
public function getEula()
|
||||
{
|
||||
$Parsedown = new \Parsedown();
|
||||
|
||||
if ($this->category->eula_text) {
|
||||
return $Parsedown->text(e($this->category->eula_text));
|
||||
return Helper::parseEscapedMarkedown($this->category->eula_text);
|
||||
} elseif ($this->category->use_default_eula == '1') {
|
||||
return $Parsedown->text(e(Setting::getSettings()->default_eula_text));
|
||||
return Helper::parseEscapedMarkedown(Setting::getSettings()->default_eula_text);
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
|
||||
+81
-7
@@ -90,6 +90,14 @@ class Location extends SnipeModel
|
||||
'parent' => ['name'],
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Determine whether or not this location can be deleted
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return bool
|
||||
*/
|
||||
public function isDeletable()
|
||||
{
|
||||
return Gate::allows('delete', $this)
|
||||
@@ -98,12 +106,25 @@ class Location extends SnipeModel
|
||||
&& ($this->users()->count() === 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the user -> location relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function users()
|
||||
{
|
||||
return $this->hasMany(\App\Models\User::class, 'location_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find assets with this location as their location_id
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function assets()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Asset::class, 'location_id')
|
||||
@@ -114,6 +135,14 @@ class Location extends SnipeModel
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Establishes the asset -> rtd_location relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function rtd_assets()
|
||||
{
|
||||
/* This used to have an ...->orHas() clause that referred to
|
||||
@@ -123,48 +152,93 @@ class Location extends SnipeModel
|
||||
It is arguable that we should have a '...->whereNull('assigned_to')
|
||||
bit in there, but that isn't always correct either (in the case
|
||||
where a user has no location, for example).
|
||||
|
||||
In all likelyhood, we need to denorm an "effective_location" column
|
||||
into Assets to make this slightly less miserable.
|
||||
*/
|
||||
return $this->hasMany(\App\Models\Asset::class, 'rtd_location_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the consumable -> location relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function consumables()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Consumable::class, 'location_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the component -> location relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function components()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Component::class, 'location_id');
|
||||
}
|
||||
|
||||
/**
|
||||
* Establishes the component -> accessory relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function accessories()
|
||||
{
|
||||
return $this->hasMany(\App\Models\Accessory::class, 'location_id');
|
||||
}
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* Find the parent of a location
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v2.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function parent()
|
||||
{
|
||||
return $this->belongsTo(self::class, 'parent_id', 'id')
|
||||
->with('parent');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find the manager of a location
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v2.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function manager()
|
||||
{
|
||||
return $this->belongsTo(\App\Models\User::class, 'manager_id');
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Find children of a location
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v2.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function children()
|
||||
{
|
||||
return $this->hasMany(self::class, 'parent_id')
|
||||
->with('children');
|
||||
}
|
||||
|
||||
// I don't think we need this anymore since we de-normed location_id in assets?
|
||||
/**
|
||||
* Establishes the asset -> location assignment relationship
|
||||
*
|
||||
* @author A. Gianotto <snipe@snipe.net>
|
||||
* @since [v3.0]
|
||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||
*/
|
||||
public function assignedAssets()
|
||||
{
|
||||
return $this->morphMany(\App\Models\Asset::class, 'assigned', 'assigned_type', 'assigned_to')->withTrashed();
|
||||
|
||||
@@ -189,7 +189,7 @@ trait Loggable
|
||||
$params = [
|
||||
'item' => $log->item,
|
||||
'filename' => $log->filename,
|
||||
'admin' => $log->user,
|
||||
'admin' => $log->admin,
|
||||
'location' => ($location) ? $location->name : '',
|
||||
'note' => $note,
|
||||
];
|
||||
|
||||
@@ -8,9 +8,10 @@ use Illuminate\Notifications\Notifiable;
|
||||
use Illuminate\Support\Collection;
|
||||
use Illuminate\Support\Facades\App;
|
||||
use Illuminate\Support\Facades\Cache;
|
||||
use Parsedown;
|
||||
use App\Helpers\Helper;
|
||||
use Watson\Validating\ValidatingTrait;
|
||||
|
||||
|
||||
/**
|
||||
* Settings model.
|
||||
*/
|
||||
@@ -135,7 +136,6 @@ class Setting extends Model
|
||||
public function lar_ver(): string
|
||||
{
|
||||
$app = App::getFacadeApplication();
|
||||
|
||||
return $app::VERSION;
|
||||
}
|
||||
|
||||
@@ -147,9 +147,7 @@ class Setting extends Model
|
||||
public static function getDefaultEula(): ?string
|
||||
{
|
||||
if (self::getSettings()->default_eula_text) {
|
||||
$parsedown = new Parsedown();
|
||||
|
||||
return $parsedown->text(e(self::getSettings()->default_eula_text));
|
||||
return Helper::parseEscapedMarkedown(self::getSettings()->default_eula_text);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -41,6 +41,11 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
|
||||
}
|
||||
);
|
||||
|
||||
// externalId support
|
||||
$config['validations'][$core.'externalId'] = 'string|nullable'; // not required, but supported mostly just for Okta
|
||||
// note that the mapping is *not* namespaced like the other $mappings
|
||||
$config['mapping']['externalId'] = AttributeMapping::eloquent('scim_externalid');
|
||||
|
||||
$config['validations'][$core.'emails'] = 'nullable|array'; // emails are not required in Snipe-IT...
|
||||
$config['validations'][$core.'emails.*.value'] = 'email'; // ...(had to remove the recommended 'required' here)
|
||||
|
||||
|
||||
@@ -59,6 +59,9 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
'username',
|
||||
'zip',
|
||||
'remote',
|
||||
'start_date',
|
||||
'end_date',
|
||||
'scim_externalid'
|
||||
];
|
||||
|
||||
protected $casts = [
|
||||
@@ -68,6 +71,16 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
'company_id' => 'integer',
|
||||
];
|
||||
|
||||
|
||||
protected $dates = [
|
||||
'created_at',
|
||||
'updated_at',
|
||||
'deleted_at',
|
||||
'start_date',
|
||||
'end_date',
|
||||
];
|
||||
|
||||
|
||||
/**
|
||||
* Model validation rules
|
||||
*
|
||||
@@ -83,6 +96,8 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||
'website' => 'url|nullable|max:191',
|
||||
'manager_id' => 'nullable|exists:users,id|cant_manage_self',
|
||||
'location_id' => 'exists:locations,id|nullable',
|
||||
'start_date' => 'nullable|date',
|
||||
'end_date' => 'nullable|date|after_or_equal:start_date',
|
||||
];
|
||||
|
||||
/**
|
||||
|
||||
@@ -0,0 +1,72 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class AcceptanceAssetAcceptedNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($params)
|
||||
{
|
||||
$this->item_tag = $params['item_tag'];
|
||||
$this->item_model = $params['item_model'];
|
||||
$this->item_serial = $params['item_serial'];
|
||||
$this->accepted_date = Helper::getFormattedDateObject($params['accepted_date'], 'date', false);
|
||||
$this->assigned_to = $params['assigned_to'];
|
||||
$this->company_name = $params['company_name'];
|
||||
$this->settings = Setting::getSettings();
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via()
|
||||
{
|
||||
|
||||
$notifyBy[] = 'mail';
|
||||
|
||||
return $notifyBy;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail()
|
||||
{
|
||||
$message = (new MailMessage)->markdown('notifications.markdown.asset-acceptance',
|
||||
[
|
||||
'item_tag' => $this->item_tag,
|
||||
'item_model' => $this->item_model,
|
||||
'item_serial' => $this->item_serial,
|
||||
'accepted_date' => $this->accepted_date,
|
||||
'assigned_to' => $this->assigned_to,
|
||||
'company_name' => $this->company_name,
|
||||
'intro_text' => trans('mail.acceptance_asset_accepted'),
|
||||
])
|
||||
->subject(trans('mail.acceptance_asset_accepted'));
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -0,0 +1,70 @@
|
||||
<?php
|
||||
|
||||
namespace App\Notifications;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
use App\Models\Setting;
|
||||
use Illuminate\Bus\Queueable;
|
||||
use Illuminate\Contracts\Queue\ShouldQueue;
|
||||
use Illuminate\Notifications\Messages\MailMessage;
|
||||
use Illuminate\Notifications\Messages\SlackMessage;
|
||||
use Illuminate\Notifications\Notification;
|
||||
|
||||
class AcceptanceAssetDeclinedNotification extends Notification
|
||||
{
|
||||
use Queueable;
|
||||
|
||||
/**
|
||||
* Create a new notification instance.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function __construct($params)
|
||||
{
|
||||
$this->item_tag = $params['item_tag'];
|
||||
$this->item_model = $params['item_model'];
|
||||
$this->item_serial = $params['item_serial'];
|
||||
$this->declined_date = Helper::getFormattedDateObject($params['declined_date'], 'date', false);
|
||||
$this->assigned_to = $params['assigned_to'];
|
||||
$this->company_name = $params['company_name'];
|
||||
$this->settings = Setting::getSettings();
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the notification's delivery channels.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return array
|
||||
*/
|
||||
public function via($notifiable)
|
||||
{
|
||||
$notifyBy[] = 'mail';
|
||||
|
||||
return $notifyBy;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the mail representation of the notification.
|
||||
*
|
||||
* @param mixed $notifiable
|
||||
* @return \Illuminate\Notifications\Messages\MailMessage
|
||||
*/
|
||||
public function toMail($notifiable)
|
||||
{
|
||||
$message = (new MailMessage)->markdown('notifications.markdown.asset-acceptance',
|
||||
[
|
||||
'item_tag' => $this->item_tag,
|
||||
'item_model' => $this->item_model,
|
||||
'item_serial' => $this->item_serial,
|
||||
'declined_date' => $this->declined_date,
|
||||
'assigned_to' => $this->assigned_to,
|
||||
'company_name' => $this->company_name,
|
||||
'intro_text' => trans('mail.acceptance_asset_declined'),
|
||||
])
|
||||
->subject(trans('mail.acceptance_asset_declined'));
|
||||
|
||||
return $message;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -42,8 +42,12 @@ class LicensePolicy extends CheckoutablePermissionsPolicy
|
||||
* @param \App\Models\User $user
|
||||
* @return mixed
|
||||
*/
|
||||
public function files(User $user)
|
||||
public function files(User $user, $license = null)
|
||||
{
|
||||
return $user->hasAccess($this->columnName().'.files');
|
||||
if ($user->hasAccess('licenses.files')) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -61,6 +61,11 @@ abstract class SnipePermissionsPolicy
|
||||
return $user->hasAccess($this->columnName().'.view');
|
||||
}
|
||||
|
||||
public function files(User $user, $item = null)
|
||||
{
|
||||
return $user->hasAccess($this->columnName().'.files');
|
||||
}
|
||||
|
||||
/**
|
||||
* Determine whether the user can create accessories.
|
||||
*
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
|
||||
namespace App\Presenters;
|
||||
|
||||
use App\Helpers\Helper;
|
||||
|
||||
/**
|
||||
* Class AssetModelPresenter
|
||||
*/
|
||||
@@ -159,10 +161,8 @@ class AssetModelPresenter extends Presenter
|
||||
*/
|
||||
public function note()
|
||||
{
|
||||
$Parsedown = new \Parsedown();
|
||||
|
||||
if ($this->model->note) {
|
||||
return $Parsedown->text($this->model->note);
|
||||
return Helper::parseEscapedMarkedown($this->model->note);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -70,47 +70,33 @@ class CategoryPresenter extends Presenter
|
||||
'visible' => true,
|
||||
'formatter' => 'trueFalseFormatter',
|
||||
], [
|
||||
'field' => 'actions',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => false,
|
||||
'title' => trans('table.actions'),
|
||||
],[
|
||||
"field" => "use_default_eula",
|
||||
"searchable" => false,
|
||||
"sortable" => true,
|
||||
"title" => trans('admin/categories/general.use_default_eula_column'),
|
||||
'visible' => true,
|
||||
"formatter" => 'trueFalseFormatter',
|
||||
],[
|
||||
"field" => "checkin_email",
|
||||
"searchable" => false,
|
||||
"sortable" => true,
|
||||
"class" => 'css-envelope',
|
||||
"title" => 'Send Email',
|
||||
"visible" => true,
|
||||
"formatter" => 'trueFalseFormatter',
|
||||
],[
|
||||
"field" => "require_acceptance",
|
||||
"searchable" => false,
|
||||
"sortable" => true,
|
||||
'formatter' => 'categoriesActionsFormatter',
|
||||
],
|
||||
[
|
||||
], [
|
||||
'field' => 'created_at',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'title' => trans('general.created_at'),
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
],
|
||||
[
|
||||
], [
|
||||
'field' => 'updated_at',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'visible' => false,
|
||||
'title' => trans('general.updated_at'),
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
], [
|
||||
'field' => 'actions',
|
||||
'searchable' => false,
|
||||
'sortable' => false,
|
||||
'switchable' => false,
|
||||
'title' => trans('table.actions'),
|
||||
'formatter' => 'categoriesActionsFormatter',
|
||||
],
|
||||
];
|
||||
|
||||
|
||||
@@ -55,17 +55,28 @@ class LocationPresenter extends Presenter
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/locations/table.assets_rtd'),
|
||||
'title' => trans('admin/locations/message.current_location'),
|
||||
'visible' => true,
|
||||
],
|
||||
|
||||
[
|
||||
'field' => 'rtd_assets_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/hardware/form.default_location'),
|
||||
'visible' => false,
|
||||
],
|
||||
|
||||
[
|
||||
'field' => 'assigned_assets_count',
|
||||
'searchable' => false,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('admin/locations/table.assets_checkedout'),
|
||||
'title' => trans('admin/locations/message.assigned_assets'),
|
||||
'visible' => true,
|
||||
],
|
||||
|
||||
[
|
||||
'field' => 'users_count',
|
||||
'searchable' => false,
|
||||
|
||||
@@ -302,6 +302,24 @@ class UserPresenter extends Presenter
|
||||
'visible' => false,
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'start_date',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.start_date'),
|
||||
'visible' => false,
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'end_date',
|
||||
'searchable' => true,
|
||||
'sortable' => true,
|
||||
'switchable' => true,
|
||||
'title' => trans('general.end_date'),
|
||||
'visible' => false,
|
||||
'formatter' => 'dateDisplayFormatter',
|
||||
],
|
||||
[
|
||||
'field' => 'last_login',
|
||||
'searchable' => false,
|
||||
|
||||
@@ -122,6 +122,13 @@ class AuthServiceProvider extends ServiceProvider
|
||||
});
|
||||
|
||||
|
||||
Gate::define('licenses.files', function ($user) {
|
||||
if ($user->hasAccess('licenses.files')) {
|
||||
return true;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
// -----------------------------------------
|
||||
// Reports
|
||||
// -----------------------------------------
|
||||
|
||||
+1
-2
@@ -61,7 +61,7 @@
|
||||
"nunomaduro/collision": "^5.4",
|
||||
"onelogin/php-saml": "^3.4",
|
||||
"paragonie/constant_time_encoding": "^2.3",
|
||||
"patchwork/utf8": "^1.3",
|
||||
"symfony/polyfill-mbstring": "^1.22",
|
||||
"phpdocumentor/reflection-docblock": "^5.1",
|
||||
"phpspec/prophecy": "^1.10",
|
||||
"pragmarx/google2fa-laravel": "^1.3",
|
||||
@@ -75,7 +75,6 @@
|
||||
"fakerphp/faker": "^1.16",
|
||||
"laravel/dusk": "^6.19",
|
||||
"mockery/mockery": "^1.4",
|
||||
"overtrue/phplint": "^3.0",
|
||||
"phpunit/php-token-stream": "^3.1",
|
||||
"phpunit/phpunit": "^9.0",
|
||||
"squizlabs/php_codesniffer": "^3.5",
|
||||
|
||||
Generated
+9
-277
@@ -4,7 +4,7 @@
|
||||
"Read more about it at https://getcomposer.org/doc/01-basic-usage.md#installing-dependencies",
|
||||
"This file is @generated automatically"
|
||||
],
|
||||
"content-hash": "9ddc3034bff0b7422031de3ea9809b2a",
|
||||
"content-hash": "0c1f3848f8c9ede2b5f1513e4feaa7d7",
|
||||
"packages": [
|
||||
{
|
||||
"name": "alek13/slack",
|
||||
@@ -78,18 +78,18 @@
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/grokability/laravel-scim-server.git",
|
||||
"reference": "d0e3d7c0b5da2ec76283b8a2fa2e672a91596509"
|
||||
"reference": "2c7ecc450eee59234e059ec2e7724b2d8f3a8369"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/grokability/laravel-scim-server/zipball/d0e3d7c0b5da2ec76283b8a2fa2e672a91596509",
|
||||
"reference": "d0e3d7c0b5da2ec76283b8a2fa2e672a91596509",
|
||||
"url": "https://api.github.com/repos/grokability/laravel-scim-server/zipball/2c7ecc450eee59234e059ec2e7724b2d8f3a8369",
|
||||
"reference": "2c7ecc450eee59234e059ec2e7724b2d8f3a8369",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"illuminate/console": "^6.0|^7.0|^8.0",
|
||||
"illuminate/database": "^6.0|^7.0|^8.0",
|
||||
"illuminate/support": "^6.0|^7.0|^8.0",
|
||||
"illuminate/console": "^6.0|^7.0|^8.0|^9.0",
|
||||
"illuminate/database": "^6.0|^7.0|^8.0|^9.0",
|
||||
"illuminate/support": "^6.0|^7.0|^8.0|^9.0",
|
||||
"php": "^7.0|^8.0",
|
||||
"tmilos/scim-filter-parser": "^1.3",
|
||||
"tmilos/scim-schema": "^0.1.0"
|
||||
@@ -133,7 +133,7 @@
|
||||
"support": {
|
||||
"source": "https://github.com/grokability/laravel-scim-server/tree/master"
|
||||
},
|
||||
"time": "2022-07-18T22:15:42+00:00"
|
||||
"time": "2022-11-22T20:26:54+00:00"
|
||||
},
|
||||
{
|
||||
"name": "asm89/stack-cors",
|
||||
@@ -6299,83 +6299,6 @@
|
||||
},
|
||||
"time": "2020-10-15T08:29:30+00:00"
|
||||
},
|
||||
{
|
||||
"name": "patchwork/utf8",
|
||||
"version": "v1.3.3",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/tchwork/utf8.git",
|
||||
"reference": "e1fa4d4a57896d074c9a8d01742b688d5db4e9d5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/tchwork/utf8/zipball/e1fa4d4a57896d074c9a8d01742b688d5db4e9d5",
|
||||
"reference": "e1fa4d4a57896d074c9a8d01742b688d5db4e9d5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"lib-pcre": ">=7.3",
|
||||
"php": ">=5.3.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/phpunit-bridge": "^3.4|^4.4"
|
||||
},
|
||||
"suggest": {
|
||||
"ext-iconv": "Use iconv for best performance",
|
||||
"ext-intl": "Use Intl for best performance",
|
||||
"ext-mbstring": "Use Mbstring for best performance",
|
||||
"ext-wfio": "Use WFIO for UTF-8 filesystem access on Windows"
|
||||
},
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"branch-alias": {
|
||||
"dev-master": "1.3-dev"
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Patchwork\\": "src/Patchwork/"
|
||||
},
|
||||
"classmap": [
|
||||
"src/Normalizer.php"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"(Apache-2.0 or GPL-2.0)"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Nicolas Grekas",
|
||||
"email": "p@tchwork.com"
|
||||
}
|
||||
],
|
||||
"description": "Portable and performant UTF-8, Unicode and Grapheme Clusters for PHP",
|
||||
"homepage": "https://github.com/tchwork/utf8",
|
||||
"keywords": [
|
||||
"grapheme",
|
||||
"i18n",
|
||||
"unicode",
|
||||
"utf-8",
|
||||
"utf8"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/tchwork/utf8/issues",
|
||||
"source": "https://github.com/tchwork/utf8/tree/v1.3.3"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/nicolas-grekas",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/patchwork/utf8",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"abandoned": "symfony/polyfill-mbstring or symfony/string",
|
||||
"time": "2021-01-07T16:38:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phenx/php-font-lib",
|
||||
"version": "0.5.4",
|
||||
@@ -12126,122 +12049,6 @@
|
||||
],
|
||||
"time": "2022-03-03T13:19:32+00:00"
|
||||
},
|
||||
{
|
||||
"name": "n98/junit-xml",
|
||||
"version": "1.1.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/cmuench/junit-xml.git",
|
||||
"reference": "0017dd92ac8cb619f02e32f4cffd768cfe327c73"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/cmuench/junit-xml/zipball/0017dd92ac8cb619f02e32f4cffd768cfe327c73",
|
||||
"reference": "0017dd92ac8cb619f02e32f4cffd768cfe327c73",
|
||||
"shasum": ""
|
||||
},
|
||||
"require-dev": {
|
||||
"phpunit/phpunit": "^9.5.0"
|
||||
},
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"N98\\JUnitXml\\": "src/N98/JUnitXml"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Christian Münch",
|
||||
"email": "c.muench@netz98.de"
|
||||
}
|
||||
],
|
||||
"description": "JUnit XML Document generation library",
|
||||
"support": {
|
||||
"issues": "https://github.com/cmuench/junit-xml/issues",
|
||||
"source": "https://github.com/cmuench/junit-xml/tree/1.1.0"
|
||||
},
|
||||
"time": "2020-12-25T09:08:58+00:00"
|
||||
},
|
||||
{
|
||||
"name": "overtrue/phplint",
|
||||
"version": "3.2.0",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/overtrue/phplint.git",
|
||||
"reference": "c3021ad8cebd802ad3f4924c45f508803e0b80e5"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/overtrue/phplint/zipball/c3021ad8cebd802ad3f4924c45f508803e0b80e5",
|
||||
"reference": "c3021ad8cebd802ad3f4924c45f508803e0b80e5",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"ext-json": "*",
|
||||
"n98/junit-xml": "1.1.0",
|
||||
"php": "^5.5.9 || ^7.0",
|
||||
"symfony/console": "^3.2 || ^4.0 || ^5.0",
|
||||
"symfony/finder": "^3.0 || ^4.0 || ^5.0",
|
||||
"symfony/process": "^3.3 || ^4.0 || ^5.0",
|
||||
"symfony/yaml": "^3.0 || ^4.0 || ^5.0"
|
||||
},
|
||||
"require-dev": {
|
||||
"brainmaestro/composer-git-hooks": "^2.7",
|
||||
"friendsofphp/php-cs-fixer": "^2.16",
|
||||
"jakub-onderka/php-console-highlighter": "^0.3.2 || ^0.4"
|
||||
},
|
||||
"bin": [
|
||||
"bin/phplint"
|
||||
],
|
||||
"type": "library",
|
||||
"extra": {
|
||||
"hooks": {
|
||||
"pre-commit": [
|
||||
"composer fix-style"
|
||||
],
|
||||
"pre-push": [
|
||||
"composer check-style"
|
||||
]
|
||||
}
|
||||
},
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Overtrue\\PHPLint\\": "src/"
|
||||
}
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "overtrue",
|
||||
"email": "anzhengchao@gmail.com"
|
||||
}
|
||||
],
|
||||
"description": "`phplint` is a tool that can speed up linting of php files by running several lint processes at once.",
|
||||
"keywords": [
|
||||
"check",
|
||||
"lint",
|
||||
"phplint",
|
||||
"syntax"
|
||||
],
|
||||
"support": {
|
||||
"issues": "https://github.com/overtrue/phplint/issues",
|
||||
"source": "https://github.com/overtrue/phplint/tree/3.2.0"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://github.com/overtrue",
|
||||
"type": "github"
|
||||
}
|
||||
],
|
||||
"time": "2022-07-12T07:37:04+00:00"
|
||||
},
|
||||
{
|
||||
"name": "phar-io/manifest",
|
||||
"version": "2.0.3",
|
||||
@@ -13656,81 +13463,6 @@
|
||||
],
|
||||
"time": "2022-04-30T18:34:00+00:00"
|
||||
},
|
||||
{
|
||||
"name": "symfony/yaml",
|
||||
"version": "v5.4.10",
|
||||
"source": {
|
||||
"type": "git",
|
||||
"url": "https://github.com/symfony/yaml.git",
|
||||
"reference": "04e42926429d9e8b39c174387ab990bf7817f7a2"
|
||||
},
|
||||
"dist": {
|
||||
"type": "zip",
|
||||
"url": "https://api.github.com/repos/symfony/yaml/zipball/04e42926429d9e8b39c174387ab990bf7817f7a2",
|
||||
"reference": "04e42926429d9e8b39c174387ab990bf7817f7a2",
|
||||
"shasum": ""
|
||||
},
|
||||
"require": {
|
||||
"php": ">=7.2.5",
|
||||
"symfony/deprecation-contracts": "^2.1|^3",
|
||||
"symfony/polyfill-ctype": "^1.8"
|
||||
},
|
||||
"conflict": {
|
||||
"symfony/console": "<5.3"
|
||||
},
|
||||
"require-dev": {
|
||||
"symfony/console": "^5.3|^6.0"
|
||||
},
|
||||
"suggest": {
|
||||
"symfony/console": "For validating YAML files using the lint command"
|
||||
},
|
||||
"bin": [
|
||||
"Resources/bin/yaml-lint"
|
||||
],
|
||||
"type": "library",
|
||||
"autoload": {
|
||||
"psr-4": {
|
||||
"Symfony\\Component\\Yaml\\": ""
|
||||
},
|
||||
"exclude-from-classmap": [
|
||||
"/Tests/"
|
||||
]
|
||||
},
|
||||
"notification-url": "https://packagist.org/downloads/",
|
||||
"license": [
|
||||
"MIT"
|
||||
],
|
||||
"authors": [
|
||||
{
|
||||
"name": "Fabien Potencier",
|
||||
"email": "fabien@symfony.com"
|
||||
},
|
||||
{
|
||||
"name": "Symfony Community",
|
||||
"homepage": "https://symfony.com/contributors"
|
||||
}
|
||||
],
|
||||
"description": "Loads and dumps YAML files",
|
||||
"homepage": "https://symfony.com",
|
||||
"support": {
|
||||
"source": "https://github.com/symfony/yaml/tree/v5.4.10"
|
||||
},
|
||||
"funding": [
|
||||
{
|
||||
"url": "https://symfony.com/sponsor",
|
||||
"type": "custom"
|
||||
},
|
||||
{
|
||||
"url": "https://github.com/fabpot",
|
||||
"type": "github"
|
||||
},
|
||||
{
|
||||
"url": "https://tidelift.com/funding/github/packagist/symfony/symfony",
|
||||
"type": "tidelift"
|
||||
}
|
||||
],
|
||||
"time": "2022-06-20T11:50:59+00:00"
|
||||
},
|
||||
{
|
||||
"name": "theseer/tokenizer",
|
||||
"version": "1.2.1",
|
||||
@@ -13798,5 +13530,5 @@
|
||||
"ext-pdo": "*"
|
||||
},
|
||||
"platform-dev": [],
|
||||
"plugin-api-version": "2.0.0"
|
||||
"plugin-api-version": "2.3.0"
|
||||
}
|
||||
|
||||
+17
-1
@@ -394,7 +394,7 @@ return [
|
||||
'allow_purge' => env('ALLOW_DATA_PURGE', false),
|
||||
|
||||
|
||||
/*
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Allow Backup Deletion
|
||||
|--------------------------------------------------------------------------
|
||||
@@ -405,4 +405,20 @@ return [
|
||||
|
||||
'allow_backup_delete' => env('ALLOW_BACKUP_DELETE', false),
|
||||
|
||||
|
||||
/*
|
||||
|--------------------------------------------------------------------------
|
||||
| Escape Excel formulas in CSV exports
|
||||
|--------------------------------------------------------------------------
|
||||
|
|
||||
| This determins whether or not we should escape Excel formulas in CSV exports.
|
||||
| This can be UNSAFE in untrusted environments, and therefore defaults to true
|
||||
| so that Excel forumals WILL be escaped in CSV exports, however if your workflow
|
||||
| is designed around using formulas in your fields, you
|
||||
| you can set CSV_ESCAPE_FORMULAS to 'false' in your .env.
|
||||
|
|
||||
*/
|
||||
|
||||
'escape_formulas' => env('CSV_ESCAPE_FORMULAS', true),
|
||||
|
||||
];
|
||||
|
||||
@@ -100,6 +100,11 @@ return [
|
||||
'emergency' => [
|
||||
'path' => storage_path('logs/laravel.log'),
|
||||
],
|
||||
|
||||
'scimtrace' => [
|
||||
'driver' => 'single',
|
||||
'path' => storage_path('logs/scim.log')
|
||||
]
|
||||
],
|
||||
|
||||
];
|
||||
|
||||
@@ -145,6 +145,13 @@ return [
|
||||
'note' => '',
|
||||
'display' => true,
|
||||
],
|
||||
[
|
||||
'permission' => 'accessories.files',
|
||||
'label' => 'View and Modify Accessory Files',
|
||||
'note' => '',
|
||||
'display' => true,
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
'Consumables' => [
|
||||
@@ -178,6 +185,12 @@ return [
|
||||
'note' => '',
|
||||
'display' => true,
|
||||
],
|
||||
[
|
||||
'permission' => 'consumables.files',
|
||||
'label' => 'View and Modify Consumable Files',
|
||||
'note' => '',
|
||||
'display' => true,
|
||||
],
|
||||
],
|
||||
|
||||
|
||||
@@ -264,6 +277,12 @@ return [
|
||||
'note' => '',
|
||||
'display' => true,
|
||||
],
|
||||
[
|
||||
'permission' => 'components.files',
|
||||
'label' => 'View and Modify Component Files',
|
||||
'note' => '',
|
||||
'display' => true,
|
||||
],
|
||||
|
||||
],
|
||||
|
||||
|
||||
+4
-1
@@ -1,5 +1,8 @@
|
||||
<?php
|
||||
|
||||
return [
|
||||
"publish_routes" => false
|
||||
"trace" => env("SCIM_TRACE",false),
|
||||
// below, if we ever get 'sure' that we can change this default to 'true' we should
|
||||
"omit_main_schema_in_return" => env('SCIM_STANDARDS_COMPLIANCE', false),
|
||||
"publish_routes" => false,
|
||||
];
|
||||
|
||||
+5
-5
@@ -1,10 +1,10 @@
|
||||
<?php
|
||||
return array (
|
||||
'app_version' => 'v6.0.10',
|
||||
'full_app_version' => 'v6.0.10 - build 8610-g22710afee',
|
||||
'build_version' => '8610',
|
||||
'app_version' => 'v6.0.14',
|
||||
'full_app_version' => 'v6.0.14 - build 9038-g163b3f6c0',
|
||||
'build_version' => '9038',
|
||||
'prerelease_version' => '',
|
||||
'hash_version' => 'g22710afee',
|
||||
'full_hash' => 'v6.0.10-91-g22710afee',
|
||||
'hash_version' => 'g163b3f6c0',
|
||||
'full_hash' => 'v6.0.14-113-g163b3f6c0',
|
||||
'branch' => 'master',
|
||||
);
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddChartTypeToSettings extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
$table->string('dash_chart_type')->nullable()->default('name');
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('settings', function (Blueprint $table) {
|
||||
if (Schema::hasColumn('settings', 'dash_chart_type')) {
|
||||
$table->dropColumn('dash_chart_type');
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,34 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddStartTerminationDateToUsers extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->date('start_date')->nullable()->default(null);
|
||||
$table->date('end_date')->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('start_date');
|
||||
$table->dropColumn('end_date');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddExternalidToUsers extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->string('scim_externalid')->nullable()->default(null);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('users', function (Blueprint $table) {
|
||||
$table->dropColumn('scim_externalid');
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<?php
|
||||
|
||||
use Illuminate\Database\Migrations\Migration;
|
||||
use Illuminate\Database\Schema\Blueprint;
|
||||
use Illuminate\Support\Facades\Schema;
|
||||
|
||||
class AddDisplayToUserInCustomFields extends Migration
|
||||
{
|
||||
/**
|
||||
* Run the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function up()
|
||||
{
|
||||
Schema::table('custom_fields', function (Blueprint $table) {
|
||||
$table->boolean('display_in_user_view')->nullable()->default(0);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverse the migrations.
|
||||
*
|
||||
* @return void
|
||||
*/
|
||||
public function down()
|
||||
{
|
||||
Schema::table('custom_fields', function (Blueprint $table) {
|
||||
$table->dropColumn('display_in_user_view');
|
||||
});
|
||||
}
|
||||
}
|
||||
+3
-1
@@ -26,6 +26,8 @@ services:
|
||||
- .env.docker
|
||||
networks:
|
||||
- snipeit-backend
|
||||
ports:
|
||||
- "3306:3306"
|
||||
|
||||
redis:
|
||||
image: redis:6.2.5-buster
|
||||
@@ -45,4 +47,4 @@ volumes:
|
||||
db: {}
|
||||
|
||||
networks:
|
||||
snipeit-backend: {}
|
||||
snipeit-backend: {}
|
||||
|
||||
Generated
+3
-3
@@ -1329,9 +1329,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"@fortawesome/fontawesome-free": {
|
||||
"version": "6.1.2",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.1.2.tgz",
|
||||
"integrity": "sha512-XwWADtfdSN73/udaFm+1mnGIj/ShDZNFMe/PRoqv3FhQ4GNI2PUN70yFTPsjq65Lw2C9i4TG5/hTbxXIXVCiqQ=="
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.2.0.tgz",
|
||||
"integrity": "sha512-CNR7qRIfCwWHNN7FnKUniva94edPdyQzil/zCwk3v6k4R6rR2Fr8i4s3PM7n/lyfPA6Zfko9z5WDzFxG9SW1uQ=="
|
||||
},
|
||||
"@jridgewell/gen-mapping": {
|
||||
"version": "0.1.1",
|
||||
|
||||
+1
-1
@@ -24,7 +24,7 @@
|
||||
"vue-template-compiler": "2.4.4"
|
||||
},
|
||||
"dependencies": {
|
||||
"@fortawesome/fontawesome-free": "^6.1.2",
|
||||
"@fortawesome/fontawesome-free": "^6.2.0",
|
||||
"acorn": "^8.8.0",
|
||||
"acorn-import-assertions": "^1.8.0",
|
||||
"admin-lte": "^2.4.18",
|
||||
|
||||
+19
-3
@@ -37,6 +37,22 @@
|
||||
</IfModule>
|
||||
Options -Indexes
|
||||
|
||||
<Files "web.config">
|
||||
Deny from all
|
||||
</Files>
|
||||
# DENY ACCESS TO IIS CONFIG FILE
|
||||
|
||||
# Apache 2.2+
|
||||
<IfModule !authz_core_module>
|
||||
<Files "web.config">
|
||||
Order allow,deny
|
||||
Deny from all
|
||||
</Files>
|
||||
</IfModule>
|
||||
|
||||
# Apache 2.4+
|
||||
<IfModule authz_core_module>
|
||||
<Files "web.config">
|
||||
Require all denied
|
||||
</Files>
|
||||
</IfModule>
|
||||
|
||||
|
||||
|
||||
|
||||
+1
-5436
File diff suppressed because one or more lines are too long
+1
-953
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
Vendored
+8
-24856
File diff suppressed because one or more lines are too long
Vendored
+1
-395
File diff suppressed because one or more lines are too long
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user