Merge branch 'develop' into develop
This commit is contained in:
commit
c2c009a018
693 changed files with 6136 additions and 3136 deletions
|
@ -2783,6 +2783,60 @@
|
||||||
"contributions": [
|
"contributions": [
|
||||||
"code"
|
"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"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "scoo73r",
|
||||||
|
"name": "Scooter Crawford",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/9262438?v=4",
|
||||||
|
"profile": "https://github.com/scoo73r",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "subdriven",
|
||||||
|
"name": "subdriven",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/5957345?v=4",
|
||||||
|
"profile": "https://github.com/subdriven",
|
||||||
|
"contributions": [
|
||||||
|
"code"
|
||||||
|
]
|
||||||
}
|
}
|
||||||
]
|
]
|
||||||
}
|
}
|
||||||
|
|
|
@ -174,3 +174,9 @@ REPORT_TIME_LIMIT=12000
|
||||||
REQUIRE_SAML=false
|
REQUIRE_SAML=false
|
||||||
API_THROTTLE_PER_MINUTE=120
|
API_THROTTLE_PER_MINUTE=120
|
||||||
CSV_ESCAPE_FORMULAS=true
|
CSV_ESCAPE_FORMULAS=true
|
||||||
|
|
||||||
|
# --------------------------------------------
|
||||||
|
# OPTIONAL: SCIM
|
||||||
|
# --------------------------------------------
|
||||||
|
SCIM_TRACE=false
|
||||||
|
SCIM_STANDARDS_COMPLIANCE=false
|
2
.github/workflows/SA-codeql.yml
vendored
2
.github/workflows/SA-codeql.yml
vendored
|
@ -26,7 +26,7 @@ jobs:
|
||||||
language: [ 'javascript' ]
|
language: [ 'javascript' ]
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout repository
|
- name: Checkout repository
|
||||||
uses: actions/checkout@v3.1.0
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
# Initializes the CodeQL tools for scanning.
|
# Initializes the CodeQL tools for scanning.
|
||||||
- name: Initialize CodeQL
|
- name: Initialize CodeQL
|
||||||
|
|
2
.github/workflows/codacy-analysis.yml
vendored
2
.github/workflows/codacy-analysis.yml
vendored
|
@ -32,7 +32,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
# Checkout the repository to the GitHub Actions runner
|
# Checkout the repository to the GitHub Actions runner
|
||||||
- name: Checkout code
|
- name: Checkout code
|
||||||
uses: actions/checkout@v3.1.0
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
# Execute Codacy Analysis CLI and generate a SARIF output with the security issues identified during the analysis
|
||||||
- name: Run Codacy Analysis CLI
|
- name: Run Codacy Analysis CLI
|
||||||
|
|
2
.github/workflows/docker-alpine.yml
vendored
2
.github/workflows/docker-alpine.yml
vendored
|
@ -41,7 +41,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
# https://github.com/actions/checkout
|
# https://github.com/actions/checkout
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v3.1.0
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
# https://github.com/docker/setup-buildx-action
|
# https://github.com/docker/setup-buildx-action
|
||||||
- name: Setup Docker Buildx
|
- name: Setup Docker Buildx
|
||||||
|
|
2
.github/workflows/docker.yml
vendored
2
.github/workflows/docker.yml
vendored
|
@ -41,7 +41,7 @@ jobs:
|
||||||
steps:
|
steps:
|
||||||
# https://github.com/actions/checkout
|
# https://github.com/actions/checkout
|
||||||
- name: Checkout codebase
|
- name: Checkout codebase
|
||||||
uses: actions/checkout@v3.1.0
|
uses: actions/checkout@v3.3.0
|
||||||
|
|
||||||
# https://github.com/docker/setup-buildx-action
|
# https://github.com/docker/setup-buildx-action
|
||||||
- name: Setup Docker Buildx
|
- name: Setup Docker Buildx
|
||||||
|
|
|
@ -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)
|
 [](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
|
## Snipe-IT - Open Source Asset Management System
|
||||||
|
|
||||||
|
@ -60,6 +60,7 @@ Since the release of the JSON REST API, several third-party developers have been
|
||||||
- [InQRy -unmaintained-](https://github.com/Microsoft/InQRy) by [@Microsoft](https://github.com/Microsoft)
|
- [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
|
- [SnipeitPS](https://github.com/snazy2000/SnipeitPS) by [@snazy2000](https://github.com/snazy2000) - Powershell API Wrapper for Snipe-it
|
||||||
- [jamf2snipe](https://github.com/grokability/jamf2snipe) - 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
|
||||||
|
- [jamf-snipe-rename](https://macblog.org/jamf-snipe-rename/) - Python script to rename computers in Jamf from Snipe-IT
|
||||||
- [Marksman](https://github.com/Scope-IT/marksman) - A Windows agent for Snipe-IT
|
- [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)
|
- [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.
|
- [Python 3 CSV importer](https://github.com/gastamper/snipeit-csvimporter) - allows importing assets into Snipe-IT based on Item Name rather than Asset Tag.
|
||||||
|
@ -138,7 +139,8 @@ Thanks goes to all of these wonderful people ([emoji key](https://github.com/ken
|
||||||
| [<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/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/97299851?v=4" width="110px;"/><br /><sub>Christian Weirich</sub>](https://github.com/chrisweirich)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chrisweirich "Code") | [<img src="https://avatars.githubusercontent.com/u/1294403?v=4" width="110px;"/><br /><sub>denzfarid</sub>](https://github.com/denzfarid)<br /> | [<img src="https://avatars.githubusercontent.com/u/94018771?v=4" width="110px;"/><br /><sub>ntbutler-nbcs</sub>](https://github.com/ntbutler-nbcs)<br />[💻](https://github.com/snipe/snipe-it/commits?author=ntbutler-nbcs "Code") | [<img src="https://avatars.githubusercontent.com/u/172697?v=4" width="110px;"/><br /><sub>Naveen</sub>](https://naveensrinivasan.dev)<br />[💻](https://github.com/snipe/snipe-it/commits?author=naveensrinivasan "Code") | [<img src="https://avatars.githubusercontent.com/u/55674383?v=4" width="110px;"/><br /><sub>Mike Roquemore</sub>](https://github.com/mikeroq)<br />[💻](https://github.com/snipe/snipe-it/commits?author=mikeroq "Code") | [<img src="https://avatars.githubusercontent.com/u/7991086?v=4" width="110px;"/><br /><sub>Daniel Reeder</sub>](https://github.com/reederda)<br />[🌍](#translation-reederda "Translation") [🌍](#translation-reederda "Translation") [💻](https://github.com/snipe/snipe-it/commits?author=reederda "Code") | [<img src="https://avatars.githubusercontent.com/u/109422491?v=4" width="110px;"/><br /><sub>vickyjaura183</sub>](https://github.com/vickyjaura183)<br />[💻](https://github.com/snipe/snipe-it/commits?author=vickyjaura183 "Code") |
|
||||||
| [<img src="https://avatars.githubusercontent.com/u/32363424?v=4" width="110px;"/><br /><sub>Peace</sub>](https://github.com/julian-piehl)<br />[💻](https://github.com/snipe/snipe-it/commits?author=julian-piehl "Code") | [<img src="https://avatars.githubusercontent.com/u/231528?v=4" width="110px;"/><br /><sub>Kyle Gordon</sub>](https://github.com/kylegordon)<br />[💻](https://github.com/snipe/snipe-it/commits?author=kylegordon "Code") | [<img src="https://avatars.githubusercontent.com/u/53009155?v=4" width="110px;"/><br /><sub>Katharina Drexel</sub>](http://www.bfh.ch)<br />[💻](https://github.com/snipe/snipe-it/commits?author=sunflowerbofh "Code") | [<img src="https://avatars.githubusercontent.com/u/1931963?v=4" width="110px;"/><br /><sub>David Sferruzza</sub>](https://david.sferruzza.fr/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=dsferruzza "Code") | [<img src="https://avatars.githubusercontent.com/u/19511639?v=4" width="110px;"/><br /><sub>Rick Nelson</sub>](https://github.com/rnelsonee)<br />[💻](https://github.com/snipe/snipe-it/commits?author=rnelsonee "Code") | [<img src="https://avatars.githubusercontent.com/u/94169344?v=4" width="110px;"/><br /><sub>BasO12</sub>](https://github.com/BasO12)<br />[💻](https://github.com/snipe/snipe-it/commits?author=BasO12 "Code") | [<img src="https://avatars.githubusercontent.com/u/111710123?v=4" width="110px;"/><br /><sub>Vautia</sub>](https://github.com/Vautia)<br />[💻](https://github.com/snipe/snipe-it/commits?author=Vautia "Code") |
|
| [<img src="https://avatars.githubusercontent.com/u/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/28321?v=4" width="110px;"/><br /><sub>Chris Hartjes</sub>](http://www.littlehart.net/atthekeyboard)<br />[💻](https://github.com/snipe/snipe-it/commits?author=chartjes "Code") | [<img src="https://avatars.githubusercontent.com/u/2404584?v=4" width="110px;"/><br /><sub>geo-chen</sub>](https://github.com/geo-chen)<br />[💻](https://github.com/snipe/snipe-it/commits?author=geo-chen "Code") | [<img src="https://avatars.githubusercontent.com/u/6006620?v=4" width="110px;"/><br /><sub>Phan Nguyen</sub>](https://github.com/nh314)<br />[💻](https://github.com/snipe/snipe-it/commits?author=nh314 "Code") | [<img src="https://avatars.githubusercontent.com/u/115993812?v=4" width="110px;"/><br /><sub>Iisakki Jaakkola</sub>](https://github.com/StarlessNights)<br />[💻](https://github.com/snipe/snipe-it/commits?author=StarlessNights "Code") | [<img src="https://avatars.githubusercontent.com/u/22633385?v=4" width="110px;"/><br /><sub>Ikko Ashimine</sub>](https://bandism.net/)<br />[💻](https://github.com/snipe/snipe-it/commits?author=eltociear "Code") | [<img src="https://avatars.githubusercontent.com/u/56871540?v=4" width="110px;"/><br /><sub>Lukas Fehling</sub>](https://github.com/lukasfehling)<br />[💻](https://github.com/snipe/snipe-it/commits?author=lukasfehling "Code") | [<img src="https://avatars.githubusercontent.com/u/1975990?v=4" width="110px;"/><br /><sub>Fernando Almeida</sub>](https://github.com/fernando-almeida)<br />[💻](https://github.com/snipe/snipe-it/commits?author=fernando-almeida "Code") |
|
||||||
|
| [<img src="https://avatars.githubusercontent.com/u/116301219?v=4" width="110px;"/><br /><sub>akemidx</sub>](https://github.com/akemidx)<br />[💻](https://github.com/snipe/snipe-it/commits?author=akemidx "Code") | [<img src="https://avatars.githubusercontent.com/u/144778?v=4" width="110px;"/><br /><sub>Oguz Bilgic</sub>](http://oguz.site)<br />[💻](https://github.com/snipe/snipe-it/commits?author=oguzbilgic "Code") | [<img src="https://avatars.githubusercontent.com/u/9262438?v=4" width="110px;"/><br /><sub>Scooter Crawford</sub>](https://github.com/scoo73r)<br />[💻](https://github.com/snipe/snipe-it/commits?author=scoo73r "Code") | [<img src="https://avatars.githubusercontent.com/u/5957345?v=4" width="110px;"/><br /><sub>subdriven</sub>](https://github.com/subdriven)<br />[💻](https://github.com/snipe/snipe-it/commits?author=subdriven "Code") |
|
||||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
This project follows the [all-contributors](https://github.com/kentcdodds/all-contributors) specification. Contributions of any kind welcome!
|
||||||
|
|
2
app.json
2
app.json
|
@ -148,7 +148,7 @@
|
||||||
"image": "heroku/php",
|
"image": "heroku/php",
|
||||||
"addons": [
|
"addons": [
|
||||||
"cleardb:ignite",
|
"cleardb:ignite",
|
||||||
"heroku-redis:hobby-dev",
|
"heroku-redis:mini",
|
||||||
"papertrail:choklad"
|
"papertrail:choklad"
|
||||||
]
|
]
|
||||||
}
|
}
|
|
@ -22,7 +22,7 @@ class CheckoutLicenseToAllUsers extends Command
|
||||||
*
|
*
|
||||||
* @var string
|
* @var string
|
||||||
*/
|
*/
|
||||||
protected $description = 'Command description';
|
protected $description = 'Checks out licenses to all users';
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Create a new command instance.
|
* Create a new command instance.
|
||||||
|
|
|
@ -3,6 +3,7 @@
|
||||||
namespace App\Console\Commands;
|
namespace App\Console\Commands;
|
||||||
|
|
||||||
use App\Models\Department;
|
use App\Models\Department;
|
||||||
|
use App\Models\Group;
|
||||||
use Illuminate\Console\Command;
|
use Illuminate\Console\Command;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\Ldap;
|
use App\Models\Ldap;
|
||||||
|
@ -57,6 +58,7 @@ class LdapSync extends Command
|
||||||
$ldap_result_country = Setting::getSettings()->ldap_country;
|
$ldap_result_country = Setting::getSettings()->ldap_country;
|
||||||
$ldap_result_dept = Setting::getSettings()->ldap_dept;
|
$ldap_result_dept = Setting::getSettings()->ldap_dept;
|
||||||
$ldap_result_manager = Setting::getSettings()->ldap_manager;
|
$ldap_result_manager = Setting::getSettings()->ldap_manager;
|
||||||
|
$ldap_default_group = Setting::getSettings()->ldap_default_group;
|
||||||
|
|
||||||
try {
|
try {
|
||||||
$ldapconn = Ldap::connectToLdap();
|
$ldapconn = Ldap::connectToLdap();
|
||||||
|
@ -177,6 +179,16 @@ class LdapSync extends Command
|
||||||
|
|
||||||
$manager_cache = [];
|
$manager_cache = [];
|
||||||
|
|
||||||
|
if($ldap_default_group != null) {
|
||||||
|
|
||||||
|
$default = Group::find($ldap_default_group);
|
||||||
|
if (!$default) {
|
||||||
|
$ldap_default_group = null; // un-set the default group if that group doesn't exist
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
for ($i = 0; $i < $results['count']; $i++) {
|
for ($i = 0; $i < $results['count']; $i++) {
|
||||||
$item = [];
|
$item = [];
|
||||||
$item['username'] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : '';
|
$item['username'] = isset($results[$i][$ldap_result_username][0]) ? $results[$i][$ldap_result_username][0] : '';
|
||||||
|
@ -192,6 +204,7 @@ class LdapSync extends Command
|
||||||
$item['department'] = isset($results[$i][$ldap_result_dept][0]) ? $results[$i][$ldap_result_dept][0] : '';
|
$item['department'] = isset($results[$i][$ldap_result_dept][0]) ? $results[$i][$ldap_result_dept][0] : '';
|
||||||
$item['manager'] = isset($results[$i][$ldap_result_manager][0]) ? $results[$i][$ldap_result_manager][0] : '';
|
$item['manager'] = isset($results[$i][$ldap_result_manager][0]) ? $results[$i][$ldap_result_manager][0] : '';
|
||||||
|
|
||||||
|
|
||||||
$department = Department::firstOrCreate([
|
$department = Department::firstOrCreate([
|
||||||
'name' => $item['department'],
|
'name' => $item['department'],
|
||||||
]);
|
]);
|
||||||
|
@ -326,6 +339,10 @@ class LdapSync extends Command
|
||||||
if ($user->save()) {
|
if ($user->save()) {
|
||||||
$item['note'] = $item['createorupdate'];
|
$item['note'] = $item['createorupdate'];
|
||||||
$item['status'] = 'success';
|
$item['status'] = 'success';
|
||||||
|
if ( $item['createorupdate'] === 'created' && $ldap_default_group) {
|
||||||
|
$user->groups()->attach($ldap_default_group);
|
||||||
|
}
|
||||||
|
|
||||||
} else {
|
} else {
|
||||||
foreach ($user->getErrors()->getMessages() as $key => $err) {
|
foreach ($user->getErrors()->getMessages() as $key => $err) {
|
||||||
$errors .= $err[0];
|
$errors .= $err[0];
|
||||||
|
|
|
@ -214,7 +214,7 @@ class RestoreFromBackup extends Command
|
||||||
$env_vars['MYSQL_PWD'] = config('database.connections.mysql.password');
|
$env_vars['MYSQL_PWD'] = config('database.connections.mysql.password');
|
||||||
// TODO notes: we are stealing the dump_binary_path (which *probably* also has your copy of the mysql binary in it. But it might not, so we might need to extend this)
|
// TODO notes: we are stealing the dump_binary_path (which *probably* also has your copy of the mysql binary in it. But it might not, so we might need to extend this)
|
||||||
// we unilaterally prepend a slash to the `mysql` command. This might mean your path could look like /blah/blah/blah//mysql - which should be fine. But maybe in some environments it isn't?
|
// we unilaterally prepend a slash to the `mysql` command. This might mean your path could look like /blah/blah/blah//mysql - which should be fine. But maybe in some environments it isn't?
|
||||||
$mysql_binary = config('database.connections.mysql.dump.dump_binary_path').'/mysql';
|
$mysql_binary = config('database.connections.mysql.dump.dump_binary_path').\DIRECTORY_SEPARATOR.'mysql'.(\DIRECTORY_SEPARATOR == '\\' ? ".exe" : "");
|
||||||
if( ! file_exists($mysql_binary) ) {
|
if( ! file_exists($mysql_binary) ) {
|
||||||
return $this->error("mysql tool at: '$mysql_binary' does not exist, cannot restore. Please edit DB_DUMP_PATH in your .env to point to a directory that contains the mysqldump and mysql binary");
|
return $this->error("mysql tool at: '$mysql_binary' does not exist, cannot restore. Please edit DB_DUMP_PATH in your .env to point to a directory that contains the mysqldump and mysql binary");
|
||||||
}
|
}
|
||||||
|
|
|
@ -39,33 +39,39 @@ class SyncAssetCounters extends Command
|
||||||
public function handle()
|
public function handle()
|
||||||
{
|
{
|
||||||
$start = microtime(true);
|
$start = microtime(true);
|
||||||
$assets = Asset::withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')
|
|
||||||
->withTrashed()->get();
|
|
||||||
|
|
||||||
if ($assets) {
|
// We need the whole count of all assets in order to set up the progress bar
|
||||||
|
$assets_count = Asset::withTrashed()->count();
|
||||||
|
$bar = $this->output->createProgressBar($assets_count);
|
||||||
|
|
||||||
|
$assets = Asset::withCount('checkins as checkins_count', 'checkouts as checkouts_count', 'userRequests as user_requests_count')
|
||||||
|
->withTrashed()->chunk(100, function ($assets) use ($bar) {
|
||||||
|
|
||||||
if ($assets->count() > 0) {
|
if ($assets->count() > 0) {
|
||||||
$bar = $this->output->createProgressBar($assets->count());
|
|
||||||
|
|
||||||
foreach ($assets as $asset) {
|
foreach ($assets as $asset) {
|
||||||
|
|
||||||
$asset->checkin_counter = (int) $asset->checkins_count;
|
$asset->checkin_counter = (int) $asset->checkins_count;
|
||||||
$asset->checkout_counter = (int) $asset->checkouts_count;
|
$asset->checkout_counter = (int) $asset->checkouts_count;
|
||||||
$asset->requests_counter = (int) $asset->user_requests_count;
|
$asset->requests_counter = (int) $asset->user_requests_count;
|
||||||
$asset->unsetEventDispatcher();
|
$asset->unsetEventDispatcher();
|
||||||
$asset->save();
|
$asset->save();
|
||||||
$output['info'][] = 'Asset: '.$asset->id.' has '.$asset->checkin_counter.' checkins, '.$asset->checkout_counter.' checkouts, and '.$asset->requests_counter.' requests';
|
|
||||||
$bar->advance();
|
$bar->advance();
|
||||||
}
|
|
||||||
$bar->finish();
|
|
||||||
|
|
||||||
foreach ($output['info'] as $key => $output_text) {
|
\Log::debug('Asset: '.$asset->id.' has '.$asset->checkin_counter.' checkins, '.$asset->checkout_counter.' checkouts, and '.$asset->requests_counter.' requests');
|
||||||
$this->info($output_text);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
$time_elapsed_secs = microtime(true) - $start;
|
|
||||||
$this->info('Sync executed in '.$time_elapsed_secs.' seconds');
|
|
||||||
} else {
|
} else {
|
||||||
$this->info('No assets to sync');
|
$this->info('No assets to sync');
|
||||||
}
|
}
|
||||||
}
|
});
|
||||||
|
|
||||||
|
|
||||||
|
$bar->finish();
|
||||||
|
$time_elapsed_secs = microtime(true) - $start;
|
||||||
|
$this->info("\nSync of ".$assets_count.' assets executed in '.$time_elapsed_secs.' seconds');
|
||||||
|
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,6 +12,7 @@ use App\Models\Statuslabel;
|
||||||
use Crypt;
|
use Crypt;
|
||||||
use Illuminate\Contracts\Encryption\DecryptException;
|
use Illuminate\Contracts\Encryption\DecryptException;
|
||||||
use Image;
|
use Image;
|
||||||
|
use Carbon\Carbon;
|
||||||
|
|
||||||
class Helper
|
class Helper
|
||||||
{
|
{
|
||||||
|
@ -1125,6 +1126,26 @@ class Helper
|
||||||
|
|
||||||
return $settings;
|
return $settings;
|
||||||
}
|
}
|
||||||
|
public static function AgeFormat($date) {
|
||||||
|
$year = Carbon::parse($date)
|
||||||
|
->diff(now())->y;
|
||||||
|
$month = Carbon::parse($date)
|
||||||
|
->diff(now())->m;
|
||||||
|
$days = Carbon::parse($date)
|
||||||
|
->diff(now())->d;
|
||||||
|
$age='';
|
||||||
|
if ($year) {
|
||||||
|
$age .= $year.'y ';
|
||||||
|
}
|
||||||
|
if ($month) {
|
||||||
|
$age .= $month.'m ';
|
||||||
|
}
|
||||||
|
if ($days) {
|
||||||
|
$age .= $days.'d';
|
||||||
|
}
|
||||||
|
|
||||||
|
return $age;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Conversion between units of measurement
|
* Conversion between units of measurement
|
||||||
|
@ -1164,5 +1185,4 @@ class Helper
|
||||||
default: throw new \InvalidArgumentException('Unit: \''.$unit.'\' is not supported');
|
default: throw new \InvalidArgumentException('Unit: \''.$unit.'\' is not supported');
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
186
app/Http/Controllers/Accessories/AccessoriesFilesController.php
Normal file
186
app/Http/Controllers/Accessories/AccessoriesFilesController.php
Normal file
|
@ -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]));
|
||||||
|
}
|
||||||
|
}
|
|
@ -100,6 +100,7 @@ class AssetsController extends Controller
|
||||||
'checkout_counter',
|
'checkout_counter',
|
||||||
'checkin_counter',
|
'checkin_counter',
|
||||||
'requests_counter',
|
'requests_counter',
|
||||||
|
'byod',
|
||||||
];
|
];
|
||||||
|
|
||||||
$filter = [];
|
$filter = [];
|
||||||
|
@ -120,7 +121,6 @@ class AssetsController extends Controller
|
||||||
|
|
||||||
if ($filter_non_deprecable_assets) {
|
if ($filter_non_deprecable_assets) {
|
||||||
$non_deprecable_models = AssetModel::select('id')->whereNotNull('depreciation_id')->get();
|
$non_deprecable_models = AssetModel::select('id')->whereNotNull('depreciation_id')->get();
|
||||||
|
|
||||||
$assets->InModelList($non_deprecable_models->toArray());
|
$assets->InModelList($non_deprecable_models->toArray());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -141,6 +141,14 @@ class AssetsController extends Controller
|
||||||
$assets->where('assets.status_id', '=', $request->input('status_id'));
|
$assets->where('assets.status_id', '=', $request->input('status_id'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($request->filled('asset_tag')) {
|
||||||
|
$assets->where('assets.asset_tag', '=', $request->input('asset_tag'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->filled('serial')) {
|
||||||
|
$assets->where('assets.serial', '=', $request->input('serial'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($request->input('requestable') == 'true') {
|
if ($request->input('requestable') == 'true') {
|
||||||
$assets->where('assets.requestable', '=', '1');
|
$assets->where('assets.requestable', '=', '1');
|
||||||
}
|
}
|
||||||
|
@ -182,6 +190,10 @@ class AssetsController extends Controller
|
||||||
$assets->ByDepreciationId($request->input('depreciation_id'));
|
$assets->ByDepreciationId($request->input('depreciation_id'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($request->filled('byod')) {
|
||||||
|
$assets->where('assets.byod', '=', $request->input('byod'));
|
||||||
|
}
|
||||||
|
|
||||||
$request->filled('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
|
$request->filled('order_number') ? $assets = $assets->where('assets.order_number', '=', e($request->get('order_number'))) : '';
|
||||||
|
|
||||||
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
// Set the offset to the API call's offset, unless the offset is higher than the actual count of items in which
|
||||||
|
@ -259,6 +271,11 @@ class AssetsController extends Controller
|
||||||
// more sad, horrible workarounds for laravel bugs when doing full text searches
|
// more sad, horrible workarounds for laravel bugs when doing full text searches
|
||||||
$assets->where('assets.assigned_to', '>', '0');
|
$assets->where('assets.assigned_to', '>', '0');
|
||||||
break;
|
break;
|
||||||
|
case 'byod':
|
||||||
|
// This is kind of redundant, since we already check for byod=1 above, but this keeps the
|
||||||
|
// sidebar nav links a little less chaotic
|
||||||
|
$assets->where('assets.byod', '=', '1');
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
|
|
||||||
if ((! $request->filled('status_id')) && ($settings->show_archived_in_list != '1')) {
|
if ((! $request->filled('status_id')) && ($settings->show_archived_in_list != '1')) {
|
||||||
|
@ -357,19 +374,38 @@ class AssetsController extends Controller
|
||||||
/**
|
/**
|
||||||
* Returns JSON with information about an asset (by tag) for detail view.
|
* Returns JSON with information about an asset (by tag) for detail view.
|
||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
|
||||||
* @param string $tag
|
* @param string $tag
|
||||||
* @since [v4.2.1]
|
* @since [v4.2.1]
|
||||||
* @return JsonResponse
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function showByTag(Request $request, $tag)
|
public function showByTag(Request $request, $tag)
|
||||||
{
|
{
|
||||||
if ($asset = Asset::with('assetstatus')->with('assignedTo')->where('asset_tag', $tag)->first()) {
|
$this->authorize('index', Asset::class);
|
||||||
$this->authorize('view', $asset);
|
$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();
|
||||||
}
|
}
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
|
||||||
|
if (($assets = $assets->get()) && ($assets->count()) > 0) {
|
||||||
|
|
||||||
|
// If there is exactly one result and the deleted parameter is not passed, we should pull the first (and only)
|
||||||
|
// asset from the returned collection, since transformAsset() expects an Asset object, NOT a collection
|
||||||
|
if (($assets->count() == 1) && ($request->input('deleted') != 'true')) {
|
||||||
|
return (new AssetsTransformer)->transformAsset($assets->first());
|
||||||
|
|
||||||
|
// If there is more than one result OR if the endpoint is requesting deleted items (even if there is only one
|
||||||
|
// match, return the normal collection transformed.
|
||||||
|
} else {
|
||||||
|
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// If there are 0 results, return the "no such asset" response
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -379,29 +415,25 @@ class AssetsController extends Controller
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @param string $serial
|
* @param string $serial
|
||||||
* @since [v4.2.1]
|
* @since [v4.2.1]
|
||||||
* @return JsonResponse
|
* @return \Illuminate\Http\JsonResponse
|
||||||
*/
|
*/
|
||||||
public function showBySerial(Request $request, $serial)
|
public function showBySerial(Request $request, $serial)
|
||||||
{
|
{
|
||||||
$this->authorize('index', Asset::class);
|
$this->authorize('index', Asset::class);
|
||||||
if ($assets = Asset::with('assetstatus')->with('assignedTo')
|
$assets = Asset::where('serial', $serial)->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::with('assetstatus')->with('assignedTo');
|
// Check if they've passed ?deleted=true
|
||||||
|
if ($request->input('deleted', 'false') == 'true') {
|
||||||
if ($request->input('deleted', 'false') === 'true') {
|
|
||||||
$assets = $assets->withTrashed();
|
$assets = $assets->withTrashed();
|
||||||
}
|
}
|
||||||
|
|
||||||
$assets = $assets->where('serial', $serial)->get();
|
if (($assets = $assets->get()) && ($assets->count()) > 0) {
|
||||||
if ($assets) {
|
|
||||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
return (new AssetsTransformer)->transformAssets($assets, $assets->count());
|
||||||
} else {
|
|
||||||
return response()->json(Helper::formatStandardApiResponse('error', null, 'Asset not found'), 200);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If there are 0 results, return the "no such asset" response
|
||||||
|
return response()->json(Helper::formatStandardApiResponse('error', null, trans('admin/hardware/message.does_not_exist')), 200);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -10,6 +10,7 @@ use App\Models\Category;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
use Illuminate\Support\Facades\Storage;
|
use Illuminate\Support\Facades\Storage;
|
||||||
|
use Illuminate\Support\Facades\Validator;
|
||||||
|
|
||||||
class CategoriesController extends Controller
|
class CategoriesController extends Controller
|
||||||
{
|
{
|
||||||
|
@ -107,7 +108,7 @@ class CategoriesController extends Controller
|
||||||
public function show($id)
|
public function show($id)
|
||||||
{
|
{
|
||||||
$this->authorize('view', Category::class);
|
$this->authorize('view', Category::class);
|
||||||
$category = Category::findOrFail($id);
|
$category = Category::withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count')->findOrFail($id);
|
||||||
return (new CategoriesTransformer)->transformCategory($category);
|
return (new CategoriesTransformer)->transformCategory($category);
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -126,8 +127,14 @@ class CategoriesController extends Controller
|
||||||
{
|
{
|
||||||
$this->authorize('update', Category::class);
|
$this->authorize('update', Category::class);
|
||||||
$category = Category::findOrFail($id);
|
$category = Category::findOrFail($id);
|
||||||
|
|
||||||
|
// Don't allow the user to change the category_type once it's been created
|
||||||
|
if (($request->filled('category_type')) && ($category->category_type != $request->input('category_type'))) {
|
||||||
|
return response()->json(
|
||||||
|
Helper::formatStandardApiResponse('error', null, trans('admin/categories/message.update.cannot_change_category_type'))
|
||||||
|
);
|
||||||
|
}
|
||||||
$category->fill($request->all());
|
$category->fill($request->all());
|
||||||
$category->category_type = strtolower($request->input('category_type'));
|
|
||||||
$category = $request->handleImages($category);
|
$category = $request->handleImages($category);
|
||||||
|
|
||||||
if ($category->save()) {
|
if ($category->save()) {
|
||||||
|
@ -148,7 +155,7 @@ class CategoriesController extends Controller
|
||||||
public function destroy($id)
|
public function destroy($id)
|
||||||
{
|
{
|
||||||
$this->authorize('delete', Category::class);
|
$this->authorize('delete', Category::class);
|
||||||
$category = Category::findOrFail($id);
|
$category = Category::withCount('assets as assets_count', 'accessories as accessories_count', 'consumables as consumables_count', 'components as components_count', 'licenses as licenses_count')->findOrFail($id);
|
||||||
|
|
||||||
if (! $category->isDeletable()) {
|
if (! $category->isDeletable()) {
|
||||||
return response()->json(
|
return response()->json(
|
||||||
|
|
|
@ -228,6 +228,7 @@ class ConsumablesController extends Controller
|
||||||
|
|
||||||
foreach ($consumable->consumableAssignments as $consumable_assignment) {
|
foreach ($consumable->consumableAssignments as $consumable_assignment) {
|
||||||
$rows[] = [
|
$rows[] = [
|
||||||
|
'avatar' => ($consumable_assignment->user) ? e($consumable_assignment->user->present()->gravatar) : '',
|
||||||
'name' => ($consumable_assignment->user) ? $consumable_assignment->user->present()->nameUrl() : 'Deleted User',
|
'name' => ($consumable_assignment->user) ? $consumable_assignment->user->present()->nameUrl() : 'Deleted User',
|
||||||
'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'),
|
'created_at' => Helper::getFormattedDateObject($consumable_assignment->created_at, 'datetime'),
|
||||||
'note' => ($consumable_assignment->note) ? e($consumable_assignment->note) : null,
|
'note' => ($consumable_assignment->note) ? e($consumable_assignment->note) : null,
|
||||||
|
|
|
@ -96,7 +96,7 @@ class CustomFieldsController extends Controller
|
||||||
$data = $request->all();
|
$data = $request->all();
|
||||||
$regex_format = null;
|
$regex_format = null;
|
||||||
|
|
||||||
if (str_contains($data['format'], 'regex:')) {
|
if ((array_key_exists('format', $data)) && (str_contains($data['format'], 'regex:'))) {
|
||||||
$regex_format = $data['format'];
|
$regex_format = $data['format'];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -127,7 +127,7 @@ class ImportController extends Controller
|
||||||
$this->authorize('import');
|
$this->authorize('import');
|
||||||
|
|
||||||
// Run a backup immediately before processing
|
// Run a backup immediately before processing
|
||||||
if ($request->has('run-backup')) {
|
if ($request->get('run-backup')) {
|
||||||
\Log::debug('Backup manually requested via importer');
|
\Log::debug('Backup manually requested via importer');
|
||||||
Artisan::call('backup:run');
|
Artisan::call('backup:run');
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -15,6 +15,7 @@ use App\Models\Asset;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\License;
|
use App\Models\License;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Notifications\CurrentInventory;
|
||||||
use Auth;
|
use Auth;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
|
@ -148,6 +149,14 @@ class UsersController extends Controller
|
||||||
$users = $users->where('remote', '=', $request->input('remote'));
|
$users = $users->where('remote', '=', $request->input('remote'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ($request->filled('two_factor_enrolled')) {
|
||||||
|
$users = $users->where('two_factor_enrolled', '=', $request->input('two_factor_enrolled'));
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($request->filled('two_factor_optin')) {
|
||||||
|
$users = $users->where('two_factor_optin', '=', $request->input('two_factor_optin'));
|
||||||
|
}
|
||||||
|
|
||||||
if ($request->filled('start_date')) {
|
if ($request->filled('start_date')) {
|
||||||
$users = $users->where('users.start_date', '=', $request->input('start_date'));
|
$users = $users->where('users.start_date', '=', $request->input('start_date'));
|
||||||
}
|
}
|
||||||
|
@ -156,7 +165,6 @@ class UsersController extends Controller
|
||||||
$users = $users->where('users.end_date', '=', $request->input('end_date'));
|
$users = $users->where('users.end_date', '=', $request->input('end_date'));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
if ($request->filled('assets_count')) {
|
if ($request->filled('assets_count')) {
|
||||||
$users->has('assets', '=', $request->input('assets_count'));
|
$users->has('assets', '=', $request->input('assets_count'));
|
||||||
}
|
}
|
||||||
|
@ -207,11 +215,39 @@ class UsersController extends Controller
|
||||||
default:
|
default:
|
||||||
$allowed_columns =
|
$allowed_columns =
|
||||||
[
|
[
|
||||||
'last_name', 'first_name', 'email', 'jobtitle', 'username', 'employee_num',
|
'last_name',
|
||||||
'assets', 'accessories', 'consumables', 'licenses', 'groups', 'activated', 'created_at',
|
'first_name',
|
||||||
'two_factor_enrolled', 'two_factor_optin', 'last_login', 'assets_count', 'licenses_count',
|
'email',
|
||||||
'consumables_count', 'accessories_count', 'phone', 'address', 'city', 'state',
|
'jobtitle',
|
||||||
'country', 'zip', 'id', 'ldap_import', 'remote', 'start_date', 'end_date',
|
'username',
|
||||||
|
'employee_num',
|
||||||
|
'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',
|
||||||
|
'two_factor_optin',
|
||||||
|
'two_factor_enrolled',
|
||||||
|
'remote',
|
||||||
|
'start_date',
|
||||||
|
'end_date',
|
||||||
];
|
];
|
||||||
|
|
||||||
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name';
|
$sort = in_array($request->get('sort'), $allowed_columns) ? $request->get('sort') : 'first_name';
|
||||||
|
@ -490,6 +526,26 @@ class UsersController extends Controller
|
||||||
return (new AssetsTransformer)->transformAssets($assets, $assets->count(), $request);
|
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.
|
* Return JSON containing a list of consumables assigned to a user.
|
||||||
|
|
|
@ -62,7 +62,7 @@ class AssetModelsFilesController extends Controller
|
||||||
$model->logUpload($file_name, e($request->get('notes')));
|
$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'));
|
return redirect()->back()->with('error', trans('admin/hardware/message.upload.nofiles'));
|
||||||
|
|
|
@ -147,6 +147,7 @@ class AssetsController extends Controller
|
||||||
$asset->supplier_id = request('supplier_id', null);
|
$asset->supplier_id = request('supplier_id', null);
|
||||||
$asset->requestable = request('requestable', 0);
|
$asset->requestable = request('requestable', 0);
|
||||||
$asset->rtd_location_id = request('rtd_location_id', null);
|
$asset->rtd_location_id = request('rtd_location_id', null);
|
||||||
|
$asset->byod = request('byod', 0);
|
||||||
|
|
||||||
if (! empty($settings->audit_interval)) {
|
if (! empty($settings->audit_interval)) {
|
||||||
$asset->next_audit_date = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
|
$asset->next_audit_date = Carbon::now()->addMonths($settings->audit_interval)->toDateString();
|
||||||
|
@ -319,6 +320,7 @@ class AssetsController extends Controller
|
||||||
// If the box isn't checked, it's not in the request at all.
|
// If the box isn't checked, it's not in the request at all.
|
||||||
$asset->requestable = $request->filled('requestable');
|
$asset->requestable = $request->filled('requestable');
|
||||||
$asset->rtd_location_id = $request->input('rtd_location_id', null);
|
$asset->rtd_location_id = $request->input('rtd_location_id', null);
|
||||||
|
$asset->byod = $request->input('byod', 0);
|
||||||
|
|
||||||
if ($asset->assigned_to == '') {
|
if ($asset->assigned_to == '') {
|
||||||
$asset->location_id = $request->input('rtd_location_id', null);
|
$asset->location_id = $request->input('rtd_location_id', null);
|
||||||
|
|
|
@ -135,9 +135,7 @@ class LoginController extends Controller
|
||||||
} else {
|
} else {
|
||||||
|
|
||||||
// Better logging
|
// Better logging
|
||||||
if (!$saml->isEnabled()) {
|
if (empty($samlData)) {
|
||||||
\Log::debug("SAML page requested, but SAML does not seem to enabled.");
|
|
||||||
} else {
|
|
||||||
\Log::debug("SAML page requested, but samlData seems empty.");
|
\Log::debug("SAML page requested, but samlData seems empty.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -41,6 +41,7 @@ class ResetPasswordController extends Controller
|
||||||
public function __construct()
|
public function __construct()
|
||||||
{
|
{
|
||||||
$this->middleware('guest');
|
$this->middleware('guest');
|
||||||
|
$this->middleware('throttle:10,1');
|
||||||
}
|
}
|
||||||
|
|
||||||
protected function rules()
|
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');
|
\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'));
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
180
app/Http/Controllers/Components/ComponentsFilesController.php
Normal file
180
app/Http/Controllers/Components/ComponentsFilesController.php
Normal file
|
@ -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]));
|
||||||
|
}
|
||||||
|
}
|
180
app/Http/Controllers/Consumables/ConsumablesFilesController.php
Normal file
180
app/Http/Controllers/Consumables/ConsumablesFilesController.php
Normal file
|
@ -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);
|
$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([
|
$field = new CustomField([
|
||||||
"name" => trim($request->get("name")),
|
"name" => trim($request->get("name")),
|
||||||
"element" => $request->get("element"),
|
"element" => $request->get("element"),
|
||||||
"help_text" => $request->get("help_text"),
|
"help_text" => $request->get("help_text"),
|
||||||
"field_values" => $request->get("field_values"),
|
"field_values" => $request->get("field_values"),
|
||||||
"field_encrypted" => $request->get("field_encrypted", 0),
|
"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),
|
"is_unique" => $request->get("is_unique", 0),
|
||||||
|
"display_in_user_view" => $display_in_user_view,
|
||||||
"user_id" => Auth::id()
|
"user_id" => Auth::id()
|
||||||
]);
|
]);
|
||||||
|
|
||||||
|
@ -221,13 +231,24 @@ class CustomFieldsController extends Controller
|
||||||
|
|
||||||
$this->authorize('update', $field);
|
$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->name = trim(e($request->get("name")));
|
||||||
$field->element = e($request->get("element"));
|
$field->element = e($request->get("element"));
|
||||||
$field->field_values = e($request->get("field_values"));
|
$field->field_values = e($request->get("field_values"));
|
||||||
$field->user_id = Auth::id();
|
$field->user_id = Auth::id();
|
||||||
$field->help_text = $request->get("help_text");
|
$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->is_unique = $request->get("is_unique", 0);
|
||||||
|
$field->display_in_user_view = $display_in_user_view;
|
||||||
|
|
||||||
if ($request->get('format') == 'CUSTOM REGEX') {
|
if ($request->get('format') == 'CUSTOM REGEX') {
|
||||||
$field->format = e($request->get('custom_format'));
|
$field->format = e($request->get('custom_format'));
|
||||||
|
|
|
@ -34,7 +34,7 @@ class DashboardController extends Controller
|
||||||
$counts['license'] = \App\Models\License::assetcount();
|
$counts['license'] = \App\Models\License::assetcount();
|
||||||
$counts['consumable'] = \App\Models\Consumable::count();
|
$counts['consumable'] = \App\Models\Consumable::count();
|
||||||
$counts['component'] = \App\Models\Component::count();
|
$counts['component'] = \App\Models\Component::count();
|
||||||
$counts['user'] = \App\Models\User::count();
|
$counts['user'] = \App\Models\Company::scopeCompanyables(Auth::user())->count();
|
||||||
$counts['grand_total'] = $counts['asset'] + $counts['accessory'] + $counts['license'] + $counts['consumable'];
|
$counts['grand_total'] = $counts['asset'] + $counts['accessory'] + $counts['license'] + $counts['consumable'];
|
||||||
|
|
||||||
if ((! file_exists(storage_path().'/oauth-private.key')) || (! file_exists(storage_path().'/oauth-public.key'))) {
|
if ((! file_exists(storage_path().'/oauth-private.key')) || (! file_exists(storage_path().'/oauth-public.key'))) {
|
||||||
|
|
|
@ -763,7 +763,7 @@ class ReportsController extends Controller
|
||||||
if ($request->filled('username')) {
|
if ($request->filled('username')) {
|
||||||
// Only works if we're checked out to a user, not anything else.
|
// Only works if we're checked out to a user, not anything else.
|
||||||
if ($asset->checkedOutToUser()) {
|
if ($asset->checkedOutToUser()) {
|
||||||
$row[] = ($asset->assignedTo) ? $asset->assignedTo->username : '';
|
$row[] = ($asset->assignedto) ? $asset->assignedto->username : '';
|
||||||
} else {
|
} else {
|
||||||
$row[] = ''; // Empty string if unassigned
|
$row[] = ''; // Empty string if unassigned
|
||||||
}
|
}
|
||||||
|
@ -772,7 +772,7 @@ class ReportsController extends Controller
|
||||||
if ($request->filled('employee_num')) {
|
if ($request->filled('employee_num')) {
|
||||||
// Only works if we're checked out to a user, not anything else.
|
// Only works if we're checked out to a user, not anything else.
|
||||||
if ($asset->checkedOutToUser()) {
|
if ($asset->checkedOutToUser()) {
|
||||||
$row[] = ($asset->assignedTo) ? $asset->assignedTo->employee_num : '';
|
$row[] = ($asset->assignedto) ? $asset->assignedto->employee_num : '';
|
||||||
} else {
|
} else {
|
||||||
$row[] = ''; // Empty string if unassigned
|
$row[] = ''; // Empty string if unassigned
|
||||||
}
|
}
|
||||||
|
@ -780,7 +780,7 @@ class ReportsController extends Controller
|
||||||
|
|
||||||
if ($request->filled('manager')) {
|
if ($request->filled('manager')) {
|
||||||
if ($asset->checkedOutToUser()) {
|
if ($asset->checkedOutToUser()) {
|
||||||
$row[] = (($asset->assignedTo) && ($asset->assignedTo->manager)) ? $asset->assignedTo->manager->present()->fullName : '';
|
$row[] = (($asset->assignedto) && ($asset->assignedto->manager)) ? $asset->assignedto->manager->present()->fullName : '';
|
||||||
} else {
|
} else {
|
||||||
$row[] = ''; // Empty string if unassigned
|
$row[] = ''; // Empty string if unassigned
|
||||||
}
|
}
|
||||||
|
@ -788,7 +788,7 @@ class ReportsController extends Controller
|
||||||
|
|
||||||
if ($request->filled('department')) {
|
if ($request->filled('department')) {
|
||||||
if ($asset->checkedOutToUser()) {
|
if ($asset->checkedOutToUser()) {
|
||||||
$row[] = (($asset->assignedTo) && ($asset->assignedTo->department)) ? $asset->assignedTo->department->name : '';
|
$row[] = (($asset->assignedto) && ($asset->assignedto->department)) ? $asset->assignedto->department->name : '';
|
||||||
} else {
|
} else {
|
||||||
$row[] = ''; // Empty string if unassigned
|
$row[] = ''; // Empty string if unassigned
|
||||||
}
|
}
|
||||||
|
@ -796,7 +796,7 @@ class ReportsController extends Controller
|
||||||
|
|
||||||
if ($request->filled('title')) {
|
if ($request->filled('title')) {
|
||||||
if ($asset->checkedOutToUser()) {
|
if ($asset->checkedOutToUser()) {
|
||||||
$row[] = ($asset->assignedTo) ? $asset->assignedTo->jobtitle : '';
|
$row[] = ($asset->assignedto) ? $asset->assignedto->jobtitle : '';
|
||||||
} else {
|
} else {
|
||||||
$row[] = ''; // Empty string if unassigned
|
$row[] = ''; // Empty string if unassigned
|
||||||
}
|
}
|
||||||
|
@ -1110,6 +1110,9 @@ class ReportsController extends Controller
|
||||||
$rows[] = implode(',', $header);
|
$rows[] = implode(',', $header);
|
||||||
|
|
||||||
foreach ($assetsForReport as $item) {
|
foreach ($assetsForReport as $item) {
|
||||||
|
|
||||||
|
if ($item['assetItem'] != null){
|
||||||
|
|
||||||
$row = [ ];
|
$row = [ ];
|
||||||
$row[] = str_replace(',', '', e($item['assetItem']->model->category->name));
|
$row[] = str_replace(',', '', e($item['assetItem']->model->category->name));
|
||||||
$row[] = str_replace(',', '', e($item['assetItem']->model->name));
|
$row[] = str_replace(',', '', e($item['assetItem']->model->name));
|
||||||
|
@ -1117,6 +1120,9 @@ class ReportsController extends Controller
|
||||||
$row[] = str_replace(',', '', e($item['assetItem']->asset_tag));
|
$row[] = str_replace(',', '', e($item['assetItem']->asset_tag));
|
||||||
$row[] = str_replace(',', '', e(($item['acceptance']->assignedTo) ? $item['acceptance']->assignedTo->present()->name() : trans('admin/reports/general.deleted_user')));
|
$row[] = str_replace(',', '', e(($item['acceptance']->assignedTo) ? $item['acceptance']->assignedTo->present()->name() : trans('admin/reports/general.deleted_user')));
|
||||||
$rows[] = implode(',', $row);
|
$rows[] = implode(',', $row);
|
||||||
|
} else {
|
||||||
|
// Log the error maybe?
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// spit out a csv
|
// spit out a csv
|
||||||
|
|
|
@ -7,6 +7,7 @@ use App\Helpers\StorageHelper;
|
||||||
use App\Http\Requests\ImageUploadRequest;
|
use App\Http\Requests\ImageUploadRequest;
|
||||||
use App\Http\Requests\SettingsSamlRequest;
|
use App\Http\Requests\SettingsSamlRequest;
|
||||||
use App\Http\Requests\SetupUserRequest;
|
use App\Http\Requests\SetupUserRequest;
|
||||||
|
use App\Models\Group;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\Asset;
|
use App\Models\Asset;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
@ -919,6 +920,8 @@ class SettingsController extends Controller
|
||||||
public function getLdapSettings()
|
public function getLdapSettings()
|
||||||
{
|
{
|
||||||
$setting = Setting::getSettings();
|
$setting = Setting::getSettings();
|
||||||
|
$groups = Group::pluck('name', 'id');
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* This validator is only temporary (famous last words.) - @snipe
|
* This validator is only temporary (famous last words.) - @snipe
|
||||||
|
@ -937,7 +940,7 @@ class SettingsController extends Controller
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
return view('settings.ldap', compact('setting'))->withErrors($validator);
|
return view('settings.ldap', compact('setting', 'groups'))->withErrors($validator);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -964,6 +967,7 @@ class SettingsController extends Controller
|
||||||
$setting->ldap_pword = Crypt::encrypt($request->input('ldap_pword'));
|
$setting->ldap_pword = Crypt::encrypt($request->input('ldap_pword'));
|
||||||
}
|
}
|
||||||
$setting->ldap_basedn = $request->input('ldap_basedn');
|
$setting->ldap_basedn = $request->input('ldap_basedn');
|
||||||
|
$setting->ldap_default_group = $request->input('ldap_default_group');
|
||||||
$setting->ldap_filter = $request->input('ldap_filter');
|
$setting->ldap_filter = $request->input('ldap_filter');
|
||||||
$setting->ldap_username_field = $request->input('ldap_username_field');
|
$setting->ldap_username_field = $request->input('ldap_username_field');
|
||||||
$setting->ldap_lname_field = $request->input('ldap_lname_field');
|
$setting->ldap_lname_field = $request->input('ldap_lname_field');
|
||||||
|
|
|
@ -8,6 +8,7 @@ use App\Models\AssetModel;
|
||||||
use App\Models\Company;
|
use App\Models\Company;
|
||||||
use App\Models\Setting;
|
use App\Models\Setting;
|
||||||
use App\Models\User;
|
use App\Models\User;
|
||||||
|
use App\Models\CustomField;
|
||||||
use App\Notifications\RequestAssetCancelation;
|
use App\Notifications\RequestAssetCancelation;
|
||||||
use App\Notifications\RequestAssetNotification;
|
use App\Notifications\RequestAssetNotification;
|
||||||
use Illuminate\Http\Request;
|
use Illuminate\Http\Request;
|
||||||
|
@ -29,23 +30,41 @@ class ViewAssetsController extends Controller
|
||||||
public function getIndex()
|
public function getIndex()
|
||||||
{
|
{
|
||||||
$user = User::with(
|
$user = User::with(
|
||||||
|
'assets',
|
||||||
'assets.model',
|
'assets.model',
|
||||||
|
'assets.model.fieldset.fields',
|
||||||
'consumables',
|
'consumables',
|
||||||
'accessories',
|
'accessories',
|
||||||
'licenses',
|
'licenses',
|
||||||
'userloc',
|
)->find(Auth::user()->id);
|
||||||
'userlog'
|
|
||||||
)->withTrashed()->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)) {
|
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());
|
->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
|
// Redirect to the user management page
|
||||||
return redirect()->route('users.index')
|
return redirect()->route('users.index')
|
||||||
->with('error', trans('admin/users/message.user_not_found', $user->id));
|
->with('error', trans('admin/users/message.user_not_found', $user->id));
|
||||||
|
|
|
@ -52,6 +52,13 @@ class AssetCountForSidebar
|
||||||
\Log::debug($e);
|
\Log::debug($e);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
try {
|
||||||
|
$total_byod_sidebar = Asset::where('byod', '=', '1')->count();
|
||||||
|
view()->share('total_byod_sidebar', $total_byod_sidebar);
|
||||||
|
} catch (\Exception $e) {
|
||||||
|
\Log::debug($e);
|
||||||
|
}
|
||||||
|
|
||||||
return $next($request);
|
return $next($request);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -146,7 +146,7 @@ class ImageUploadRequest extends Request
|
||||||
}
|
}
|
||||||
|
|
||||||
// Remove Current image if exists
|
// Remove Current image if exists
|
||||||
if (Storage::disk('public')->exists($path.'/'.$item->{$use_db_field})) {
|
if (($item->{$use_db_field}!='') && (Storage::disk('public')->exists($path.'/'.$item->{$use_db_field}))) {
|
||||||
\Log::debug('A file already exists that we are replacing - we should delete the old one.');
|
\Log::debug('A file already exists that we are replacing - we should delete the old one.');
|
||||||
try {
|
try {
|
||||||
Storage::disk('public')->delete($path.'/'.$item->{$use_db_field});
|
Storage::disk('public')->delete($path.'/'.$item->{$use_db_field});
|
||||||
|
|
|
@ -49,7 +49,7 @@ class ItemImportRequest extends FormRequest
|
||||||
$errorMessage = null;
|
$errorMessage = null;
|
||||||
|
|
||||||
if (is_null($fieldValue)) {
|
if (is_null($fieldValue)) {
|
||||||
$errorMessage = trans('validation.import_field_empty');
|
$errorMessage = trans('validation.import_field_empty', ['fieldname' => $field]);
|
||||||
$this->errorCallback($import, $field, $errorMessage);
|
$this->errorCallback($import, $field, $errorMessage);
|
||||||
|
|
||||||
return $this->errors;
|
return $this->errors;
|
||||||
|
|
|
@ -85,6 +85,7 @@ class ActionlogsTransformer
|
||||||
'id' => (int) $actionlog->item->id,
|
'id' => (int) $actionlog->item->id,
|
||||||
'name' => ($actionlog->itemType()=='user') ? e($actionlog->item->getFullNameAttribute()) : e($actionlog->item->getDisplayNameAttribute()),
|
'name' => ($actionlog->itemType()=='user') ? e($actionlog->item->getFullNameAttribute()) : e($actionlog->item->getDisplayNameAttribute()),
|
||||||
'type' => e($actionlog->itemType()),
|
'type' => e($actionlog->itemType()),
|
||||||
|
'serial' =>e($actionlog->item->serial) ? e($actionlog->item->serial) : null
|
||||||
] : null,
|
] : null,
|
||||||
'location' => ($actionlog->location) ? [
|
'location' => ($actionlog->location) ? [
|
||||||
'id' => (int) $actionlog->location->id,
|
'id' => (int) $actionlog->location->id,
|
||||||
|
|
|
@ -22,6 +22,22 @@ class AssetModelsTransformer
|
||||||
|
|
||||||
public function transformAssetModel(AssetModel $assetmodel)
|
public function transformAssetModel(AssetModel $assetmodel)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
$default_field_values = array();
|
||||||
|
|
||||||
|
// Reach into the custom fields and models_custom_fields pivot table to find the default values for this model
|
||||||
|
if ($assetmodel->fieldset) {
|
||||||
|
foreach($assetmodel->fieldset->fields AS $field) {
|
||||||
|
$default_field_values[] = [
|
||||||
|
'name' => e($field->name),
|
||||||
|
'db_column_name' => e($field->db_column_name()),
|
||||||
|
'default_value' => ($field->defaultValue($assetmodel->id)) ? e($field->defaultValue($assetmodel->id)) : null,
|
||||||
|
'format' => e($field->format),
|
||||||
|
'required' => ($field->pivot->required == '1') ? true : false,
|
||||||
|
];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
$array = [
|
$array = [
|
||||||
'id' => (int) $assetmodel->id,
|
'id' => (int) $assetmodel->id,
|
||||||
'name' => e($assetmodel->name),
|
'name' => e($assetmodel->name),
|
||||||
|
@ -44,6 +60,7 @@ class AssetModelsTransformer
|
||||||
'id' => (int) $assetmodel->fieldset->id,
|
'id' => (int) $assetmodel->fieldset->id,
|
||||||
'name'=> e($assetmodel->fieldset->name),
|
'name'=> e($assetmodel->fieldset->name),
|
||||||
] : null,
|
] : null,
|
||||||
|
'default_fieldset_values' => $default_field_values,
|
||||||
'eol' => ($assetmodel->eol > 0) ? $assetmodel->eol.' months' : 'None',
|
'eol' => ($assetmodel->eol > 0) ? $assetmodel->eol.' months' : 'None',
|
||||||
'requestable' => ($assetmodel->requestable == '1') ? true : false,
|
'requestable' => ($assetmodel->requestable == '1') ? true : false,
|
||||||
'notes' => e($assetmodel->notes),
|
'notes' => e($assetmodel->notes),
|
||||||
|
|
|
@ -8,6 +8,7 @@ use App\Models\Setting;
|
||||||
use Gate;
|
use Gate;
|
||||||
use Illuminate\Database\Eloquent\Collection;
|
use Illuminate\Database\Eloquent\Collection;
|
||||||
|
|
||||||
|
|
||||||
class AssetsTransformer
|
class AssetsTransformer
|
||||||
{
|
{
|
||||||
public function transformAssets(Collection $assets, $total)
|
public function transformAssets(Collection $assets, $total)
|
||||||
|
@ -34,6 +35,8 @@ class AssetsTransformer
|
||||||
'id' => (int) $asset->model->id,
|
'id' => (int) $asset->model->id,
|
||||||
'name'=> e($asset->model->name),
|
'name'=> e($asset->model->name),
|
||||||
] : null,
|
] : null,
|
||||||
|
'byod' => ($asset->byod ? true : false),
|
||||||
|
|
||||||
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
|
'model_number' => (($asset->model) && ($asset->model->model_number)) ? e($asset->model->model_number) : null,
|
||||||
'eol' => ($asset->purchase_date != '') ? Helper::getFormattedDateObject($asset->present()->eol_date(), 'date') : null,
|
'eol' => ($asset->purchase_date != '') ? Helper::getFormattedDateObject($asset->present()->eol_date(), 'date') : null,
|
||||||
'status_label' => ($asset->assetstatus) ? [
|
'status_label' => ($asset->assetstatus) ? [
|
||||||
|
@ -80,6 +83,7 @@ class AssetsTransformer
|
||||||
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date, 'date'),
|
'next_audit_date' => Helper::getFormattedDateObject($asset->next_audit_date, 'date'),
|
||||||
'deleted_at' => Helper::getFormattedDateObject($asset->deleted_at, 'datetime'),
|
'deleted_at' => Helper::getFormattedDateObject($asset->deleted_at, 'datetime'),
|
||||||
'purchase_date' => Helper::getFormattedDateObject($asset->purchase_date, 'date'),
|
'purchase_date' => Helper::getFormattedDateObject($asset->purchase_date, 'date'),
|
||||||
|
'age' => $asset->purchase_date ? Helper::AgeFormat($asset->purchase_date) : '',
|
||||||
'last_checkout' => Helper::getFormattedDateObject($asset->last_checkout, 'datetime'),
|
'last_checkout' => Helper::getFormattedDateObject($asset->last_checkout, 'datetime'),
|
||||||
'expected_checkin' => Helper::getFormattedDateObject($asset->expected_checkin, 'date'),
|
'expected_checkin' => Helper::getFormattedDateObject($asset->expected_checkin, 'date'),
|
||||||
'purchase_cost' => Helper::formatCurrencyOutput($asset->purchase_cost),
|
'purchase_cost' => Helper::formatCurrencyOutput($asset->purchase_cost),
|
||||||
|
@ -131,7 +135,7 @@ class AssetsTransformer
|
||||||
$array['custom_fields'] = $fields_array;
|
$array['custom_fields'] = $fields_array;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
$array['custom_fields'] = [];
|
$array['custom_fields'] = new \stdClass; // HACK to force generation of empty object instead of empty list
|
||||||
}
|
}
|
||||||
|
|
||||||
$permissions_array['available_actions'] = [
|
$permissions_array['available_actions'] = [
|
||||||
|
@ -185,6 +189,7 @@ class AssetsTransformer
|
||||||
'name' => e($asset->assigned->getFullNameAttribute()),
|
'name' => e($asset->assigned->getFullNameAttribute()),
|
||||||
'first_name'=> e($asset->assigned->first_name),
|
'first_name'=> e($asset->assigned->first_name),
|
||||||
'last_name'=> ($asset->assigned->last_name) ? e($asset->assigned->last_name) : null,
|
'last_name'=> ($asset->assigned->last_name) ? e($asset->assigned->last_name) : null,
|
||||||
|
'email'=> ($asset->assigned->email) ? e($asset->assigned->email) : null,
|
||||||
'employee_number' => ($asset->assigned->employee_num) ? e($asset->assigned->employee_num) : null,
|
'employee_number' => ($asset->assigned->employee_num) ? e($asset->assigned->employee_num) : null,
|
||||||
'type' => 'user',
|
'type' => 'user',
|
||||||
] : null;
|
] : null;
|
||||||
|
|
|
@ -22,6 +22,26 @@ class CategoriesTransformer
|
||||||
|
|
||||||
public function transformCategory(Category $category = null)
|
public function transformCategory(Category $category = null)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// We only ever use item_count for categories in this transformer, so it makes sense to keep it
|
||||||
|
// simple and do this switch here.
|
||||||
|
switch ($category->category_type) {
|
||||||
|
case 'asset':
|
||||||
|
$category->item_count = $category->assets_count;
|
||||||
|
break;
|
||||||
|
case 'accessory':
|
||||||
|
$category->item_count = $category->accessories_count;
|
||||||
|
break;
|
||||||
|
case 'consumable':
|
||||||
|
$category->item_count = $category->consumables_count;
|
||||||
|
break;
|
||||||
|
case 'component':
|
||||||
|
$category->item_count = $category->components_count;
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
$category->item_count = 0;
|
||||||
|
}
|
||||||
|
|
||||||
if ($category) {
|
if ($category) {
|
||||||
$array = [
|
$array = [
|
||||||
'id' => (int) $category->id,
|
'id' => (int) $category->id,
|
||||||
|
@ -33,7 +53,7 @@ class CategoriesTransformer
|
||||||
'eula' => ($category->getEula()),
|
'eula' => ($category->getEula()),
|
||||||
'checkin_email' => ($category->checkin_email == '1'),
|
'checkin_email' => ($category->checkin_email == '1'),
|
||||||
'require_acceptance' => ($category->require_acceptance == '1'),
|
'require_acceptance' => ($category->require_acceptance == '1'),
|
||||||
'item_count' => (int) $category->itemCount(),
|
'item_count' => (int) $category->item_count,
|
||||||
'assets_count' => (int) $category->assets_count,
|
'assets_count' => (int) $category->assets_count,
|
||||||
'accessories_count' => (int) $category->accessories_count,
|
'accessories_count' => (int) $category->accessories_count,
|
||||||
'consumables_count' => (int) $category->consumables_count,
|
'consumables_count' => (int) $category->consumables_count,
|
||||||
|
|
|
@ -47,6 +47,7 @@ class CustomFieldsTransformer
|
||||||
'field_values_array' => ($field->field_values) ? explode("\r\n", e($field->field_values)) : null,
|
'field_values_array' => ($field->field_values) ? explode("\r\n", e($field->field_values)) : null,
|
||||||
'type' => e($field->element),
|
'type' => e($field->element),
|
||||||
'required' => (($field->pivot) && ($field->pivot->required=='1')) ? true : false,
|
'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'),
|
'created_at' => Helper::getFormattedDateObject($field->created_at, 'datetime'),
|
||||||
'updated_at' => Helper::getFormattedDateObject($field->updated_at, 'datetime'),
|
'updated_at' => Helper::getFormattedDateObject($field->updated_at, 'datetime'),
|
||||||
];
|
];
|
||||||
|
|
|
@ -56,8 +56,8 @@ class UsersTransformer
|
||||||
'permissions' => $user->decodePermissions(),
|
'permissions' => $user->decodePermissions(),
|
||||||
'activated' => ($user->activated == '1') ? true : false,
|
'activated' => ($user->activated == '1') ? true : false,
|
||||||
'ldap_import' => ($user->ldap_import == '1') ? true : false,
|
'ldap_import' => ($user->ldap_import == '1') ? true : false,
|
||||||
'two_factor_activated' => ($user->two_factor_active()) ? true : false,
|
|
||||||
'two_factor_enrolled' => ($user->two_factor_active_and_enrolled()) ? true : false,
|
'two_factor_enrolled' => ($user->two_factor_active_and_enrolled()) ? true : false,
|
||||||
|
'two_factor_optin' => ($user->two_factor_active()) ? true : false,
|
||||||
'assets_count' => (int) $user->assets_count,
|
'assets_count' => (int) $user->assets_count,
|
||||||
'licenses_count' => (int) $user->licenses_count,
|
'licenses_count' => (int) $user->licenses_count,
|
||||||
'accessories_count' => (int) $user->accessories_count,
|
'accessories_count' => (int) $user->accessories_count,
|
||||||
|
|
|
@ -77,6 +77,7 @@ abstract class Importer
|
||||||
'manager_first_name' => 'manager first name',
|
'manager_first_name' => 'manager first name',
|
||||||
'manager_last_name' => 'manager last name',
|
'manager_last_name' => 'manager last name',
|
||||||
'min_amt' => 'minimum quantity',
|
'min_amt' => 'minimum quantity',
|
||||||
|
'remote' => 'remote',
|
||||||
];
|
];
|
||||||
/**
|
/**
|
||||||
* Map of item fields->csv names
|
* Map of item fields->csv names
|
||||||
|
@ -288,6 +289,7 @@ abstract class Importer
|
||||||
'department_id' => '',
|
'department_id' => '',
|
||||||
'username' => $this->findCsvMatch($row, 'username'),
|
'username' => $this->findCsvMatch($row, 'username'),
|
||||||
'activated' => $this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')),
|
'activated' => $this->fetchHumanBoolean($this->findCsvMatch($row, 'activated')),
|
||||||
|
'remote' => $this->fetchHumanBoolean(($this->findCsvMatch($row, 'remote'))),
|
||||||
];
|
];
|
||||||
|
|
||||||
// Maybe we're lucky and the user already exists.
|
// Maybe we're lucky and the user already exists.
|
||||||
|
|
|
@ -57,6 +57,7 @@ class UserImporter extends ItemImporter
|
||||||
$this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num');
|
$this->item['employee_num'] = $this->findCsvMatch($row, 'employee_num');
|
||||||
$this->item['department_id'] = $this->createOrFetchDepartment($this->findCsvMatch($row, 'department'));
|
$this->item['department_id'] = $this->createOrFetchDepartment($this->findCsvMatch($row, 'department'));
|
||||||
$this->item['manager_id'] = $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name'));
|
$this->item['manager_id'] = $this->fetchManager($this->findCsvMatch($row, 'manager_first_name'), $this->findCsvMatch($row, 'manager_last_name'));
|
||||||
|
$this->item['remote'] =($this->fetchHumanBoolean($this->findCsvMatch($row, 'remote')) ==1 ) ? '1' : 0;
|
||||||
|
|
||||||
$user_department = $this->findCsvMatch($row, 'department');
|
$user_department = $this->findCsvMatch($row, 'department');
|
||||||
if ($this->shouldUpdateField($user_department)) {
|
if ($this->shouldUpdateField($user_department)) {
|
||||||
|
|
|
@ -101,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
|
* Establishes the accessory -> supplier relationship
|
||||||
*
|
*
|
||||||
|
|
|
@ -95,6 +95,7 @@ class Asset extends Depreciable
|
||||||
'location_id' => 'integer',
|
'location_id' => 'integer',
|
||||||
'rtd_company_id' => 'integer',
|
'rtd_company_id' => 'integer',
|
||||||
'supplier_id' => 'integer',
|
'supplier_id' => 'integer',
|
||||||
|
'byod' => 'boolean',
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
|
@ -106,7 +107,6 @@ class Asset extends Depreciable
|
||||||
'physical' => 'numeric|max:1|nullable',
|
'physical' => 'numeric|max:1|nullable',
|
||||||
'checkout_date' => 'date|max:10|min:10|nullable',
|
'checkout_date' => 'date|max:10|min:10|nullable',
|
||||||
'checkin_date' => 'date|max:10|min:10|nullable',
|
'checkin_date' => 'date|max:10|min:10|nullable',
|
||||||
'supplier_id' => 'exists:suppliers,id|numeric|nullable',
|
|
||||||
'location_id' => 'exists:locations,id|nullable',
|
'location_id' => 'exists:locations,id|nullable',
|
||||||
'rtd_location_id' => 'exists:locations,id|nullable',
|
'rtd_location_id' => 'exists:locations,id|nullable',
|
||||||
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
|
'asset_tag' => 'required|min:1|max:255|unique_undeleted',
|
||||||
|
@ -144,6 +144,7 @@ class Asset extends Depreciable
|
||||||
'requestable',
|
'requestable',
|
||||||
'last_checkout',
|
'last_checkout',
|
||||||
'expected_checkin',
|
'expected_checkin',
|
||||||
|
'byod',
|
||||||
];
|
];
|
||||||
|
|
||||||
use Searchable;
|
use Searchable;
|
||||||
|
@ -315,14 +316,10 @@ class Asset extends Depreciable
|
||||||
}
|
}
|
||||||
|
|
||||||
$this->last_checkout = $checkout_at;
|
$this->last_checkout = $checkout_at;
|
||||||
|
$this->name = $name;
|
||||||
|
|
||||||
$this->assignedTo()->associate($target);
|
$this->assignedTo()->associate($target);
|
||||||
|
|
||||||
|
|
||||||
if ($name != null) {
|
|
||||||
$this->name = $name;
|
|
||||||
}
|
|
||||||
|
|
||||||
if ($location != null) {
|
if ($location != null) {
|
||||||
$this->location_id = $location;
|
$this->location_id = $location;
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -10,6 +10,7 @@ use Illuminate\Database\Eloquent\SoftDeletes;
|
||||||
use Illuminate\Support\Facades\Gate;
|
use Illuminate\Support\Facades\Gate;
|
||||||
use Watson\Validating\ValidatingTrait;
|
use Watson\Validating\ValidatingTrait;
|
||||||
use App\Helpers\Helper;
|
use App\Helpers\Helper;
|
||||||
|
use Illuminate\Support\Str;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Model for Categories. Categories are a higher-level group
|
* Model for Categories. Categories are a higher-level group
|
||||||
|
@ -97,6 +98,7 @@ class Category extends SnipeModel
|
||||||
*/
|
*/
|
||||||
public function isDeletable()
|
public function isDeletable()
|
||||||
{
|
{
|
||||||
|
|
||||||
return Gate::allows('delete', $this)
|
return Gate::allows('delete', $this)
|
||||||
&& ($this->itemCount() == 0);
|
&& ($this->itemCount() == 0);
|
||||||
}
|
}
|
||||||
|
@ -150,7 +152,10 @@ class Category extends SnipeModel
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the number of items in the category
|
* Get the number of items in the category. This should NEVER be used in
|
||||||
|
* a collection of categories, as you'll end up with an n+1 query problem.
|
||||||
|
*
|
||||||
|
* It should only be used in a single category context.
|
||||||
*
|
*
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
* @since [v2.0]
|
* @since [v2.0]
|
||||||
|
@ -158,6 +163,11 @@ class Category extends SnipeModel
|
||||||
*/
|
*/
|
||||||
public function itemCount()
|
public function itemCount()
|
||||||
{
|
{
|
||||||
|
|
||||||
|
if (isset($this->{Str::plural($this->category_type).'_count'})) {
|
||||||
|
return $this->{Str::plural($this->category_type).'_count'};
|
||||||
|
}
|
||||||
|
|
||||||
switch ($this->category_type) {
|
switch ($this->category_type) {
|
||||||
case 'asset':
|
case 'asset':
|
||||||
return $this->assets()->count();
|
return $this->assets()->count();
|
||||||
|
@ -169,9 +179,10 @@ class Category extends SnipeModel
|
||||||
return $this->consumables()->count();
|
return $this->consumables()->count();
|
||||||
case 'license':
|
case 'license':
|
||||||
return $this->licenses()->count();
|
return $this->licenses()->count();
|
||||||
|
default:
|
||||||
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
return '0';
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -21,7 +21,7 @@ class CheckoutAcceptance extends Model
|
||||||
{
|
{
|
||||||
// At this point the endpoint is the same for everything.
|
// At this point the endpoint is the same for everything.
|
||||||
// In the future this may want to be adapted for individual notifications.
|
// In the future this may want to be adapted for individual notifications.
|
||||||
return config('mail.reply_to.address');
|
return (config('mail.reply_to.address')) ? config('mail.reply_to.address') : '' ;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -73,6 +73,10 @@ final class Company extends SnipeModel
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Scoping table queries, determining if a logged in user is part of a company, and only allows
|
||||||
|
* that user to see items associated with that company
|
||||||
|
*/
|
||||||
private static function scopeCompanyablesDirectly($query, $column = 'company_id', $table_name = null)
|
private static function scopeCompanyablesDirectly($query, $column = 'company_id', $table_name = null)
|
||||||
{
|
{
|
||||||
if (Auth::user()) {
|
if (Auth::user()) {
|
||||||
|
@ -127,6 +131,11 @@ final class Company extends SnipeModel
|
||||||
return false;
|
return false;
|
||||||
} elseif (! static::isFullMultipleCompanySupportEnabled()) {
|
} elseif (! static::isFullMultipleCompanySupportEnabled()) {
|
||||||
return true;
|
return true;
|
||||||
|
} elseif (!$companyable instanceof Company && !\Schema::hasColumn($companyable->getModel()->getTable(), 'company_id')) {
|
||||||
|
// This is primary for the gate:allows-check in location->isDeletable()
|
||||||
|
// Locations don't have a company_id so without this it isn't possible to delete locations with FullMultipleCompanySupport enabled
|
||||||
|
// because this function is called by SnipePermissionsPolicy->before()
|
||||||
|
return true;
|
||||||
} else {
|
} else {
|
||||||
if (Auth::user()) {
|
if (Auth::user()) {
|
||||||
$current_user_company_id = Auth::user()->company_id;
|
$current_user_company_id = Auth::user()->company_id;
|
||||||
|
|
|
@ -88,6 +88,24 @@ class Component extends SnipeModel
|
||||||
'location' => ['name'],
|
'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
|
* Establishes the component -> location relationship
|
||||||
*
|
*
|
||||||
|
|
|
@ -96,6 +96,24 @@ class Consumable extends SnipeModel
|
||||||
'manufacturer' => ['name'],
|
'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
|
* Sets the attribute of whether or not the consumable is requestable
|
||||||
*
|
*
|
||||||
|
|
|
@ -48,7 +48,11 @@ class CustomField extends Model
|
||||||
*
|
*
|
||||||
* @var array
|
* @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.
|
* The attributes that are mass assignable.
|
||||||
|
@ -64,6 +68,7 @@ class CustomField extends Model
|
||||||
'help_text',
|
'help_text',
|
||||||
'show_in_email',
|
'show_in_email',
|
||||||
'is_unique',
|
'is_unique',
|
||||||
|
'display_in_user_view',
|
||||||
];
|
];
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -356,15 +361,9 @@ class CustomField extends Model
|
||||||
public function validationRules($regex_format = null)
|
public function validationRules($regex_format = null)
|
||||||
{
|
{
|
||||||
return [
|
return [
|
||||||
'name' => 'required|unique:custom_fields',
|
|
||||||
'element' => [
|
|
||||||
'required',
|
|
||||||
Rule::in(['text', 'listbox', 'textarea', 'checkbox', 'radio']),
|
|
||||||
],
|
|
||||||
'format' => [
|
'format' => [
|
||||||
Rule::in(array_merge(array_keys(self::PREDEFINED_FORMATS), self::PREDEFINED_FORMATS, [$regex_format])),
|
Rule::in(array_merge(array_keys(self::PREDEFINED_FORMATS), self::PREDEFINED_FORMATS, [$regex_format])),
|
||||||
],
|
]
|
||||||
'field_encrypted' => 'nullable|boolean',
|
|
||||||
];
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -29,7 +29,7 @@ class Department extends SnipeModel
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $rules = [
|
protected $rules = [
|
||||||
'name' => 'required|max:255',
|
'name' => 'required|max:255|is_unique_department',
|
||||||
'location_id' => 'numeric|nullable',
|
'location_id' => 'numeric|nullable',
|
||||||
'company_id' => 'numeric|nullable',
|
'company_id' => 'numeric|nullable',
|
||||||
'manager_id' => 'numeric|nullable',
|
'manager_id' => 'numeric|nullable',
|
||||||
|
|
|
@ -123,12 +123,20 @@ class License extends Depreciable
|
||||||
static::created(function ($license) {
|
static::created(function ($license) {
|
||||||
$newSeatCount = $license->getAttributes()['seats'];
|
$newSeatCount = $license->getAttributes()['seats'];
|
||||||
|
|
||||||
return static::adjustSeatCount($license, $oldSeatCount = 0, $newSeatCount);
|
return static::adjustSeatCount($license, 0, $newSeatCount);
|
||||||
});
|
});
|
||||||
// However, we listen for updating to be able to prevent the edit if we cannot delete enough seats.
|
// However, we listen for updating to be able to prevent the edit if we cannot delete enough seats.
|
||||||
static::updating(function ($license) {
|
static::updating(function ($license) {
|
||||||
$newSeatCount = $license->getAttributes()['seats'];
|
$newSeatCount = $license->getAttributes()['seats'];
|
||||||
$oldSeatCount = isset($license->getOriginal()['seats']) ? $license->getOriginal()['seats'] : 0;
|
//$oldSeatCount = isset($license->getOriginal()['seats']) ? $license->getOriginal()['seats'] : 0;
|
||||||
|
/*
|
||||||
|
That previous method *did* mostly work, but if you ever managed to get your $license->seats value out of whack
|
||||||
|
with your actual count of license_seats *records*, you would never manage to get back 'into whack'.
|
||||||
|
The below method actually grabs a count of existing license_seats records, so it will be more accurate.
|
||||||
|
This means that if your license_seats are out of whack, you can change the quantity and hit 'save' and it
|
||||||
|
will manage to 'true up' and make your counts line up correctly.
|
||||||
|
*/
|
||||||
|
$oldSeatCount = $license->license_seats_count;
|
||||||
|
|
||||||
return static::adjustSeatCount($license, $oldSeatCount, $newSeatCount);
|
return static::adjustSeatCount($license, $oldSeatCount, $newSeatCount);
|
||||||
});
|
});
|
||||||
|
|
|
@ -21,11 +21,10 @@ class Setting extends Model
|
||||||
use Notifiable, ValidatingTrait;
|
use Notifiable, ValidatingTrait;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The app settings cache key name.
|
* The cache property so that multiple invocations of this will only load the Settings record from disk only once
|
||||||
*
|
* @var self
|
||||||
* @var string
|
|
||||||
*/
|
*/
|
||||||
const APP_SETTINGS_KEY = 'snipeit_app_settings';
|
public static ?self $_cache = null;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The setup check cache key name.
|
* The setup check cache key name.
|
||||||
|
@ -98,14 +97,15 @@ class Setting extends Model
|
||||||
*/
|
*/
|
||||||
public static function getSettings(): ?self
|
public static function getSettings(): ?self
|
||||||
{
|
{
|
||||||
return Cache::rememberForever(self::APP_SETTINGS_KEY, function () {
|
if (!self::$_cache) {
|
||||||
// Need for setup as no tables exist
|
// Need for setup as no tables exist
|
||||||
try {
|
try {
|
||||||
return self::first();
|
self::$_cache = self::first();
|
||||||
} catch (\Throwable $th) {
|
} catch (\Throwable $th) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
});
|
}
|
||||||
|
return self::$_cache;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
|
@ -41,8 +41,10 @@ class SnipeSCIMConfig extends \ArieTimmerman\Laravel\SCIMServer\SCIMConfig
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
|
|
||||||
$config['validations'][$core.'externalId'] = 'string'; // not required, but supported mostly just for Okta
|
// externalId support
|
||||||
$mappings['externalId'] = AttributeMapping::eloquent('scim_externalid');
|
$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'] = 'nullable|array'; // emails are not required in Snipe-IT...
|
||||||
$config['validations'][$core.'emails.*.value'] = 'email'; // ...(had to remove the recommended 'required' here)
|
$config['validations'][$core.'emails.*.value'] = 'email'; // ...(had to remove the recommended 'required' here)
|
||||||
|
|
|
@ -61,6 +61,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||||
'remote',
|
'remote',
|
||||||
'start_date',
|
'start_date',
|
||||||
'end_date',
|
'end_date',
|
||||||
|
'scim_externalid'
|
||||||
];
|
];
|
||||||
|
|
||||||
protected $casts = [
|
protected $casts = [
|
||||||
|
@ -337,6 +338,24 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||||
return $this->belongsToMany(\App\Models\License::class, 'license_seats', 'assigned_to', 'license_id')->withPivot('id');
|
return $this->belongsToMany(\App\Models\License::class, 'license_seats', 'assigned_to', 'license_id')->withPivot('id');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Establishes a count of all items assigned
|
||||||
|
*
|
||||||
|
* @author J. Vinsmoke
|
||||||
|
* @since [v6.1]
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||||
|
*/
|
||||||
|
Public function allAssignedCount() {
|
||||||
|
$assetsCount = $this->assets()->count();
|
||||||
|
$licensesCount = $this->licenses()->count();
|
||||||
|
$accessoriesCount = $this->accessories()->count();
|
||||||
|
$consumablesCount = $this->consumables()->count();
|
||||||
|
|
||||||
|
$totalCount = $assetsCount + $licensesCount + $accessoriesCount + $consumablesCount;
|
||||||
|
|
||||||
|
return (int) $totalCount;
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Establishes the user -> actionlogs relationship
|
* Establishes the user -> actionlogs relationship
|
||||||
*
|
*
|
||||||
|
@ -567,6 +586,7 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||||
if ((Setting::getSettings()->two_factor_enabled == '1') && ($this->two_factor_optin == '1')) {
|
if ((Setting::getSettings()->two_factor_enabled == '1') && ($this->two_factor_optin == '1')) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// If the 2FA is required for everyone so is implicitly active
|
// If the 2FA is required for everyone so is implicitly active
|
||||||
elseif (Setting::getSettings()->two_factor_enabled == '2') {
|
elseif (Setting::getSettings()->two_factor_enabled == '2') {
|
||||||
return true;
|
return true;
|
||||||
|
@ -575,18 +595,6 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the admin user who created this user
|
|
||||||
*
|
|
||||||
* @author [A. Gianotto] [<snipe@snipe.net>]
|
|
||||||
* @since [v6.0.5]
|
|
||||||
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
|
||||||
*/
|
|
||||||
public function createdBy()
|
|
||||||
{
|
|
||||||
return $this->belongsTo(\App\Models\User::class, 'created_by')->withTrashed();
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Check whether two-factor authorization is required and the user has activated it
|
* Check whether two-factor authorization is required and the user has activated it
|
||||||
* and enrolled a device
|
* and enrolled a device
|
||||||
|
@ -615,6 +623,19 @@ class User extends SnipeModel implements AuthenticatableContract, AuthorizableCo
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the admin user who created this user
|
||||||
|
*
|
||||||
|
* @author [A. Gianotto] [<snipe@snipe.net>]
|
||||||
|
* @since [v6.0.5]
|
||||||
|
* @return \Illuminate\Database\Eloquent\Relations\Relation
|
||||||
|
*/
|
||||||
|
public function createdBy()
|
||||||
|
{
|
||||||
|
return $this->belongsTo(\App\Models\User::class, 'created_by')->withTrashed();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
public function decodePermissions()
|
public function decodePermissions()
|
||||||
{
|
{
|
||||||
|
|
|
@ -19,11 +19,11 @@ class WelcomeNotification extends Notification
|
||||||
*/
|
*/
|
||||||
public function __construct(array $content)
|
public function __construct(array $content)
|
||||||
{
|
{
|
||||||
$this->_data['email'] = $content['email'];
|
$this->_data['email'] = htmlspecialchars_decode($content['email']);
|
||||||
$this->_data['first_name'] = $content['first_name'];
|
$this->_data['first_name'] = htmlspecialchars_decode($content['first_name']);
|
||||||
$this->_data['last_name'] = $content['last_name'];
|
$this->_data['last_name'] = htmlspecialchars_decode($content['last_name']);
|
||||||
$this->_data['username'] = $content['username'];
|
$this->_data['username'] = htmlspecialchars_decode($content['username']);
|
||||||
$this->_data['password'] = $content['password'];
|
$this->_data['password'] = htmlspecialchars_decode($content['password']);
|
||||||
$this->_data['url'] = url('/');
|
$this->_data['url'] = url('/');
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -16,7 +16,6 @@ class SettingObserver
|
||||||
*/
|
*/
|
||||||
public function saved(Setting $setting)
|
public function saved(Setting $setting)
|
||||||
{
|
{
|
||||||
Cache::forget(Setting::APP_SETTINGS_KEY);
|
|
||||||
Cache::forget(Setting::SETUP_CHECK_KEY);
|
Cache::forget(Setting::SETUP_CHECK_KEY);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,7 +88,7 @@ class AssetModelPresenter extends Presenter
|
||||||
'sortable' => true,
|
'sortable' => true,
|
||||||
'switchable' => true,
|
'switchable' => true,
|
||||||
'title' => trans('general.category'),
|
'title' => trans('general.category'),
|
||||||
'visible' => false,
|
'visible' => true,
|
||||||
'formatter' => 'categoriesLinkObjFormatter',
|
'formatter' => 'categoriesLinkObjFormatter',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
|
|
|
@ -140,6 +140,12 @@ class AssetPresenter extends Presenter
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
'title' => trans('general.purchase_date'),
|
'title' => trans('general.purchase_date'),
|
||||||
'formatter' => 'dateDisplayFormatter',
|
'formatter' => 'dateDisplayFormatter',
|
||||||
|
], [
|
||||||
|
'field' => 'age',
|
||||||
|
'searchable' => true,
|
||||||
|
'sortable' => true,
|
||||||
|
'visible' => false,
|
||||||
|
'title' => trans('general.age'),
|
||||||
], [
|
], [
|
||||||
'field' => 'purchase_cost',
|
'field' => 'purchase_cost',
|
||||||
'searchable' => true,
|
'searchable' => true,
|
||||||
|
@ -244,6 +250,14 @@ class AssetPresenter extends Presenter
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
'title' => trans('general.next_audit_date'),
|
'title' => trans('general.next_audit_date'),
|
||||||
'formatter' => 'dateDisplayFormatter',
|
'formatter' => 'dateDisplayFormatter',
|
||||||
|
], [
|
||||||
|
'field' => 'byod',
|
||||||
|
'searchable' => false,
|
||||||
|
'sortable' => true,
|
||||||
|
'visible' => false,
|
||||||
|
'title' => trans('general.byod'),
|
||||||
|
'formatter' => 'trueFalseFormatter',
|
||||||
|
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -70,47 +70,33 @@ class CategoryPresenter extends Presenter
|
||||||
'visible' => true,
|
'visible' => true,
|
||||||
'formatter' => 'trueFalseFormatter',
|
'formatter' => 'trueFalseFormatter',
|
||||||
], [
|
], [
|
||||||
'field' => 'actions',
|
|
||||||
'searchable' => false,
|
|
||||||
'sortable' => false,
|
|
||||||
'switchable' => false,
|
|
||||||
'title' => trans('table.actions'),
|
|
||||||
],[
|
|
||||||
"field" => "use_default_eula",
|
"field" => "use_default_eula",
|
||||||
"searchable" => false,
|
"searchable" => false,
|
||||||
"sortable" => true,
|
"sortable" => true,
|
||||||
"title" => trans('admin/categories/general.use_default_eula_column'),
|
"title" => trans('admin/categories/general.use_default_eula_column'),
|
||||||
'visible' => true,
|
'visible' => true,
|
||||||
"formatter" => 'trueFalseFormatter',
|
"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',
|
'field' => 'created_at',
|
||||||
'searchable' => true,
|
'searchable' => true,
|
||||||
'sortable' => true,
|
'sortable' => true,
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
'title' => trans('general.created_at'),
|
'title' => trans('general.created_at'),
|
||||||
'formatter' => 'dateDisplayFormatter',
|
'formatter' => 'dateDisplayFormatter',
|
||||||
],
|
], [
|
||||||
[
|
|
||||||
'field' => 'updated_at',
|
'field' => 'updated_at',
|
||||||
'searchable' => true,
|
'searchable' => true,
|
||||||
'sortable' => true,
|
'sortable' => true,
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
'title' => trans('general.updated_at'),
|
'title' => trans('general.updated_at'),
|
||||||
'formatter' => 'dateDisplayFormatter',
|
'formatter' => 'dateDisplayFormatter',
|
||||||
|
], [
|
||||||
|
'field' => 'actions',
|
||||||
|
'searchable' => false,
|
||||||
|
'sortable' => false,
|
||||||
|
'switchable' => false,
|
||||||
|
'title' => trans('table.actions'),
|
||||||
|
'formatter' => 'categoriesActionsFormatter',
|
||||||
],
|
],
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
|
@ -268,9 +268,9 @@ class UserPresenter extends Presenter
|
||||||
'formatter' => 'trueFalseFormatter',
|
'formatter' => 'trueFalseFormatter',
|
||||||
],
|
],
|
||||||
[
|
[
|
||||||
'field' => 'two_factor_activated',
|
'field' => 'two_factor_optin',
|
||||||
'searchable' => false,
|
'searchable' => false,
|
||||||
'sortable' => false,
|
'sortable' => true,
|
||||||
'switchable' => true,
|
'switchable' => true,
|
||||||
'title' => trans('admin/users/general.two_factor_active'),
|
'title' => trans('admin/users/general.two_factor_active'),
|
||||||
'visible' => false,
|
'visible' => false,
|
||||||
|
|
|
@ -114,6 +114,24 @@ class AuthServiceProvider extends ServiceProvider
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Gate::define('accessories.files', function ($user) {
|
||||||
|
if ($user->hasAccess('accessories.files')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Gate::define('components.files', function ($user) {
|
||||||
|
if ($user->hasAccess('components.files')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
Gate::define('consumables.files', function ($user) {
|
||||||
|
if ($user->hasAccess('consumables.files')) {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
// Can the user import CSVs?
|
// Can the user import CSVs?
|
||||||
Gate::define('import', function ($user) {
|
Gate::define('import', function ($user) {
|
||||||
if ($user->hasAccess('import')) {
|
if ($user->hasAccess('import')) {
|
||||||
|
@ -159,6 +177,10 @@ class AuthServiceProvider extends ServiceProvider
|
||||||
return $user->hasAccess('self.checkout_assets');
|
return $user->hasAccess('self.checkout_assets');
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Gate::define('self.view_purchase_cost', function ($user) {
|
||||||
|
return $user->hasAccess('self.view_purchase_cost');
|
||||||
|
});
|
||||||
|
|
||||||
// This is largely used to determine whether to display the gear icon sidenav
|
// This is largely used to determine whether to display the gear icon sidenav
|
||||||
// in the left-side navigation
|
// in the left-side navigation
|
||||||
Gate::define('backend.interact', function ($user) {
|
Gate::define('backend.interact', function ($user) {
|
||||||
|
|
|
@ -2,8 +2,10 @@
|
||||||
|
|
||||||
namespace App\Providers;
|
namespace App\Providers;
|
||||||
|
|
||||||
|
use App\Models\Department;
|
||||||
use DB;
|
use DB;
|
||||||
use Illuminate\Support\ServiceProvider;
|
use Illuminate\Support\ServiceProvider;
|
||||||
|
use Illuminate\Validation\Rule;
|
||||||
use Validator;
|
use Validator;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -213,6 +215,23 @@ class ValidationServiceProvider extends ServiceProvider
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
Validator::extend('is_unique_department', function ($attribute, $value, $parameters, $validator) {
|
||||||
|
$data = $validator->getData();
|
||||||
|
if ((array_key_exists('location_id', $data) && $data['location_id'] != null) && (array_key_exists('company_id', $data) && $data['company_id'] != null)) {
|
||||||
|
$count = Department::where('name', $data['name'])
|
||||||
|
->where('location_id', $data['location_id'])
|
||||||
|
->where('company_id', $data['company_id'])
|
||||||
|
->whereNotNull('company_id')
|
||||||
|
->whereNotNull('location_id')
|
||||||
|
->count('name');
|
||||||
|
|
||||||
|
return $count < 1;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
|
16
composer.lock
generated
16
composer.lock
generated
|
@ -78,19 +78,19 @@
|
||||||
"source": {
|
"source": {
|
||||||
"type": "git",
|
"type": "git",
|
||||||
"url": "https://github.com/grokability/laravel-scim-server.git",
|
"url": "https://github.com/grokability/laravel-scim-server.git",
|
||||||
"reference": "9e7a8fd51a7380bc18ca1f01256574d75a2c6b49"
|
"reference": "2c7ecc450eee59234e059ec2e7724b2d8f3a8369"
|
||||||
},
|
},
|
||||||
"dist": {
|
"dist": {
|
||||||
"type": "zip",
|
"type": "zip",
|
||||||
"url": "https://api.github.com/repos/grokability/laravel-scim-server/zipball/9e7a8fd51a7380bc18ca1f01256574d75a2c6b49",
|
"url": "https://api.github.com/repos/grokability/laravel-scim-server/zipball/2c7ecc450eee59234e059ec2e7724b2d8f3a8369",
|
||||||
"reference": "9e7a8fd51a7380bc18ca1f01256574d75a2c6b49",
|
"reference": "2c7ecc450eee59234e059ec2e7724b2d8f3a8369",
|
||||||
"shasum": ""
|
"shasum": ""
|
||||||
},
|
},
|
||||||
"require": {
|
"require": {
|
||||||
"illuminate/console": "^6.0|^7.0|^8.0",
|
"illuminate/console": "^6.0|^7.0|^8.0|^9.0",
|
||||||
"illuminate/database": "^6.0|^7.0|^8.0",
|
"illuminate/database": "^6.0|^7.0|^8.0|^9.0",
|
||||||
"illuminate/support": "^6.0|^7.0|^8.0",
|
"illuminate/support": "^6.0|^7.0|^8.0|^9.0",
|
||||||
"php": "^7.4|^8.0",
|
"php": "^7.0|^8.0",
|
||||||
"tmilos/scim-filter-parser": "^1.3",
|
"tmilos/scim-filter-parser": "^1.3",
|
||||||
"tmilos/scim-schema": "^0.1.0"
|
"tmilos/scim-schema": "^0.1.0"
|
||||||
},
|
},
|
||||||
|
@ -133,7 +133,7 @@
|
||||||
"support": {
|
"support": {
|
||||||
"source": "https://github.com/grokability/laravel-scim-server/tree/master"
|
"source": "https://github.com/grokability/laravel-scim-server/tree/master"
|
||||||
},
|
},
|
||||||
"time": "2022-10-06T00:42:37+00:00"
|
"time": "2022-11-22T20:26:54+00:00"
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"name": "asm89/stack-cors",
|
"name": "asm89/stack-cors",
|
||||||
|
|
|
@ -4,7 +4,7 @@ use Monolog\Handler\NullHandler;
|
||||||
use Monolog\Handler\StreamHandler;
|
use Monolog\Handler\StreamHandler;
|
||||||
use Monolog\Handler\SyslogUdpHandler;
|
use Monolog\Handler\SyslogUdpHandler;
|
||||||
|
|
||||||
return [
|
$config = [
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|--------------------------------------------------------------------------
|
|--------------------------------------------------------------------------
|
||||||
|
@ -35,6 +35,8 @@ return [
|
||||||
*/
|
*/
|
||||||
|
|
||||||
'channels' => [
|
'channels' => [
|
||||||
|
// This will get overwritten to 'single' AND 'rollbar' in the code at the bottom of this file
|
||||||
|
// if a ROLLBAR_TOKEN is given in the .env file
|
||||||
'stack' => [
|
'stack' => [
|
||||||
'driver' => 'stack',
|
'driver' => 'stack',
|
||||||
'channels' => ['single'],
|
'channels' => ['single'],
|
||||||
|
@ -104,7 +106,23 @@ return [
|
||||||
'scimtrace' => [
|
'scimtrace' => [
|
||||||
'driver' => 'single',
|
'driver' => 'single',
|
||||||
'path' => storage_path('logs/scim.log')
|
'path' => storage_path('logs/scim.log')
|
||||||
]
|
],
|
||||||
|
|
||||||
|
'rollbar' => [
|
||||||
|
'driver' => 'monolog',
|
||||||
|
'handler' => \Rollbar\Laravel\MonologHandler::class,
|
||||||
|
'access_token' => env('ROLLBAR_TOKEN'),
|
||||||
|
'level' => env('ROLLBAR_LEVEL', 'error'),
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
||||||
|
|
||||||
|
// Only add rollbar if the .env has a rollbar token
|
||||||
|
if ((env('APP_ENV')=='production') && (env('ROLLBAR_TOKEN'))) {
|
||||||
|
$config['channels']['stack']['channels'] = ['single', 'rollbar'];
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return $config;
|
|
@ -145,6 +145,13 @@ return [
|
||||||
'note' => '',
|
'note' => '',
|
||||||
'display' => true,
|
'display' => true,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'permission' => 'accessories.files',
|
||||||
|
'label' => 'View and Modify Accessory Files',
|
||||||
|
'note' => '',
|
||||||
|
'display' => true,
|
||||||
|
],
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
'Consumables' => [
|
'Consumables' => [
|
||||||
|
@ -178,6 +185,12 @@ return [
|
||||||
'note' => '',
|
'note' => '',
|
||||||
'display' => true,
|
'display' => true,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'permission' => 'consumables.files',
|
||||||
|
'label' => 'View and Modify Consumable Files',
|
||||||
|
'note' => '',
|
||||||
|
'display' => true,
|
||||||
|
],
|
||||||
],
|
],
|
||||||
|
|
||||||
|
|
||||||
|
@ -264,6 +277,12 @@ return [
|
||||||
'note' => '',
|
'note' => '',
|
||||||
'display' => true,
|
'display' => true,
|
||||||
],
|
],
|
||||||
|
[
|
||||||
|
'permission' => 'components.files',
|
||||||
|
'label' => 'View and Modify Component Files',
|
||||||
|
'note' => '',
|
||||||
|
'display' => true,
|
||||||
|
],
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
|
@ -626,6 +645,13 @@ return [
|
||||||
'display' => true,
|
'display' => true,
|
||||||
],
|
],
|
||||||
|
|
||||||
|
[
|
||||||
|
'permission' => 'self.view_purchase_cost',
|
||||||
|
'label' => 'View Purchase-Cost Column',
|
||||||
|
'note' => 'This user can see the purchase cost column of items assigned to them.',
|
||||||
|
'display' => true,
|
||||||
|
],
|
||||||
|
|
||||||
],
|
],
|
||||||
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,6 +1,8 @@
|
||||||
<?php
|
<?php
|
||||||
|
|
||||||
return [
|
return [
|
||||||
|
"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,
|
"publish_routes" => false,
|
||||||
"trace" => env("SCIM_TRACE",false)
|
|
||||||
];
|
];
|
||||||
|
|
|
@ -1,10 +1,10 @@
|
||||||
<?php
|
<?php
|
||||||
return array (
|
return array (
|
||||||
'app_version' => 'v6.0.12',
|
'app_version' => 'v6.0.14',
|
||||||
'full_app_version' => 'v6.0.12 - build 8876-gbc4c6abe0',
|
'full_app_version' => 'v6.0.14 - build 9161-g799c9c910',
|
||||||
'build_version' => '8876',
|
'build_version' => '9161',
|
||||||
'prerelease_version' => '',
|
'prerelease_version' => '',
|
||||||
'hash_version' => 'gbc4c6abe0',
|
'hash_version' => 'g799c9c910',
|
||||||
'full_hash' => 'v6.0.12-50-gbc4c6abe0',
|
'full_hash' => 'v6.0.14-117-g799c9c910',
|
||||||
'branch' => 'develop',
|
'branch' => 'master',
|
||||||
);
|
);
|
|
@ -0,0 +1,33 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddsLdapDefaultGroupToSettingsTable extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('settings', function (Blueprint $table) {
|
||||||
|
$table->integer('ldap_default_group')
|
||||||
|
->after('ldap_basedn')->default(null);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('settings', function (Blueprint $table) {
|
||||||
|
$table->dropColumn('ldap_default_group');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -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');
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
|
@ -0,0 +1,30 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class FixNullableMigrationForSettings extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('settings', function (Blueprint $table) {
|
||||||
|
$table->string('ldap_default_group')->nullable()->default(null)->change();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
// nothing to do here - this is a hotfix
|
||||||
|
}
|
||||||
|
}
|
34
database/migrations/2023_01_18_122534_add_byod_to_assets.php
Normal file
34
database/migrations/2023_01_18_122534_add_byod_to_assets.php
Normal file
|
@ -0,0 +1,34 @@
|
||||||
|
<?php
|
||||||
|
|
||||||
|
use Illuminate\Database\Migrations\Migration;
|
||||||
|
use Illuminate\Database\Schema\Blueprint;
|
||||||
|
use Illuminate\Support\Facades\Schema;
|
||||||
|
|
||||||
|
class AddByodToAssets extends Migration
|
||||||
|
{
|
||||||
|
/**
|
||||||
|
* Run the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function up()
|
||||||
|
{
|
||||||
|
Schema::table('assets', function (Blueprint $table) {
|
||||||
|
$table->boolean('byod')->nullable()->default(0);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reverse the migrations.
|
||||||
|
*
|
||||||
|
* @return void
|
||||||
|
*/
|
||||||
|
public function down()
|
||||||
|
{
|
||||||
|
Schema::table('assets', function (Blueprint $table) {
|
||||||
|
if (Schema::hasColumn('assets', 'byod')) {
|
||||||
|
$table->dropColumn('byod');
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
360
package-lock.json
generated
360
package-lock.json
generated
|
@ -1329,9 +1329,9 @@
|
||||||
"dev": true
|
"dev": true
|
||||||
},
|
},
|
||||||
"@fortawesome/fontawesome-free": {
|
"@fortawesome/fontawesome-free": {
|
||||||
"version": "6.2.0",
|
"version": "6.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.2.0.tgz",
|
"resolved": "https://registry.npmjs.org/@fortawesome/fontawesome-free/-/fontawesome-free-6.2.1.tgz",
|
||||||
"integrity": "sha512-CNR7qRIfCwWHNN7FnKUniva94edPdyQzil/zCwk3v6k4R6rR2Fr8i4s3PM7n/lyfPA6Zfko9z5WDzFxG9SW1uQ=="
|
"integrity": "sha512-viouXhegu/TjkvYQoiRZK3aax69dGXxgEjpvZW81wIJdxm5Fnvp3VVIP4VHKqX4SvFw6qpmkILkD4RJWAdrt7A=="
|
||||||
},
|
},
|
||||||
"@jridgewell/gen-mapping": {
|
"@jridgewell/gen-mapping": {
|
||||||
"version": "0.1.1",
|
"version": "0.1.1",
|
||||||
|
@ -3588,9 +3588,9 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"camelcase": {
|
"camelcase": {
|
||||||
"version": "5.3.1",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-5.3.1.tgz",
|
"resolved": "https://registry.npmjs.org/camelcase/-/camelcase-6.3.0.tgz",
|
||||||
"integrity": "sha512-L28STB170nwWS63UjtlEOE3dldQApaJXZkOI1uMFfzf3rRuPegHaHesyee+YxQ+W6SvRDQV6UrdOdRiR153wJg=="
|
"integrity": "sha512-Gmy6FhYlCY7uOElZUSbxo2UCDH8owEk996gkbrpsgGtrJLM3J7jGxl9Ic7Qwwj4ivOE5AWZWRMecDdF7hqGjFA=="
|
||||||
},
|
},
|
||||||
"caniuse-api": {
|
"caniuse-api": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
|
@ -4244,75 +4244,60 @@
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"css-loader": {
|
"css-loader": {
|
||||||
"version": "3.6.0",
|
"version": "4.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-3.6.0.tgz",
|
"resolved": "https://registry.npmjs.org/css-loader/-/css-loader-4.3.0.tgz",
|
||||||
"integrity": "sha512-M5lSukoWi1If8dhQAUCvj4H8vUt3vOnwbQBH9DdTm/s4Ym2B/3dPMtYZeJmq7Q3S3Pa+I94DcZ7pc9bP14cWIQ==",
|
"integrity": "sha512-rdezjCjScIrsL8BSYszgT4s476IcNKt6yX69t0pHjJVnPUTDpn4WfIpDQTN3wCJvUvfsz/mFjuGOekf3PY3NUg==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"camelcase": "^5.3.1",
|
"camelcase": "^6.0.0",
|
||||||
"cssesc": "^3.0.0",
|
"cssesc": "^3.0.0",
|
||||||
"icss-utils": "^4.1.1",
|
"icss-utils": "^4.1.1",
|
||||||
"loader-utils": "^1.2.3",
|
"loader-utils": "^2.0.0",
|
||||||
"normalize-path": "^3.0.0",
|
|
||||||
"postcss": "^7.0.32",
|
"postcss": "^7.0.32",
|
||||||
"postcss-modules-extract-imports": "^2.0.0",
|
"postcss-modules-extract-imports": "^2.0.0",
|
||||||
"postcss-modules-local-by-default": "^3.0.2",
|
"postcss-modules-local-by-default": "^3.0.3",
|
||||||
"postcss-modules-scope": "^2.2.0",
|
"postcss-modules-scope": "^2.2.0",
|
||||||
"postcss-modules-values": "^3.0.0",
|
"postcss-modules-values": "^3.0.0",
|
||||||
"postcss-value-parser": "^4.1.0",
|
"postcss-value-parser": "^4.1.0",
|
||||||
"schema-utils": "^2.7.0",
|
"schema-utils": "^2.7.1",
|
||||||
"semver": "^6.3.0"
|
"semver": "^7.3.2"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": {
|
"loader-utils": {
|
||||||
"version": "3.2.1",
|
"version": "2.0.4",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.4.tgz",
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
"integrity": "sha512-xXqpXoINfFhgua9xiqD8fPFHgkoq1mmmpE92WlDbm9rNRd/EbRb+Gqf908T2DMfuHjjJlksiK2RbHVOdD/MqSw==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"color-convert": "^1.9.0"
|
"big.js": "^5.2.2",
|
||||||
|
"emojis-list": "^3.0.0",
|
||||||
|
"json5": "^2.1.2"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"chalk": {
|
"picocolors": {
|
||||||
"version": "2.4.2",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
|
||||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
"integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^3.2.1",
|
|
||||||
"escape-string-regexp": "^1.0.5",
|
|
||||||
"supports-color": "^5.3.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"supports-color": {
|
|
||||||
"version": "5.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "7.0.36",
|
"version": "7.0.39",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
|
||||||
"integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
|
"integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chalk": "^2.4.2",
|
"picocolors": "^0.2.1",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1"
|
||||||
"supports-color": "^6.1.0"
|
}
|
||||||
|
},
|
||||||
|
"semver": {
|
||||||
|
"version": "7.3.8",
|
||||||
|
"resolved": "https://registry.npmjs.org/semver/-/semver-7.3.8.tgz",
|
||||||
|
"integrity": "sha512-NB1ctGL5rlHrPJtFDVIVzTyQylMLu9N9VICA6HSFJo8MCGVTMW6gfpicwKmmK/dAjTOrqu5l63JJOpDSrAis3A==",
|
||||||
|
"requires": {
|
||||||
|
"lru-cache": "^6.0.0"
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "6.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
|
|
||||||
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -4936,7 +4921,8 @@
|
||||||
"escape-string-regexp": {
|
"escape-string-regexp": {
|
||||||
"version": "1.0.5",
|
"version": "1.0.5",
|
||||||
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
"resolved": "https://registry.npmjs.org/escape-string-regexp/-/escape-string-regexp-1.0.5.tgz",
|
||||||
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ="
|
"integrity": "sha1-G2HAViGQqN/2rjuyzwIAyhMLhtQ=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"escodegen": {
|
"escodegen": {
|
||||||
"version": "1.14.3",
|
"version": "1.14.3",
|
||||||
|
@ -15028,7 +15014,8 @@
|
||||||
"has-flag": {
|
"has-flag": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-3.0.0.tgz",
|
||||||
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0="
|
"integrity": "sha1-tdRU3CGZriJWmfNGfloH87lVuv0=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"has-symbols": {
|
"has-symbols": {
|
||||||
"version": "1.0.1",
|
"version": "1.0.1",
|
||||||
|
@ -15350,56 +15337,24 @@
|
||||||
"postcss": "^7.0.14"
|
"postcss": "^7.0.14"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": {
|
"picocolors": {
|
||||||
"version": "3.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
"integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="
|
||||||
"requires": {
|
|
||||||
"color-convert": "^1.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chalk": {
|
|
||||||
"version": "2.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
|
||||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^3.2.1",
|
|
||||||
"escape-string-regexp": "^1.0.5",
|
|
||||||
"supports-color": "^5.3.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"supports-color": {
|
|
||||||
"version": "5.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "7.0.36",
|
"version": "7.0.39",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
|
||||||
"integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
|
"integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chalk": "^2.4.2",
|
"picocolors": "^0.2.1",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1"
|
||||||
"supports-color": "^6.1.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "6.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
|
|
||||||
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -15867,8 +15822,7 @@
|
||||||
"json5": {
|
"json5": {
|
||||||
"version": "2.2.1",
|
"version": "2.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/json5/-/json5-2.2.1.tgz",
|
||||||
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA==",
|
"integrity": "sha512-1hqLFMSrGHRHxav9q9gNjJ5EXznIxGVO09xQRrwplcS8qs28pZ8s8hupZAmqDwZUmVZ2Qb2jnyPOWcDH8m8dlA=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"jsonfile": {
|
"jsonfile": {
|
||||||
"version": "6.1.0",
|
"version": "6.1.0",
|
||||||
|
@ -16453,7 +16407,6 @@
|
||||||
"version": "6.0.0",
|
"version": "6.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/lru-cache/-/lru-cache-6.0.0.tgz",
|
||||||
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
"integrity": "sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==",
|
||||||
"dev": true,
|
|
||||||
"requires": {
|
"requires": {
|
||||||
"yallist": "^4.0.0"
|
"yallist": "^4.0.0"
|
||||||
}
|
}
|
||||||
|
@ -17011,7 +16964,8 @@
|
||||||
"normalize-path": {
|
"normalize-path": {
|
||||||
"version": "3.0.0",
|
"version": "3.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/normalize-path/-/normalize-path-3.0.0.tgz",
|
||||||
"integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU="
|
"integrity": "sha1-Dc1p/yOhybEf0JeDFmRKA4ghamU=",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"normalize-range": {
|
"normalize-range": {
|
||||||
"version": "0.1.2",
|
"version": "0.1.2",
|
||||||
|
@ -17691,56 +17645,24 @@
|
||||||
"postcss": "^7.0.5"
|
"postcss": "^7.0.5"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": {
|
"picocolors": {
|
||||||
"version": "3.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
"integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="
|
||||||
"requires": {
|
|
||||||
"color-convert": "^1.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chalk": {
|
|
||||||
"version": "2.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
|
||||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^3.2.1",
|
|
||||||
"escape-string-regexp": "^1.0.5",
|
|
||||||
"supports-color": "^5.3.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"supports-color": {
|
|
||||||
"version": "5.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "7.0.36",
|
"version": "7.0.39",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
|
||||||
"integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
|
"integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chalk": "^2.4.2",
|
"picocolors": "^0.2.1",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1"
|
||||||
"supports-color": "^6.1.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "6.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
|
|
||||||
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -17755,56 +17677,24 @@
|
||||||
"postcss-value-parser": "^4.1.0"
|
"postcss-value-parser": "^4.1.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": {
|
"picocolors": {
|
||||||
"version": "3.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
"integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="
|
||||||
"requires": {
|
|
||||||
"color-convert": "^1.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chalk": {
|
|
||||||
"version": "2.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
|
||||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^3.2.1",
|
|
||||||
"escape-string-regexp": "^1.0.5",
|
|
||||||
"supports-color": "^5.3.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"supports-color": {
|
|
||||||
"version": "5.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "7.0.36",
|
"version": "7.0.39",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
|
||||||
"integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
|
"integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chalk": "^2.4.2",
|
"picocolors": "^0.2.1",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1"
|
||||||
"supports-color": "^6.1.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "6.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
|
|
||||||
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -17817,56 +17707,24 @@
|
||||||
"postcss-selector-parser": "^6.0.0"
|
"postcss-selector-parser": "^6.0.0"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": {
|
"picocolors": {
|
||||||
"version": "3.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
"integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="
|
||||||
"requires": {
|
|
||||||
"color-convert": "^1.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chalk": {
|
|
||||||
"version": "2.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
|
||||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^3.2.1",
|
|
||||||
"escape-string-regexp": "^1.0.5",
|
|
||||||
"supports-color": "^5.3.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"supports-color": {
|
|
||||||
"version": "5.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "7.0.36",
|
"version": "7.0.39",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
|
||||||
"integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
|
"integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chalk": "^2.4.2",
|
"picocolors": "^0.2.1",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1"
|
||||||
"supports-color": "^6.1.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "6.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
|
|
||||||
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -17879,56 +17737,24 @@
|
||||||
"postcss": "^7.0.6"
|
"postcss": "^7.0.6"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"ansi-styles": {
|
"picocolors": {
|
||||||
"version": "3.2.1",
|
"version": "0.2.1",
|
||||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-3.2.1.tgz",
|
"resolved": "https://registry.npmjs.org/picocolors/-/picocolors-0.2.1.tgz",
|
||||||
"integrity": "sha512-VT0ZI6kZRdTh8YyJw3SMbYm/u+NqfsAxEpWO0Pf9sq8/e94WxxOpPKx9FR1FlyCtOVDNOQ+8ntlqFxiRc+r5qA==",
|
"integrity": "sha512-cMlDqaLEqfSaW8Z7N5Jw+lyIW869EzT73/F5lhtY9cLGoVxSXznfgfXMO0Z5K0o0Q2TkTXq+0KFsdnSe3jDViA=="
|
||||||
"requires": {
|
|
||||||
"color-convert": "^1.9.0"
|
|
||||||
}
|
|
||||||
},
|
|
||||||
"chalk": {
|
|
||||||
"version": "2.4.2",
|
|
||||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-2.4.2.tgz",
|
|
||||||
"integrity": "sha512-Mti+f9lpJNcwF4tWV8/OrTTtF1gZi+f8FqlyAdouralcFWFQWF2+NgCHShjkCb+IFBLq9buZwE1xckQU4peSuQ==",
|
|
||||||
"requires": {
|
|
||||||
"ansi-styles": "^3.2.1",
|
|
||||||
"escape-string-regexp": "^1.0.5",
|
|
||||||
"supports-color": "^5.3.0"
|
|
||||||
},
|
|
||||||
"dependencies": {
|
|
||||||
"supports-color": {
|
|
||||||
"version": "5.5.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-5.5.0.tgz",
|
|
||||||
"integrity": "sha512-QjVjwdXIt408MIiAqCX4oUKsgU2EqAGzs2Ppkm4aQYbjm+ZEWEcW4SfFNTr4uMNZma0ey4f5lgLrkB0aX0QMow==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
},
|
},
|
||||||
"postcss": {
|
"postcss": {
|
||||||
"version": "7.0.36",
|
"version": "7.0.39",
|
||||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
|
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.39.tgz",
|
||||||
"integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
|
"integrity": "sha512-yioayjNbHn6z1/Bywyb2Y4s3yvDAeXGOyxqD+LnVOinq6Mdmd++SW2wUNVzavyyHxd6+DxzWGIuosg6P1Rj8uA==",
|
||||||
"requires": {
|
"requires": {
|
||||||
"chalk": "^2.4.2",
|
"picocolors": "^0.2.1",
|
||||||
"source-map": "^0.6.1",
|
"source-map": "^0.6.1"
|
||||||
"supports-color": "^6.1.0"
|
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
"source-map": {
|
"source-map": {
|
||||||
"version": "0.6.1",
|
"version": "0.6.1",
|
||||||
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
"resolved": "https://registry.npmjs.org/source-map/-/source-map-0.6.1.tgz",
|
||||||
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
"integrity": "sha512-UjgapumWlbMhkBgzT7Ykc5YXUT46F0iKu8SGXq0bcwP5dz/h0Plj6enJqjz1Zbq2l5WaqYnrVbwWOWMyF3F47g=="
|
||||||
},
|
|
||||||
"supports-color": {
|
|
||||||
"version": "6.1.0",
|
|
||||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-6.1.0.tgz",
|
|
||||||
"integrity": "sha512-qe1jfm1Mg7Nq/NSh6XE24gPXROEVsWHxC1LIx//XNlD9iw7YZQGjZNjYN7xGaEG6iKdA8EtNFW6R0gjnVXp+wQ==",
|
|
||||||
"requires": {
|
|
||||||
"has-flag": "^3.0.0"
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
|
@ -18714,7 +18540,8 @@
|
||||||
"semver": {
|
"semver": {
|
||||||
"version": "6.3.0",
|
"version": "6.3.0",
|
||||||
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
"resolved": "https://registry.npmjs.org/semver/-/semver-6.3.0.tgz",
|
||||||
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw=="
|
"integrity": "sha512-b39TBaTSfV6yBrapU89p5fKekE2m/NwnDocOVruQFS1/veMgdzuPcnOM34M6CwxW8jH/lxEa5rBoDeUwu5HHTw==",
|
||||||
|
"dev": true
|
||||||
},
|
},
|
||||||
"send": {
|
"send": {
|
||||||
"version": "0.18.0",
|
"version": "0.18.0",
|
||||||
|
@ -20418,8 +20245,7 @@
|
||||||
"yallist": {
|
"yallist": {
|
||||||
"version": "4.0.0",
|
"version": "4.0.0",
|
||||||
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
"resolved": "https://registry.npmjs.org/yallist/-/yallist-4.0.0.tgz",
|
||||||
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A==",
|
"integrity": "sha512-3wdGidZyq5PB084XLES5TpOSRA3wjXAlIWMhum2kRcv/41Sn2emQ0dycQW4uZXLejwKvg6EsvbdlVL+FYEct7A=="
|
||||||
"dev": true
|
|
||||||
},
|
},
|
||||||
"yaml": {
|
"yaml": {
|
||||||
"version": "1.10.2",
|
"version": "1.10.2",
|
||||||
|
|
|
@ -24,7 +24,7 @@
|
||||||
"vue-template-compiler": "2.4.4"
|
"vue-template-compiler": "2.4.4"
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fortawesome/fontawesome-free": "^6.2.0",
|
"@fortawesome/fontawesome-free": "^6.2.1",
|
||||||
"acorn": "^8.8.0",
|
"acorn": "^8.8.0",
|
||||||
"acorn-import-assertions": "^1.8.0",
|
"acorn-import-assertions": "^1.8.0",
|
||||||
"admin-lte": "^2.4.18",
|
"admin-lte": "^2.4.18",
|
||||||
|
@ -37,7 +37,7 @@
|
||||||
"bootstrap-less": "^3.3.8",
|
"bootstrap-less": "^3.3.8",
|
||||||
"bootstrap-table": "1.20.2",
|
"bootstrap-table": "1.20.2",
|
||||||
"chart.js": "^2.9.4",
|
"chart.js": "^2.9.4",
|
||||||
"css-loader": "^3.6.0",
|
"css-loader": "^4.0.0",
|
||||||
"ekko-lightbox": "^5.1.1",
|
"ekko-lightbox": "^5.1.1",
|
||||||
"icheck": "^1.0.2",
|
"icheck": "^1.0.2",
|
||||||
"imagemin": "^8.0.1",
|
"imagemin": "^8.0.1",
|
||||||
|
@ -48,7 +48,7 @@
|
||||||
"jquery.iframe-transport": "^1.0.0",
|
"jquery.iframe-transport": "^1.0.0",
|
||||||
"jspdf-autotable": "^3.5.24",
|
"jspdf-autotable": "^3.5.24",
|
||||||
"less": "^4.1.2",
|
"less": "^4.1.2",
|
||||||
"less-loader": "^5.0.0",
|
"less-loader": "^5.0",
|
||||||
"list.js": "^1.5.0",
|
"list.js": "^1.5.0",
|
||||||
"papaparse": "^4.3.3",
|
"papaparse": "^4.3.3",
|
||||||
"select2": "4.0.13",
|
"select2": "4.0.13",
|
||||||
|
|
|
@ -968,4 +968,9 @@ th.css-accessory > .th-inner::before {
|
||||||
margin-top: 51px;
|
margin-top: 51px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ellipsis {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
|
@ -601,4 +601,9 @@ th.css-accessory > .th-inner::before {
|
||||||
margin-top: 51px;
|
margin-top: 51px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ellipsis {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
10
public/css/dist/all.css
vendored
10
public/css/dist/all.css
vendored
|
@ -23830,6 +23830,11 @@ th.css-accessory > .th-inner::before {
|
||||||
margin-top: 51px;
|
margin-top: 51px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ellipsis {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
.select2-container {
|
.select2-container {
|
||||||
|
@ -24917,4 +24922,9 @@ th.css-accessory > .th-inner::before {
|
||||||
margin-top: 51px;
|
margin-top: 51px;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
.ellipsis {
|
||||||
|
overflow: hidden;
|
||||||
|
white-space: nowrap;
|
||||||
|
text-overflow: ellipsis;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
3
public/css/dist/skins/skin-black-dark.css
vendored
3
public/css/dist/skins/skin-black-dark.css
vendored
|
@ -217,6 +217,9 @@ a:visited {
|
||||||
.navbar-nav > li > a:link {
|
.navbar-nav > li > a:link {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.modal-content {
|
.modal-content {
|
||||||
background-color: var(--back-main);
|
background-color: var(--back-main);
|
||||||
color: var(--text-main);
|
color: var(--text-main);
|
||||||
|
|
|
@ -217,6 +217,9 @@ a:visited {
|
||||||
.navbar-nav > li > a:link {
|
.navbar-nav > li > a:link {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.modal-content {
|
.modal-content {
|
||||||
background-color: var(--back-main);
|
background-color: var(--back-main);
|
||||||
color: var(--text-main);
|
color: var(--text-main);
|
||||||
|
|
3
public/css/dist/skins/skin-black.css
vendored
3
public/css/dist/skins/skin-black.css
vendored
|
@ -199,6 +199,9 @@ a.btn-danger:visited {
|
||||||
.btn-danger.btn-sm.disabled {
|
.btn-danger.btn-sm.disabled {
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.sidebar-toggle-mobile {
|
.sidebar-toggle-mobile {
|
||||||
color: #FFF !important;
|
color: #FFF !important;
|
||||||
}
|
}
|
||||||
|
|
3
public/css/dist/skins/skin-black.min.css
vendored
3
public/css/dist/skins/skin-black.min.css
vendored
|
@ -199,6 +199,9 @@ a.btn-danger:visited {
|
||||||
.btn-danger.btn-sm.disabled {
|
.btn-danger.btn-sm.disabled {
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.sidebar-toggle-mobile {
|
.sidebar-toggle-mobile {
|
||||||
color: #FFF !important;
|
color: #FFF !important;
|
||||||
}
|
}
|
||||||
|
|
3
public/css/dist/skins/skin-blue-dark.css
vendored
3
public/css/dist/skins/skin-blue-dark.css
vendored
|
@ -212,6 +212,9 @@ a:visited {
|
||||||
.navbar-nav > li > a:link {
|
.navbar-nav > li > a:link {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.modal-content {
|
.modal-content {
|
||||||
background-color: var(--back-main);
|
background-color: var(--back-main);
|
||||||
color: var(--text-main);
|
color: var(--text-main);
|
||||||
|
|
3
public/css/dist/skins/skin-blue-dark.min.css
vendored
3
public/css/dist/skins/skin-blue-dark.min.css
vendored
|
@ -212,6 +212,9 @@ a:visited {
|
||||||
.navbar-nav > li > a:link {
|
.navbar-nav > li > a:link {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.modal-content {
|
.modal-content {
|
||||||
background-color: var(--back-main);
|
background-color: var(--back-main);
|
||||||
color: var(--text-main);
|
color: var(--text-main);
|
||||||
|
|
5
public/css/dist/skins/skin-blue.css
vendored
5
public/css/dist/skins/skin-blue.css
vendored
|
@ -123,7 +123,7 @@
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
}
|
}
|
||||||
.skin-blue.layout-top-nav .main-header > .logo .logo-variant {
|
.skin-blue.layout-top-nav .main-header > .logo .logo-variant {
|
||||||
background-color: none;
|
background-color: unset;
|
||||||
}
|
}
|
||||||
.btn.btn-primary,
|
.btn.btn-primary,
|
||||||
btn-sm.btn-primary,
|
btn-sm.btn-primary,
|
||||||
|
@ -218,6 +218,9 @@ a:hover {
|
||||||
.text-primary {
|
.text-primary {
|
||||||
color: #23536f;
|
color: #23536f;
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.fixed-table-container tbody .selected td {
|
.fixed-table-container tbody .selected td {
|
||||||
background-color: #fff8af;
|
background-color: #fff8af;
|
||||||
}
|
}
|
||||||
|
|
5
public/css/dist/skins/skin-blue.min.css
vendored
5
public/css/dist/skins/skin-blue.min.css
vendored
|
@ -123,7 +123,7 @@
|
||||||
border-bottom-left-radius: 0;
|
border-bottom-left-radius: 0;
|
||||||
}
|
}
|
||||||
.skin-blue.layout-top-nav .main-header > .logo .logo-variant {
|
.skin-blue.layout-top-nav .main-header > .logo .logo-variant {
|
||||||
background-color: none;
|
background-color: unset;
|
||||||
}
|
}
|
||||||
.btn.btn-primary,
|
.btn.btn-primary,
|
||||||
btn-sm.btn-primary,
|
btn-sm.btn-primary,
|
||||||
|
@ -218,6 +218,9 @@ a:hover {
|
||||||
.text-primary {
|
.text-primary {
|
||||||
color: #23536f;
|
color: #23536f;
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.fixed-table-container tbody .selected td {
|
.fixed-table-container tbody .selected td {
|
||||||
background-color: #fff8af;
|
background-color: #fff8af;
|
||||||
}
|
}
|
||||||
|
|
3
public/css/dist/skins/skin-green-dark.css
vendored
3
public/css/dist/skins/skin-green-dark.css
vendored
|
@ -205,6 +205,9 @@ a:visited {
|
||||||
.bootstrap-table .fixed-table-container .table thead th .sortable {
|
.bootstrap-table .fixed-table-container .table thead th .sortable {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.thead,
|
.thead,
|
||||||
.navbar-nav > li > a:link {
|
.navbar-nav > li > a:link {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
|
|
|
@ -205,6 +205,9 @@ a:visited {
|
||||||
.bootstrap-table .fixed-table-container .table thead th .sortable {
|
.bootstrap-table .fixed-table-container .table thead th .sortable {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.thead,
|
.thead,
|
||||||
.navbar-nav > li > a:link {
|
.navbar-nav > li > a:link {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
|
|
3
public/css/dist/skins/skin-green.css
vendored
3
public/css/dist/skins/skin-green.css
vendored
|
@ -195,6 +195,9 @@ a:visited {
|
||||||
.text-primary {
|
.text-primary {
|
||||||
color: #004023;
|
color: #004023;
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.fixed-table-container tbody .selected td {
|
.fixed-table-container tbody .selected td {
|
||||||
background-color: #fff8af;
|
background-color: #fff8af;
|
||||||
}
|
}
|
||||||
|
|
3
public/css/dist/skins/skin-green.min.css
vendored
3
public/css/dist/skins/skin-green.min.css
vendored
|
@ -195,6 +195,9 @@ a:visited {
|
||||||
.text-primary {
|
.text-primary {
|
||||||
color: #004023;
|
color: #004023;
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.fixed-table-container tbody .selected td {
|
.fixed-table-container tbody .selected td {
|
||||||
background-color: #fff8af;
|
background-color: #fff8af;
|
||||||
}
|
}
|
||||||
|
|
3
public/css/dist/skins/skin-orange-dark.css
vendored
3
public/css/dist/skins/skin-orange-dark.css
vendored
|
@ -196,6 +196,9 @@ li.dropdown-item-marker {
|
||||||
background: linear-gradient(to bottom, var(--header) 0%, var(--header) 100%);
|
background: linear-gradient(to bottom, var(--header) 0%, var(--header) 100%);
|
||||||
border-color: var(--header);
|
border-color: var(--header);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.bootstrap-table .fixed-table-container .table thead th .sortable {
|
.bootstrap-table .fixed-table-container .table thead th .sortable {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
|
|
@ -196,6 +196,9 @@ li.dropdown-item-marker {
|
||||||
background: linear-gradient(to bottom, var(--header) 0%, var(--header) 100%);
|
background: linear-gradient(to bottom, var(--header) 0%, var(--header) 100%);
|
||||||
border-color: var(--header);
|
border-color: var(--header);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.bootstrap-table .fixed-table-container .table thead th .sortable {
|
.bootstrap-table .fixed-table-container .table thead th .sortable {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
|
3
public/css/dist/skins/skin-orange.css
vendored
3
public/css/dist/skins/skin-orange.css
vendored
|
@ -190,6 +190,9 @@ a.btn-warning:visited,
|
||||||
a.btn-danger:visited {
|
a.btn-danger:visited {
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.fixed-table-container tbody .selected td {
|
.fixed-table-container tbody .selected td {
|
||||||
background-color: #fff8af;
|
background-color: #fff8af;
|
||||||
}
|
}
|
||||||
|
|
3
public/css/dist/skins/skin-orange.min.css
vendored
3
public/css/dist/skins/skin-orange.min.css
vendored
|
@ -190,6 +190,9 @@ a.btn-warning:visited,
|
||||||
a.btn-danger:visited {
|
a.btn-danger:visited {
|
||||||
color: #FFF;
|
color: #FFF;
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.fixed-table-container tbody .selected td {
|
.fixed-table-container tbody .selected td {
|
||||||
background-color: #fff8af;
|
background-color: #fff8af;
|
||||||
}
|
}
|
||||||
|
|
3
public/css/dist/skins/skin-purple-dark.css
vendored
3
public/css/dist/skins/skin-purple-dark.css
vendored
|
@ -223,6 +223,9 @@ a:visited {
|
||||||
a:link {
|
a:link {
|
||||||
color: var(--link);
|
color: var(--link);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.btn-primary.hover {
|
.btn-primary.hover {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
|
|
@ -223,6 +223,9 @@ a:visited {
|
||||||
a:link {
|
a:link {
|
||||||
color: var(--link);
|
color: var(--link);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.btn-primary.hover {
|
.btn-primary.hover {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
|
3
public/css/dist/skins/skin-purple.css
vendored
3
public/css/dist/skins/skin-purple.css
vendored
|
@ -196,6 +196,9 @@ a.btn-danger:visited {
|
||||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||||
background-color: #605ca8;
|
background-color: #605ca8;
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.search-highlight,
|
.search-highlight,
|
||||||
.search-highlight:hover {
|
.search-highlight:hover {
|
||||||
background-color: #e9d15b;
|
background-color: #e9d15b;
|
||||||
|
|
3
public/css/dist/skins/skin-purple.min.css
vendored
3
public/css/dist/skins/skin-purple.min.css
vendored
|
@ -196,6 +196,9 @@ a.btn-danger:visited {
|
||||||
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
.select2-container--default .select2-selection--multiple .select2-selection__choice {
|
||||||
background-color: #605ca8;
|
background-color: #605ca8;
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.search-highlight,
|
.search-highlight,
|
||||||
.search-highlight:hover {
|
.search-highlight:hover {
|
||||||
background-color: #e9d15b;
|
background-color: #e9d15b;
|
||||||
|
|
3
public/css/dist/skins/skin-red-dark.css
vendored
3
public/css/dist/skins/skin-red-dark.css
vendored
|
@ -226,6 +226,9 @@ a:visited {
|
||||||
a:hover {
|
a:hover {
|
||||||
color: var(--hover-link);
|
color: var(--hover-link);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.btn-primary.hover {
|
.btn-primary.hover {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
|
3
public/css/dist/skins/skin-red-dark.min.css
vendored
3
public/css/dist/skins/skin-red-dark.min.css
vendored
|
@ -226,6 +226,9 @@ a:visited {
|
||||||
a:hover {
|
a:hover {
|
||||||
color: var(--hover-link);
|
color: var(--hover-link);
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
.btn-primary.hover {
|
.btn-primary.hover {
|
||||||
color: var(--nav-link);
|
color: var(--nav-link);
|
||||||
}
|
}
|
||||||
|
|
3
public/css/dist/skins/skin-red.css
vendored
3
public/css/dist/skins/skin-red.css
vendored
|
@ -207,4 +207,7 @@ a.btn-danger:visited {
|
||||||
.search-highlight:hover {
|
.search-highlight:hover {
|
||||||
background-color: #e9d15b;
|
background-color: #e9d15b;
|
||||||
}
|
}
|
||||||
|
.far fa-life-ring {
|
||||||
|
color: var(--link);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Reference in a new issue