Compare commits
209 Commits
Author | SHA1 | Date | |
---|---|---|---|
|
62774ab042 | ||
|
a772052845 | ||
|
fecc761eeb | ||
|
6fb1e93423 | ||
|
593a571725 | ||
|
3dffc3339c | ||
|
a5b1c47785 | ||
|
b229387b78 | ||
|
3db6ccda2d | ||
|
05181ad9b2 | ||
|
21f9320cef | ||
|
0f7c2214f0 | ||
|
34308491c6 | ||
|
45579d6df3 | ||
|
50b4cb972f | ||
|
b61e892b67 | ||
|
f7954a994b | ||
|
e07a0b0cca | ||
|
befa9a5c25 | ||
|
1543d57f7b | ||
|
431d275ff6 | ||
|
726a45aabb | ||
|
a4202850f6 | ||
|
1cfe3445f6 | ||
|
0090b87c48 | ||
|
26476df490 | ||
|
95590bd889 | ||
|
413e198dff | ||
|
40b6699d04 | ||
|
77ecf62ec5 | ||
|
26086acf8d | ||
|
e4ead1d97e | ||
|
13788c92df | ||
|
1ce1e00f9c | ||
|
2efdd288eb | ||
|
f69189043f | ||
|
b8d1d2b4b7 | ||
|
60f454d930 | ||
|
379d51d557 | ||
|
60241df28c | ||
|
ef65d80a5b | ||
|
a21ce4c5c1 | ||
|
459b483a8e | ||
|
28216c28e0 | ||
|
d633415531 | ||
|
5335d82f61 | ||
|
85f842587b | ||
|
a680efad94 | ||
|
00a5ef480e | ||
|
39eef6623a | ||
|
a6d8107a97 | ||
|
7a3addc00f | ||
|
c270716deb | ||
|
a62c3f6cd8 | ||
|
bcb7f6b3ac | ||
|
3e0b4caa6b | ||
|
97037033ae | ||
|
e8dc034b40 | ||
|
877c6706c4 | ||
|
197eaf38dd | ||
|
e96a8e1f6c | ||
|
8e4e95597a | ||
|
146055541f | ||
|
f8c2a7bc79 | ||
|
67bff29e3f | ||
|
9f98271e2a | ||
|
db5542de00 | ||
|
d59c2d3e02 | ||
|
0686f9d001 | ||
|
015561d973 | ||
|
12b66baebe | ||
|
8cc114bbf4 | ||
|
413d0009c4 | ||
|
e8035718b9 | ||
|
8d58d1604f | ||
|
60a7113023 | ||
|
6d219e70b4 | ||
|
bede08c00c | ||
|
4741b9310c | ||
|
98fe877830 | ||
|
bb9b0f1623 | ||
|
f1eae498b9 | ||
|
86817db14c | ||
|
cb511413e9 | ||
|
12e3dbe9f4 | ||
|
0bb22d0c52 | ||
|
e22ae2819f | ||
|
b90aa79795 | ||
|
fc23f94ed1 | ||
|
baced8f780 | ||
|
b30691595d | ||
|
100ed67c53 | ||
|
2b36eb3f1f | ||
|
ff13552c96 | ||
|
80e8dc94fb | ||
|
864fecaaff | ||
|
439c73c89f | ||
|
ce89f1dd9d | ||
|
b6668c6811 | ||
|
5dff4cd65a | ||
|
37fd064fa4 | ||
|
d16cfb8b4e | ||
|
2db28a3119 | ||
|
535c6ab96b | ||
|
c372da6971 | ||
|
2b59c32ad6 | ||
|
15c1c95bc0 | ||
|
85922be11e | ||
|
0514ee464a | ||
|
63b9ba38cb | ||
|
b75d1db867 | ||
|
531bb954d6 | ||
|
c5649b80e9 | ||
|
090fc87859 | ||
|
5a3f81e250 | ||
|
c542e5b2c1 | ||
|
d8d55d7d94 | ||
|
33b4343dd4 | ||
|
92c430a817 | ||
|
7051aeda83 | ||
|
78ea929c93 | ||
|
bfcccd0139 | ||
|
17c3605794 | ||
|
d2da68bc6c | ||
|
55bcadedff | ||
|
264cb754cd | ||
|
12e25d04d3 | ||
|
9547c3baec | ||
|
66dac6ff6d | ||
|
4990d4043a | ||
|
80fe545626 | ||
|
d3d1de6964 | ||
|
2f450e7026 | ||
|
3aa038ce05 | ||
|
254d45f747 | ||
|
a02e1e8a99 | ||
|
da22108ffd | ||
|
89aeb0b007 | ||
|
23f7a84649 | ||
|
b32852cf3c | ||
|
2d9b90e48c | ||
|
f0f87dbb11 | ||
|
77af028107 | ||
|
14c02b1c34 | ||
|
0b1af9db48 | ||
|
bb3d3d7ef3 | ||
|
f49ba2fb2d | ||
|
e1e6452b3a | ||
|
768d746cbf | ||
|
d4ac785b1b | ||
|
89adda8adf | ||
|
5c19c03a62 | ||
|
ef851d005f | ||
|
f4285a7531 | ||
|
7aba2af0f7 | ||
|
7b5055c02c | ||
|
86dd435903 | ||
|
66d12bef13 | ||
|
cc736b2209 | ||
|
34887272ed | ||
|
8e01d342a8 | ||
|
462d9dbff2 | ||
|
6db97b0f7f | ||
|
4474cccf30 | ||
|
17fa29c54f | ||
|
86adcbd8dd | ||
|
d2b68fbd58 | ||
|
abb1730a88 | ||
|
19b24d96a8 | ||
|
c558491bc8 | ||
|
2337be155c | ||
|
c3b04f60d5 | ||
|
aa6ed69015 | ||
|
1acc60f95c | ||
|
c5717814eb | ||
|
843a1df862 | ||
|
e7d16478b3 | ||
|
d4509691bc | ||
|
e84133ddd7 | ||
|
2070a17835 | ||
|
a1721def37 | ||
|
c92340649e | ||
|
a768d01dbe | ||
|
c3b199361c | ||
|
4b919f8a9b | ||
|
5a88beaf64 | ||
|
e151729cd8 | ||
|
be9a996928 | ||
|
9b60229f14 | ||
|
07dbcccc83 | ||
|
eea193ae5c | ||
|
72d2f1bb74 | ||
|
b97ba745a5 | ||
|
46e1c2027e | ||
|
bb9bced18b | ||
|
c5f4f17449 | ||
|
b9902e3fa0 | ||
|
93c2c77f6b | ||
|
d6af666230 | ||
|
beb262871e | ||
|
a7c15ce36f | ||
|
2f86b16491 | ||
|
eb62c7c53c | ||
|
bfba50aa8e | ||
|
b4bf81fe3c | ||
|
80eaea069e | ||
|
5854db4205 | ||
|
c3aa2b5282 | ||
|
69caa99c90 |
36
.devcontainer/devcontainer.json
Normal file
@ -0,0 +1,36 @@
|
||||
// For format details, see https://aka.ms/devcontainer.json. For config options, see the
|
||||
// README at: https://github.com/devcontainers/templates/tree/main/src/javascript-node
|
||||
{
|
||||
"name": "Dashy",
|
||||
// Or use a Dockerfile or Docker Compose file. More info: https://containers.dev/guide/dockerfile
|
||||
"image": "mcr.microsoft.com/devcontainers/javascript-node:1-18-bullseye",
|
||||
"customizations": {
|
||||
"vscode": {
|
||||
"extensions": [
|
||||
"Vue.volar",
|
||||
"dbaeumer.vscode-eslint",
|
||||
"ms-azuretools.vscode-docker",
|
||||
"ms-edgedevtools.vscode-edge-devtools",
|
||||
"firefox-devtools.vscode-firefox-debug",
|
||||
"aaravb.chrome-extension-developer-tools"
|
||||
]
|
||||
}
|
||||
},
|
||||
|
||||
// Features to add to the dev container. More info: https://containers.dev/features.
|
||||
"features": {
|
||||
"ghcr.io/devcontainers/features/github-cli:1": {}
|
||||
},
|
||||
|
||||
// Use 'forwardPorts' to make a list of ports inside the container available locally.
|
||||
// "forwardPorts": [],
|
||||
|
||||
// Use 'postCreateCommand' to run commands after the container is created.
|
||||
"postCreateCommand": "yarn install --ignore-engines --immutable --no-cache --network-timeout 300000 --network-concurrency 1"
|
||||
|
||||
// Configure tool-specific properties.
|
||||
// "customizations": {},
|
||||
|
||||
// Uncomment to connect as root instead. More info: https://aka.ms/dev-containers-non-root.
|
||||
// "remoteUser": "root"
|
||||
}
|
2
.github/ISSUE_TEMPLATE/bug.yml
vendored
@ -3,7 +3,7 @@ description: Report something that's not working the way it's (probably) intende
|
||||
title: '[BUG] <title>'
|
||||
labels: ['🐛 Bug']
|
||||
assignees:
|
||||
- lissy93
|
||||
- Lissy93
|
||||
body:
|
||||
- type: dropdown
|
||||
id: environment
|
||||
|
4
.github/ISSUE_TEMPLATE/feature-request.yml
vendored
@ -2,6 +2,8 @@ name: Feature Request ✨
|
||||
description: Suggest an idea for future development of Dashy
|
||||
title: '[FEATURE_REQUEST] <title>'
|
||||
labels: ['🦄 Feature Request']
|
||||
assignees:
|
||||
- Lissy93
|
||||
|
||||
body:
|
||||
|
||||
@ -59,4 +61,4 @@ body:
|
||||
Please note that there is no guarantee that your idea will be implemented
|
||||
If you haven't already done so, please Star the Dashy's repository on GitHub, to help other users discover it
|
||||
validations:
|
||||
required: false
|
||||
required: false
|
||||
|
2
.github/ISSUE_TEMPLATE/question.yml
vendored
@ -2,6 +2,8 @@ name: Question 🤷♂️
|
||||
description: Got a question about Dashy, deployment, development or usage?
|
||||
title: '[QUESTION] <title>'
|
||||
labels: ['🤷♂️ Question']
|
||||
assignees:
|
||||
- Lissy93
|
||||
|
||||
body:
|
||||
# Filed 1 - Intro Text
|
||||
|
4
.github/ISSUE_TEMPLATE/showcase-addition.yml
vendored
@ -2,6 +2,8 @@ name: Add your Dashboard to the Showcase 🌟
|
||||
description: Share a screenshot of your dashboard to the Readme showcase!
|
||||
title: '[SHOWCASE] <title>'
|
||||
labels: ['💯 Showcase']
|
||||
assignees:
|
||||
- lissy93
|
||||
|
||||
body:
|
||||
# 1 - Title
|
||||
@ -55,4 +57,4 @@ body:
|
||||
## That's It!
|
||||
Thanks for sharing your dashboard :) You will receive an update to this ticket once it's added to the showcase
|
||||
validations:
|
||||
required: false
|
||||
required: false
|
||||
|
12
.github/dependabot.yml
vendored
Normal file
@ -0,0 +1,12 @@
|
||||
# To get started with Dependabot version updates, you'll need to specify which
|
||||
# package ecosystems to update and where the package manifests are located.
|
||||
# Please see the documentation for more information:
|
||||
# https://docs.github.com/github/administering-a-repository/configuration-options-for-dependency-updates
|
||||
# https://containers.dev/guide/dependabot
|
||||
|
||||
version: 2
|
||||
updates:
|
||||
- package-ecosystem: "devcontainers"
|
||||
directory: "/"
|
||||
schedule:
|
||||
interval: weekly
|
7
.github/pull_request_template.md
vendored
@ -1,4 +1,7 @@
|
||||
*Thank you for contributing to Dashy! So that your PR can be handled effectively, please populate the following fields (delete sections that are not applicable)*
|
||||
<!--
|
||||
Thank you for contributing to Dashy!
|
||||
So that your PR can be handled effectively, please populate the following fields
|
||||
-->
|
||||
|
||||
**Category**:
|
||||
> One of: Bugfix / Feature / Code style update / Refactoring Only / Build related changes / Documentation / Other (please specify)
|
||||
@ -20,5 +23,5 @@
|
||||
- [ ] There are no (new) build warnings or errors
|
||||
- [ ] _(If a new config option is added)_ Attribute is outlined in the schema and documented
|
||||
- [ ] _(If a new dependency is added)_ Package is essential, and has been checked out for security or performance
|
||||
- [ ] Bumps version, if new feature added
|
||||
- [ ] _(If significant change)_ Bumps version in package.json
|
||||
|
||||
|
44
.github/workflows/auto-tag-pr.yml
vendored
@ -1,44 +0,0 @@
|
||||
# Creates a new tag, whenever the app version (in package.json) is updated in master
|
||||
# And marks any relevant issues as fixed
|
||||
name: 🏗️ Release Tag new Versions
|
||||
on:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
jobs:
|
||||
tag-pre-release:
|
||||
runs-on: ubuntu-latest
|
||||
permissions:
|
||||
contents: write
|
||||
outputs:
|
||||
tag: ${{ steps.autotag.outputs.tagname }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: butlerlogic/action-autotag@stable
|
||||
id: autotag
|
||||
with:
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
strategy: package
|
||||
commit_message_template: "🔖 {{number}} {{message}} (by {{author}})\nSHA: {{sha}}\n."
|
||||
github-release:
|
||||
runs-on: ubuntu-latest
|
||||
needs: tag-pre-release
|
||||
if: ${{ needs.tag-pre-release.outputs.tag }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- uses: ncipollo/release-action@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag: ${{ needs.tag-pre-release.outputs.tag }}
|
||||
bodyFile: ".github/LATEST_CHANGELOG.md"
|
||||
mark-issue-fixed:
|
||||
runs-on: ubuntu-latest
|
||||
if: ${{ github.event_name == 'issues' }}
|
||||
steps:
|
||||
- uses: actions/checkout@v2
|
||||
- name: Label Fixed Issues
|
||||
uses: gh-bot/fix-labeler@master
|
||||
with:
|
||||
token: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
label: '✅ Fixed'
|
55
.github/workflows/create-tag-for-version.yml
vendored
Normal file
@ -0,0 +1,55 @@
|
||||
# When Dashy's version in package.json is updated
|
||||
# this workflow will create a new tag
|
||||
# And then publish it to the repository
|
||||
name: 🏗️ Tag on Version Change
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches:
|
||||
- master
|
||||
paths:
|
||||
- 'package.json'
|
||||
|
||||
jobs:
|
||||
tag-if-version-updated:
|
||||
runs-on: ubuntu-latest
|
||||
|
||||
steps:
|
||||
- name: Check Out Repository 🛎️
|
||||
uses: actions/checkout@v2
|
||||
|
||||
- name: Set Up Python 🐍
|
||||
uses: actions/setup-python@v4
|
||||
with:
|
||||
python-version: '3.x'
|
||||
|
||||
- name: Extract Version from package.json 🔢
|
||||
id: package_version
|
||||
run: |
|
||||
import json
|
||||
with open('package.json', 'r') as f:
|
||||
version = json.load(f)['version']
|
||||
print(f"::set-output name=VERSION::{version}")
|
||||
shell: python
|
||||
|
||||
- name: Get Latest Tag 🏷️
|
||||
id: latest_tag
|
||||
run: |
|
||||
git fetch --tags
|
||||
latest_tag=$(git describe --tags `git rev-list --tags --max-count=1` 2>/dev/null)
|
||||
echo "::set-output name=TAG::${latest_tag:-0}"
|
||||
|
||||
- name: Create and Push Tag ⤴️
|
||||
if: steps.package_version.outputs.VERSION != steps.latest_tag.outputs.TAG && steps.latest_tag.outputs.TAG != '0'
|
||||
run: |
|
||||
git config --local user.email "liss-bot@d0h.co"
|
||||
git config --local user.name "Liss-Bot"
|
||||
git tag -a ${{ steps.package_version.outputs.VERSION }} -m "Release v${{ steps.package_version.outputs.VERSION }}"
|
||||
git push origin ${{ steps.package_version.outputs.VERSION }}
|
||||
env:
|
||||
GIT_AUTHOR_NAME: Liss-Bot
|
||||
GIT_AUTHOR_EMAIL: liss-bot@d0h.co
|
||||
GIT_COMMITTER_NAME: Liss-Bot
|
||||
GIT_COMMITTER_EMAIL: liss-bot@d0h.co
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
25
.github/workflows/docker-build-publish.yml
vendored
@ -1,11 +1,10 @@
|
||||
# Scans, builds and releases a multi-architecture docker image
|
||||
name: 🐳 Build + Publish Multi-Platform Image
|
||||
|
||||
on:
|
||||
workflow_dispatch:
|
||||
push:
|
||||
branches: ['master']
|
||||
tags: [v*]
|
||||
tags: ['*.*']
|
||||
paths:
|
||||
- '**.js'
|
||||
- 'src/**'
|
||||
@ -33,7 +32,7 @@ jobs:
|
||||
|
||||
steps:
|
||||
- name: 🛎️ Checkout Repo
|
||||
uses: actions/checkout@v2
|
||||
uses: actions/checkout@v3
|
||||
|
||||
- name: 🔖 Get App Version
|
||||
uses: tyankatsu0105/read-package-version-actions@v1
|
||||
@ -47,8 +46,12 @@ jobs:
|
||||
${{ env.DH_IMAGE }}
|
||||
ghcr.io/${{ env.GH_IMAGE }}
|
||||
tags: |
|
||||
type=ref,event=tag,prefix=release-,suffix={{tag}}
|
||||
type=semver,pattern={{raw}},value=${{ steps.package-version.outputs.version }}
|
||||
type=ref,event=tag
|
||||
type=semver,pattern={{version}},enable=false
|
||||
type=semver,pattern={{major}}.x
|
||||
type=raw,value=latest
|
||||
flavor: |
|
||||
latest=false
|
||||
labels: |
|
||||
maintainer=Lissy93
|
||||
org.opencontainers.image.title=Dashy
|
||||
@ -63,10 +66,10 @@ jobs:
|
||||
platforms: linux/amd64,linux/arm64,linux/arm/v7
|
||||
|
||||
- name: 🔧 Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v1
|
||||
id: buildx
|
||||
uses: docker/setup-buildx-action@v2
|
||||
with:
|
||||
driver-opts: image=moby/buildkit:v0.10.6
|
||||
use-buildkit: true
|
||||
buildkit-daemon-opts: "--oci-worker-no-process-sandbox"
|
||||
|
||||
- name: 👀 Inspect builder
|
||||
run: |
|
||||
@ -77,13 +80,13 @@ jobs:
|
||||
echo "Platforms: ${{ steps.buildx.outputs.platforms }}"
|
||||
|
||||
- name: 🔑 Login to DockerHub
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
username: ${{ secrets.DOCKER_USERNAME }}
|
||||
password: ${{ secrets.DOCKER_PASSWORD }}
|
||||
|
||||
- name: 🔑 Login to GitHub Container Registry
|
||||
uses: docker/login-action@v1
|
||||
uses: docker/login-action@v2
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
@ -93,7 +96,7 @@ jobs:
|
||||
uses: crazy-max/ghaction-docker-status@v1
|
||||
|
||||
- name: ⚒️ Build and push
|
||||
uses: docker/build-push-action@v2
|
||||
uses: docker/build-push-action@v3
|
||||
with:
|
||||
context: .
|
||||
file: ./Dockerfile
|
||||
|
36
.github/workflows/draft-release.yml
vendored
Normal file
@ -0,0 +1,36 @@
|
||||
name: 🏗️ Draft New Release
|
||||
|
||||
on:
|
||||
push:
|
||||
tags:
|
||||
- '^[0-9]+\.[0-9]+\.[0-9]+$'
|
||||
- '**'
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: 'Tag to draft a release for (must already exist)'
|
||||
required: true
|
||||
|
||||
jobs:
|
||||
create-draft-release:
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout code 🛎️
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
fetch-depth: 0 # We need all history for generating release notes
|
||||
|
||||
- name: Create Draft Release 📝
|
||||
id: create_release
|
||||
uses: actions/create-release@v1
|
||||
env:
|
||||
GITHUB_TOKEN: ${{ secrets.BOT_GITHUB_TOKEN || secrets.GITHUB_TOKEN }}
|
||||
with:
|
||||
tag_name: ${{ github.event.inputs.tag || github.ref_name }}
|
||||
release_name: Release ${{ github.event.inputs.tag || github.ref_name }}
|
||||
draft: true
|
||||
prerelease: false
|
||||
generate_release_notes: true
|
||||
|
||||
- name: Output new release URL ↗️
|
||||
run: 'echo "Draft release URL: ${{ steps.create_release.outputs.html_url }}"'
|
1
.gitignore
vendored
@ -13,7 +13,6 @@ yarn-error.log*
|
||||
|
||||
# Editor directories and files
|
||||
.idea
|
||||
.vscode
|
||||
*.suo
|
||||
*.ntvs*
|
||||
*.njsproj
|
||||
|
65
.vscode/launch.json
vendored
Normal file
@ -0,0 +1,65 @@
|
||||
{
|
||||
// Use IntelliSense to learn about possible attributes.
|
||||
// Hover to view descriptions of existing attributes.
|
||||
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
|
||||
"version": "0.2.0",
|
||||
"configurations": [
|
||||
{
|
||||
"type": "msedge",
|
||||
"request": "launch",
|
||||
"name": "dashy: edge",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"breakOnLoad": true,
|
||||
"pathMapping": {
|
||||
"/_karma_webpack_": "${workspaceFolder}"
|
||||
},
|
||||
"sourceMapPathOverrides": {
|
||||
"webpack:/*": "${webRoot}/*",
|
||||
"/./*": "${webRoot}/*",
|
||||
"/src/*": "${webRoot}/*",
|
||||
"/*": "*",
|
||||
"/./~/*": "${webRoot}/node_modules/*"
|
||||
},
|
||||
"preLaunchTask": "dashy start"
|
||||
},
|
||||
{
|
||||
"type": "chrome",
|
||||
"request": "launch",
|
||||
"name": "dashy: chrome",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"breakOnLoad": true,
|
||||
"pathMapping": {
|
||||
"/_karma_webpack_": "${workspaceFolder}"
|
||||
},
|
||||
"sourceMapPathOverrides": {
|
||||
"webpack:/*": "${webRoot}/*",
|
||||
"/./*": "${webRoot}/*",
|
||||
"/src/*": "${webRoot}/*",
|
||||
"/*": "*",
|
||||
"/./~/*": "${webRoot}/node_modules/*"
|
||||
},
|
||||
"preLaunchTask": "dashy start"
|
||||
},
|
||||
{
|
||||
"type": "firefox",
|
||||
"request": "launch",
|
||||
"name": "dashy: firefox",
|
||||
"url": "http://localhost:8080",
|
||||
"webRoot": "${workspaceFolder}",
|
||||
"breakOnLoad": true,
|
||||
"pathMapping": {
|
||||
"/_karma_webpack_": "${workspaceFolder}"
|
||||
},
|
||||
"sourceMapPathOverrides": {
|
||||
"webpack:/*": "${webRoot}/*",
|
||||
"/./*": "${webRoot}/*",
|
||||
"/src/*": "${webRoot}/*",
|
||||
"/*": "*",
|
||||
"/./~/*": "${webRoot}/node_modules/*"
|
||||
},
|
||||
"preLaunchTask": "dashy start"
|
||||
}
|
||||
]
|
||||
}
|
21
.vscode/tasks.json
vendored
Normal file
@ -0,0 +1,21 @@
|
||||
{
|
||||
"version": "2.0.0",
|
||||
"tasks": [
|
||||
{
|
||||
"label": "dashy start",
|
||||
"type": "npm",
|
||||
"script": "dev",
|
||||
"isBackground": true,
|
||||
"problemMatcher": [
|
||||
{
|
||||
"base": "$tsc-watch",
|
||||
"background": {
|
||||
"activeOnStart": true,
|
||||
"beginsPattern": "Starting development server",
|
||||
"endsPattern": "Compiled successfully"
|
||||
}
|
||||
}
|
||||
],
|
||||
}
|
||||
]
|
||||
}
|
@ -22,7 +22,7 @@ RUN yarn install --ignore-engines --immutable --no-cache --network-timeout 30000
|
||||
COPY . ./
|
||||
|
||||
# Build initial app for production
|
||||
RUN yarn build --mode production
|
||||
RUN yarn build --mode production --no-clean
|
||||
|
||||
# Production stage
|
||||
FROM node:20.11.1-alpine3.19
|
||||
@ -42,7 +42,7 @@ RUN apk add --no-cache tzdata
|
||||
COPY --from=BUILD_IMAGE /app ./
|
||||
|
||||
# Finally, run start command to serve up the built application
|
||||
CMD [ "yarn", "start" ]
|
||||
CMD [ "yarn", "build-and-start" ]
|
||||
|
||||
# Expose the port
|
||||
EXPOSE ${PORT}
|
||||
|
113
README.md
@ -241,7 +241,7 @@ Status indicators can be globally enabled by setting `appConfig.statusCheck: tru
|
||||
|
||||
> For full widget documentation, see: [**Widgets**](./docs/widgets.md)
|
||||
|
||||
You can display dynamic content from services in the form of widgets. There are several pre-built widgets availible for showing useful info, and integrations with commonly self-hosted services, but you can also easily create your own for almost any app.
|
||||
You can display dynamic content from services in the form of widgets. There are several pre-built widgets available for showing useful info, and integrations with commonly self-hosted services, but you can also easily create your own for almost any app.
|
||||
|
||||
|
||||
<p align="center">
|
||||
@ -526,48 +526,19 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/undefined">
|
||||
<img src="" width="80;" alt="undefined"/>
|
||||
<br />
|
||||
<sub><b>Undefined</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/koconder">
|
||||
<img src="https://avatars.githubusercontent.com/u/25068?u=582657b23622aaa3dfe68bd028a780f272f456fa&v=4" width="80;" alt="koconder"/>
|
||||
<a href="https://github.com/vincentkoc">
|
||||
<img src="https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4" width="80;" alt="vincentkoc"/>
|
||||
<br />
|
||||
<sub><b>Vincent Koc</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Admonstrator">
|
||||
<img src="https://avatars.githubusercontent.com/u/69824?u=1e226d7a36cdd661c3e4cd486fea140d045b7d57&v=4" width="80;" alt="Admonstrator"/>
|
||||
<br />
|
||||
<sub><b>Aaron Viehl</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/tbjers">
|
||||
<img src="https://avatars.githubusercontent.com/u/1117052?v=4" width="80;" alt="tbjers"/>
|
||||
<br />
|
||||
<sub><b>Torgny Bjers</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/emlazzarin">
|
||||
<img src="https://avatars.githubusercontent.com/u/1141361?u=714e3487a3f2e0df721b01a0133945f075d3ff68&v=4" width="80;" alt="emlazzarin"/>
|
||||
<br />
|
||||
<sub><b>Eddy Lazzarin</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/AnandChowdhary">
|
||||
<img src="https://avatars.githubusercontent.com/u/2841780?u=747e554b3a7f12eb20b7910e1c87d817844f714f&v=4" width="80;" alt="AnandChowdhary"/>
|
||||
<br />
|
||||
<sub><b>Anand Chowdhary</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/shrippen">
|
||||
<img src="https://avatars.githubusercontent.com/u/2873570?v=4" width="80;" alt="shrippen"/>
|
||||
@ -595,7 +566,8 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
||||
<br />
|
||||
<sub><b>Digital Archeology</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/InDieTasten">
|
||||
<img src="https://avatars.githubusercontent.com/u/7047377?u=8d8f8017628b38bc46dcbf3620e194b01d3fb2d1&v=4" width="80;" alt="InDieTasten"/>
|
||||
@ -609,8 +581,7 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
||||
<br />
|
||||
<sub><b>Araguaci</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/bmcgonag">
|
||||
<img src="https://avatars.githubusercontent.com/u/7346620?u=2a0f9284f3e12ac1cc15288c254d1ec68a5081e8&v=4" width="80;" alt="bmcgonag"/>
|
||||
@ -619,10 +590,17 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/vlad-timofeev">
|
||||
<img src="https://avatars.githubusercontent.com/u/11474041?u=eee43705b54d2ec9f51fc4fcce5ad18dd17c87e4&v=4" width="80;" alt="vlad-timofeev"/>
|
||||
<a href="https://github.com/arcestia">
|
||||
<img src="https://avatars.githubusercontent.com/u/7936962?u=afc43f878a0858cae75418f18d9696d65ebd53f9&v=4" width="80;" alt="arcestia"/>
|
||||
<br />
|
||||
<sub><b>Vlad Timofeev</b></sub>
|
||||
<sub><b>Laurensius Jeffrey</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/vlad-tim">
|
||||
<img src="https://avatars.githubusercontent.com/u/11474041?u=eee43705b54d2ec9f51fc4fcce5ad18dd17c87e4&v=4" width="80;" alt="vlad-tim"/>
|
||||
<br />
|
||||
<sub><b>Vlad</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@ -631,55 +609,34 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
||||
<br />
|
||||
<sub><b>HeliXZz</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/patvdv">
|
||||
<img src="https://avatars.githubusercontent.com/u/12430107?u=e8911c2fb91af4d30432f76da8c40927b2830bd7&v=4" width="80;" alt="patvdv"/>
|
||||
<br />
|
||||
<sub><b>Patrick Van Der Veken</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/plgonzalezrx8">
|
||||
<img src="https://avatars.githubusercontent.com/u/19900049?v=4" width="80;" alt="plgonzalezrx8"/>
|
||||
<br />
|
||||
<sub><b>Pedro Gonzalez</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/mryesiller">
|
||||
<img src="https://avatars.githubusercontent.com/u/24632172?u=0d20f2d615158f87cd60a3398d3efb026c32f291&v=4" width="80;" alt="mryesiller"/>
|
||||
<br />
|
||||
<sub><b>Göksel Yeşiller</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/allesauseinerhand">
|
||||
<img src="https://avatars.githubusercontent.com/u/32039836?v=4" width="80;" alt="allesauseinerhand"/>
|
||||
<a href="https://github.com/sushibait">
|
||||
<img src="https://avatars.githubusercontent.com/u/26634535?v=4" width="80;" alt="sushibait"/>
|
||||
<br />
|
||||
<sub><b>Allesauseinerhand</b></sub>
|
||||
<sub><b>Shiverme Timbers</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/lamtrinhdev">
|
||||
<img src="https://avatars.githubusercontent.com/u/49742151?u=c5eaca5aa6841a80605cf4f7d0e861a9e6339ef3&v=4" width="80;" alt="lamtrinhdev"/>
|
||||
<a href="https://github.com/undefined">
|
||||
<img src="" width="80;" alt="undefined"/>
|
||||
<br />
|
||||
<sub><b>LamTrinh.Dev</b></sub>
|
||||
<sub><b>Undefined</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Bastii717">
|
||||
<img src="https://avatars.githubusercontent.com/u/53431819?u=604977bed6ad6875ada890d0d3765a4cacc2fa14&v=4" width="80;" alt="Bastii717"/>
|
||||
<a href="https://github.com/OlliVHH">
|
||||
<img src="https://avatars.githubusercontent.com/u/84959562?v=4" width="80;" alt="OlliVHH"/>
|
||||
<br />
|
||||
<sub><b>Bastii717</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/M2TD">
|
||||
<img src="https://avatars.githubusercontent.com/u/85460457?v=4" width="80;" alt="M2TD"/>
|
||||
<br />
|
||||
<sub><b>M2TD</b></sub>
|
||||
<sub><b>HamburgerJung</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@ -690,18 +647,18 @@ Huge thanks to the sponsors helping to support Dashy's development!
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/NixyJuppie">
|
||||
<img src="https://avatars.githubusercontent.com/u/138570196?u=b102c222487905728b858704962d32759df29ebe&v=4" width="80;" alt="NixyJuppie"/>
|
||||
<a href="https://github.com/st617">
|
||||
<img src="https://avatars.githubusercontent.com/u/128325650?v=4" width="80;" alt="st617"/>
|
||||
<br />
|
||||
<sub><b>Nixy</b></sub>
|
||||
<sub><b>St617</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/nrvo">
|
||||
<img src="https://avatars.githubusercontent.com/u/151435968?u=e1dcb307fd0efdc45cddbe9490a7b956e4da6835&v=4" width="80;" alt="nrvo"/>
|
||||
<a href="https://github.com/hudsonrock-partnerships">
|
||||
<img src="https://avatars.githubusercontent.com/u/163282900?u=5f2667f7fe5d284ac7a2da6b0800ea8970b0fcbf&v=4" width="80;" alt="hudsonrock-partnerships"/>
|
||||
<br />
|
||||
<sub><b>Nrvo</b></sub>
|
||||
<sub><b>Hudsonrock-partnerships</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
</table>
|
||||
|
Before Width: | Height: | Size: 30 MiB After Width: | Height: | Size: 36 MiB |
@ -14,6 +14,9 @@
|
||||
- [Deploying Keycloak](#1-deploy-keycloak)
|
||||
- [Setting up Keycloak](#2-setup-keycloak-users)
|
||||
- [Configuring Dashy for Keycloak](#3-enable-keycloak-in-dashy-config-file)
|
||||
- [Toubleshooting Keycloak](#troubleshooting-keycloak)
|
||||
- [OIDC Auth](#oidc)
|
||||
- [authentik](#authentik)
|
||||
- [Alternative Authentication Methods](#alternative-authentication-methods)
|
||||
- [VPN](#vpn)
|
||||
- [IP-Based Access](#ip-based-access)
|
||||
@ -151,7 +154,7 @@ With basic auth, all logic is happening on the client-side, which could mean a s
|
||||
|
||||
If you'd like to protect all your config files from direct access, you can set the `BASIC_AUTH_USERNAME` and `BASIC_AUTH_PASSWORD` environmental variables. You'll then be prompted to enter these credentials when visiting Dashy.
|
||||
|
||||
Then, if you'd like your frontend to automatically log you in, without prompting you for credentials, then also specify `VUE_APP_BASIC_AUTH_USERNAME` and `VUE_APP_BASIC_AUTH_PASSWORD`. This is useful for when you're hosting Dashy on a private server, and you want to prevent unauthorized access to your config files, while still allowing the frontend to access them. Note that a rebuild is required for these changes to take effect.
|
||||
Then, if you'd like your frontend to automatically log you in, without prompting you for credentials (insecure, so only use on a trusted environment), then also specify `VUE_APP_BASIC_AUTH_USERNAME` and `VUE_APP_BASIC_AUTH_PASSWORD`. This is useful for when you're hosting Dashy on a private server, and just want to use auth for user management and to prevent direct access to your config files, while still allowing the frontend to access them. Note that a rebuild is required for these changes to take effect.
|
||||
|
||||
**[⬆️ Back to Top](#authentication)**
|
||||
|
||||
@ -253,6 +256,245 @@ From within the Keycloak console, you can then configure things like time-outs,
|
||||
|
||||
---
|
||||
|
||||
### Troubleshooting Keycloak
|
||||
|
||||
If you encounter issues with your Keycloak setup, follow these steps to troubleshoot and resolve common problems.
|
||||
|
||||
1. Client Authentication Issue
|
||||
Problem: Redirect loop, if client authentication is enabled.
|
||||
Solution: Switch off "client authentication" in "TC clients" -> "Advanced" settings.
|
||||
|
||||
2. Double URL
|
||||
Problem: If you get redirected to "https://dashy.my.domain/#iss=https://keycloak.my.domain/realms/my-realm"
|
||||
Solution: Make sure to turn on "Exclude Issuer From Authentication Response" in "TC clients" -> "Advanced" -> "OpenID Connect Compatibility Modes"
|
||||
|
||||
3. Problems with mutiple Dashy Pages
|
||||
Problem: Refreshing or logging out of dashy results in an "invalid_redirect_uri" error.
|
||||
Solution: In "TC clients" -> "Access settings" -> "Root URL" https://dashy.my.domain/, valid redirect URIs must be /*
|
||||
|
||||
---
|
||||
|
||||
## OIDC
|
||||
|
||||
Dashy also supports using a general [OIDC compatible](https://openid.net/connect/) authentication server. In order to use it, the authentication section needs to be configured:
|
||||
|
||||
```yaml
|
||||
appConfig:
|
||||
auth:
|
||||
enableOidc: true
|
||||
oidc:
|
||||
clientId: [registered client id]
|
||||
endpoint: [OIDC endpoint]
|
||||
scope: [The scope(s) to request from the OIDC provider]
|
||||
```
|
||||
|
||||
Because Dashy is a SPA, a [public client](https://datatracker.ietf.org/doc/html/rfc6749#section-2.1) registration with PKCE is needed.
|
||||
|
||||
An example for Authelia is shared below, but other OIDC systems can be used:
|
||||
|
||||
```yaml
|
||||
identity_providers:
|
||||
oidc:
|
||||
clients:
|
||||
- client_id: dashy
|
||||
client_name: dashy
|
||||
public: true
|
||||
authorization_policy: 'one_factor'
|
||||
require_pkce: true
|
||||
pkce_challenge_method: 'S256'
|
||||
redirect_uris:
|
||||
- https://dashy.local # should point to your dashy endpoint
|
||||
grant_types:
|
||||
- authorization_code
|
||||
scopes:
|
||||
- 'openid'
|
||||
- 'profile'
|
||||
- 'roles'
|
||||
- 'email'
|
||||
- 'groups'
|
||||
```
|
||||
|
||||
Groups and roles will be populated and available for controlling display similar to [Keycloak](#Keycloak) above.
|
||||
|
||||
---
|
||||
|
||||
### authentik
|
||||
|
||||
This documentation is specific to `authentik`, however it may be useful in getting other idP's working with `Dashy`.
|
||||
|
||||
This guide will only walk through the following:
|
||||
* Creating and configuring an OIDC provider
|
||||
* Creating and configuring an application
|
||||
* Assigning groups
|
||||
* Configuring `Dashy` to use the OIDC client
|
||||
* Show quick examples of how to hide/show `pages`, `items`, and `sections` using OIDC groups
|
||||
|
||||
This guide assumes the following:
|
||||
* You have a working instance of `authentik` terminated with SSL
|
||||
* You have a working instance of `Dashy` terminated with SSL
|
||||
* Users and groups are provisioned
|
||||
* You are familiar with how `authentik` works in case you need to do further troubleshooting that is outside the scope of this guide.
|
||||
|
||||
>[!TIP]
|
||||
>It it recommended that you create groups specific for `Dashy`. Groups will allow you to display content based on group membership as well as limiting user access to `Dashy`. If you do not need this functionality, then you can forgo creating specific groups.
|
||||
|
||||
>[!TIP]
|
||||
>You can use the application wizard to create the provider and application at one time. This is the recommended route, but only the manual process will be outlined in this guide.
|
||||
|
||||

|
||||
|
||||
#### 1. Create an OIDC provider
|
||||
|
||||
Login to the admin console for `authentik`. Go to `Applications` > `Providers`. Click `Create`.
|
||||
|
||||

|
||||
|
||||
A dialog box will pop-up, select the `OAuth2/OpenID Provider`. Click `Next`.
|
||||
|
||||

|
||||
|
||||
On the next page of the wizard, set the `Name`, `Authentication flow`, and `Authorization flow`. See example below. Using the `default-provider-authorization-implicit-consent` authorization flow on internal services and `default-provider-authorization-explicit-consent` on external services is a common practice. However, it is fully up to you on how you would like to configure this option. `Implicit` will login directly without user consent, `explicit` will ask if the user approves the service being logged into with their user credentials.
|
||||
|
||||

|
||||
|
||||
Scroll down and configure the `Protocol settings`. Set the `Client type` to `Public`. Add the `Redirect URIs/Origins (RegEx)`. If the site is hosted at `dashy.lan.domain.com`, then you would enter as the example below.
|
||||
|
||||
>[!NOTE]
|
||||
>If you have an internal and external domain for `Dashy`, enter both URI's. Enter each URI on a new line.
|
||||
|
||||

|
||||
|
||||
Scroll down to set the `Signing Key`. It is recommended to use the built in `authentik Self-signed Certificate` here unless you have special needs for your own custom cert.
|
||||
|
||||

|
||||
|
||||
Expand `Advanced protocol settings` then verify the `Scopes` are set to what is highlighted in `white` below. Set the `Subject mode` to `Based on the Users's Email`.
|
||||
|
||||

|
||||
|
||||
Lastly, toggle `Include claims in id_token` to on. Click `Finish` to complete creating the provider.
|
||||
|
||||

|
||||
|
||||
Grab the generated `Client ID` and `OpenID Configuration Issuer` URL by clicking the newly created provider as this will use this later when `Dashy` is configured to use the OIDC auth mechanism. In this tutorial, what was generated is used below. Obviously adjust the `Client ID` that was generated and use your domain here for the `issuer`.
|
||||
```
|
||||
Client ID: pzN9DCMLqHTTatgtYFg50cl0jn1NmCyBC3wreX15
|
||||
OpenID Configuration Issuer: https://auth.domain.com/application/o/dashy/
|
||||
```
|
||||
|
||||
#### 2. Create an application
|
||||
|
||||
Make sure you are still in the `authentik` admin console then go to `Applications` > `Applications`. Click `Create`.
|
||||
|
||||

|
||||
|
||||
Next, it is required to give a user facing `Name`, `Slug` and assign the newly created provider. Use the example below if you have been following the guide. If you have used your own naming, then adjust accordingly. Click `Create` once you are done.
|
||||
|
||||

|
||||
|
||||
>[!TIP]
|
||||
>Open the application in a new tab from the `authentik` user portal and upload a custom icon. You can also enter a user facing `Description` that the user would see.
|
||||
|
||||

|
||||
|
||||
#### 3. *(Optional)* Limiting access via `authentik` with groups
|
||||
|
||||
If you would like to deny `Dashy` access from specific users who are not within `authentik` based groups, you bind them to the application you just created now. `authentik` will deny access to those who are not members of this group or groups. If you want to allow everyone access from your `authentik` instance, skip this step.
|
||||
|
||||
Make sure you are still in the `authentik` admin console then go to `Applications` > `Applications`. Click the newly created `Dashy` application.
|
||||
|
||||

|
||||
|
||||
Click the `Policy/Group/User Bindings` tab at the top, then click `Bind existing policy`. This assumes you have already created the groups you want to use for `Dashy` and populated users in those groups.
|
||||
|
||||

|
||||
|
||||
Click `Group` for the binding type. Under `Group` select the appropriate group you would like to bind. Make sure `Enabled` is toggeled on. Click `Create`.
|
||||
|
||||

|
||||
|
||||
`Dashy` will now be scoped only to users within the assigned groups you have bound the application to. Keep adding groups if you would like to adjust the dashboard visibilty based on group membership.
|
||||
|
||||
#### 4. Configure `Dashy` to use OIDC client
|
||||
|
||||
>[!IMPORTANT]
|
||||
>It is highly recommended to edit your `conf.yml` directly for this step.
|
||||
|
||||
>[!CAUTION]
|
||||
>Do not make the same mistake many have made here by including the fully qualified address for the `OpenID Configuration URL`. `Dashy` will append the `.well-known` configuration automatically. If the `.well-known` URI is included the app will get redirect loops and `400` errors.
|
||||
|
||||
Enter the `Client ID` in the `clientId` field and `OpenID Configuration Issuer` in the `endpoint` field.
|
||||
|
||||
Below is how to configure the `auth` section in the yaml syntax. Once this is enabled, when an attempt to access `Dashy` is made it will now redirect you to the `authentik` login page moving forward.
|
||||
|
||||
```
|
||||
appConfig:
|
||||
theme: glass
|
||||
layout: auto
|
||||
iconSize: medium
|
||||
auth:
|
||||
enableOidc: true
|
||||
oidc:
|
||||
clientId: pzN9DCMLqHTTatgtYFg50cl0jn1NmCyBC3wreX15
|
||||
endpoint: https://auth.domain.com/application/o/dashy/
|
||||
```
|
||||
|
||||
#### 5. *(OPTIONAL)* Example snippets for dashboard visibility
|
||||
|
||||
Using the `hideForKeycloakUsers` configuration option is needed to use the `authentik` groups that were created previously.
|
||||
|
||||
Adjusting `pages` visibility:
|
||||
```
|
||||
pages:
|
||||
- name: App Management
|
||||
path: appmgmt.yml
|
||||
displayData:
|
||||
hideForKeycloakUsers:
|
||||
groups:
|
||||
- Dashy Users
|
||||
- name: Network Management
|
||||
path: network.yml
|
||||
displayData:
|
||||
hideForKeycloakUsers:
|
||||
groups:
|
||||
- Dashy Users
|
||||
```
|
||||
|
||||
Adjusting `items` visibility:
|
||||
```
|
||||
items:
|
||||
- title: Authentik Admin
|
||||
icon: authentik.svg
|
||||
url: https://auth.domain.com/if/admin/
|
||||
target: newtab
|
||||
id: 0_1472_authentikadmin
|
||||
displayData:
|
||||
hideForKeycloakUsers:
|
||||
groups:
|
||||
- Dashy Users
|
||||
- title: Authentik User
|
||||
icon: authentik-light.png
|
||||
url: https://auth.domain.com/if/user/
|
||||
target: newtab
|
||||
id: 1_1472_authentikuser
|
||||
```
|
||||
|
||||
Adjusting `sections` visibility:
|
||||
```
|
||||
sections:
|
||||
- name: Authentication
|
||||
displayData:
|
||||
sortBy: default
|
||||
rows: 2
|
||||
cols: 1
|
||||
collapsed: false
|
||||
hideForGuests: false
|
||||
hideForKeycloakUsers:
|
||||
groups:
|
||||
- Dashy Users
|
||||
```
|
||||
---
|
||||
|
||||
## Alternative Authentication Methods
|
||||
|
||||
If you are self-hosting Dashy, and require secure authentication to prevent unauthorized access, then you can either use Keycloak, or one of the following options:
|
||||
|
@ -158,6 +158,8 @@ The following file provides a reference of all supported configuration options.
|
||||
**`keycloak`** | `object` | _Optional_ | Config options to point Dashy to your Keycloak server. Requires `enableKeycloak: true`. See [`auth.keycloak`](#appconfigauthkeycloak-optional) for more info
|
||||
**`enableHeaderAuth`** | `boolean` | _Optional_ | If set to `true`, then authentication using HeaderAuth will be enabled. Note that you need to have your web server/reverse proxy running, and have also configured `auth.headerAuth`. Defaults to `false`
|
||||
**`headerAuth`** | `object` | _Optional_ | Config options to point Dashy to your headers for authentication. Requires `enableHeaderAuth: true`. See [`auth.headerAuth`](#appconfigauthheaderauth-optional) for more info
|
||||
**`enableOidc`** | `boolean` | _Optional_ | If set to `true`, then authentication using OIDC will be enabled. Note that you need to have a configured OIDC server and configure it with `auth.oidc`. Defaults to `false`
|
||||
**`oidc`** | `object` | _Optional_ | Config options to point Dash to your OIDC configuration. Request `enableOidc: true`. See [`auth.oidc`](#appconfigauthoidc-optional) for more info
|
||||
**`enableGuestAccess`** | `boolean` | _Optional_ | When set to `true`, an unauthenticated user will be able to access the dashboard, with read-only access, without having to login. Requires `auth.users` to be configured. Defaults to `false`.
|
||||
|
||||
For more info, see the **[Authentication Docs](/docs/authentication.md)**
|
||||
@ -194,6 +196,16 @@ For more info, see the **[Authentication Docs](/docs/authentication.md)**
|
||||
|
||||
**[⬆️ Back to Top](#configuring)**
|
||||
|
||||
## `appConfig.auth.oidc` _(optional)_
|
||||
|
||||
**Field** | **Type** | **Required**| **Description**
|
||||
--- | --- | --- | ---
|
||||
**`clientId`** | `string` | Required | The client id registered in the OIDC server
|
||||
**`endpoint`** | `string` | Required | The URL of the OIDC server that should be used.
|
||||
**`scope`** | `string` | Required | The scope(s) to request from the OIDC provider
|
||||
|
||||
**[⬆️ Back to Top](#configuring)**
|
||||
|
||||
## `appConfig.webSearch` _(optional)_
|
||||
|
||||
**Field** | **Type** | **Required**| **Description**
|
||||
|
641
docs/credits.md
@ -5,48 +5,19 @@
|
||||
<table>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/github">
|
||||
<img src="https://avatars.githubusercontent.com/u/9919?v=4" width="80;" alt="github"/>
|
||||
<br />
|
||||
<sub><b>GitHub</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/koconder">
|
||||
<img src="https://avatars.githubusercontent.com/u/25068?u=582657b23622aaa3dfe68bd028a780f272f456fa&v=4" width="80;" alt="koconder"/>
|
||||
<a href="https://github.com/vincentkoc">
|
||||
<img src="https://avatars.githubusercontent.com/u/25068?u=fbd5b2d51142daa4bdbc21e21953a3b8b8188a4a&v=4" width="80;" alt="vincentkoc"/>
|
||||
<br />
|
||||
<sub><b>Vincent Koc</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Admonstrator">
|
||||
<img src="https://avatars.githubusercontent.com/u/69824?u=1e226d7a36cdd661c3e4cd486fea140d045b7d57&v=4" width="80;" alt="Admonstrator"/>
|
||||
<br />
|
||||
<sub><b>Aaron Viehl</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/tbjers">
|
||||
<img src="https://avatars.githubusercontent.com/u/1117052?v=4" width="80;" alt="tbjers"/>
|
||||
<br />
|
||||
<sub><b>Torgny Bjers</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/emlazzarin">
|
||||
<img src="https://avatars.githubusercontent.com/u/1141361?u=714e3487a3f2e0df721b01a0133945f075d3ff68&v=4" width="80;" alt="emlazzarin"/>
|
||||
<br />
|
||||
<sub><b>Eddy Lazzarin</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/AnandChowdhary">
|
||||
<img src="https://avatars.githubusercontent.com/u/2841780?u=747e554b3a7f12eb20b7910e1c87d817844f714f&v=4" width="80;" alt="AnandChowdhary"/>
|
||||
<br />
|
||||
<sub><b>Anand Chowdhary</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/shrippen">
|
||||
<img src="https://avatars.githubusercontent.com/u/2873570?v=4" width="80;" alt="shrippen"/>
|
||||
@ -74,7 +45,8 @@
|
||||
<br />
|
||||
<sub><b>Digital Archeology</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/InDieTasten">
|
||||
<img src="https://avatars.githubusercontent.com/u/7047377?u=8d8f8017628b38bc46dcbf3620e194b01d3fb2d1&v=4" width="80;" alt="InDieTasten"/>
|
||||
@ -88,8 +60,7 @@
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/bmcgonag">
|
||||
<img src="https://avatars.githubusercontent.com/u/7346620?u=2a0f9284f3e12ac1cc15288c254d1ec68a5081e8&v=4" width="80;" alt="bmcgonag"/>
|
||||
@ -98,10 +69,17 @@
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/vlad-timofeev">
|
||||
<img src="https://avatars.githubusercontent.com/u/11474041?u=eee43705b54d2ec9f51fc4fcce5ad18dd17c87e4&v=4" width="80;" alt="vlad-timofeev"/>
|
||||
<a href="https://github.com/arcestia">
|
||||
<img src="https://avatars.githubusercontent.com/u/7936962?u=afc43f878a0858cae75418f18d9696d65ebd53f9&v=4" width="80;" alt="arcestia"/>
|
||||
<br />
|
||||
<sub><b>Vlad Timofeev</b></sub>
|
||||
<sub><b>Laurensius Jeffrey</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/vlad-tim">
|
||||
<img src="https://avatars.githubusercontent.com/u/11474041?u=eee43705b54d2ec9f51fc4fcce5ad18dd17c87e4&v=4" width="80;" alt="vlad-tim"/>
|
||||
<br />
|
||||
<sub><b>Vlad</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@ -110,55 +88,20 @@
|
||||
<br />
|
||||
<sub><b>HeliXZz</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/patvdv">
|
||||
<img src="https://avatars.githubusercontent.com/u/12430107?u=e8911c2fb91af4d30432f76da8c40927b2830bd7&v=4" width="80;" alt="patvdv"/>
|
||||
<br />
|
||||
<sub><b>Patrick Van Der Veken</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/plgonzalezrx8">
|
||||
<img src="https://avatars.githubusercontent.com/u/19900049?v=4" width="80;" alt="plgonzalezrx8"/>
|
||||
<br />
|
||||
<sub><b>Pedro Gonzalez</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/mryesiller">
|
||||
<img src="https://avatars.githubusercontent.com/u/24632172?u=0d20f2d615158f87cd60a3398d3efb026c32f291&v=4" width="80;" alt="mryesiller"/>
|
||||
<br />
|
||||
<sub><b>Göksel Yeşiller</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/allesauseinerhand">
|
||||
<img src="https://avatars.githubusercontent.com/u/32039836?v=4" width="80;" alt="allesauseinerhand"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/forwardemail">
|
||||
<img src="https://avatars.githubusercontent.com/u/32481436?v=4" width="80;" alt="forwardemail"/>
|
||||
<a href="https://github.com/sushibait">
|
||||
<img src="https://avatars.githubusercontent.com/u/26634535?v=4" width="80;" alt="sushibait"/>
|
||||
<br />
|
||||
<sub><b>Forward Email - Open-source & Privacy-focused Email Service (2023)</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/lamtrinhdev">
|
||||
<img src="https://avatars.githubusercontent.com/u/49742151?u=c5eaca5aa6841a80605cf4f7d0e861a9e6339ef3&v=4" width="80;" alt="lamtrinhdev"/>
|
||||
<br />
|
||||
<sub><b>LamTrinh.Dev</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Bastii717">
|
||||
<img src="https://avatars.githubusercontent.com/u/53431819?u=604977bed6ad6875ada890d0d3765a4cacc2fa14&v=4" width="80;" alt="Bastii717"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
<sub><b>Shiverme Timbers</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@ -169,13 +112,12 @@
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/M2TD">
|
||||
<img src="https://avatars.githubusercontent.com/u/85460457?v=4" width="80;" alt="M2TD"/>
|
||||
<a href="https://github.com/OlliVHH">
|
||||
<img src="https://avatars.githubusercontent.com/u/84959562?v=4" width="80;" alt="OlliVHH"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
<sub><b>HamburgerJung</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/frankdez93">
|
||||
<img src="https://avatars.githubusercontent.com/u/87549420?v=4" width="80;" alt="frankdez93"/>
|
||||
@ -189,17 +131,18 @@
|
||||
<br />
|
||||
<sub><b>Terminal Trove</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/NixyJuppie">
|
||||
<img src="https://avatars.githubusercontent.com/u/138570196?u=b102c222487905728b858704962d32759df29ebe&v=4" width="80;" alt="NixyJuppie"/>
|
||||
<a href="https://github.com/st617">
|
||||
<img src="https://avatars.githubusercontent.com/u/128325650?v=4" width="80;" alt="st617"/>
|
||||
<br />
|
||||
<sub><b>Nixy</b></sub>
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/nrvo">
|
||||
<img src="https://avatars.githubusercontent.com/u/151435968?u=e1dcb307fd0efdc45cddbe9490a7b956e4da6835&v=4" width="80;" alt="nrvo"/>
|
||||
<a href="https://github.com/hudsonrock-partnerships">
|
||||
<img src="https://avatars.githubusercontent.com/u/163282900?u=5f2667f7fe5d284ac7a2da6b0800ea8970b0fcbf&v=4" width="80;" alt="hudsonrock-partnerships"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
@ -225,6 +168,13 @@
|
||||
<sub><b>Alicia Bot</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/CrazyWolf13">
|
||||
<img src="https://avatars.githubusercontent.com/u/96661824?v=4" width="80;" alt="CrazyWolf13"/>
|
||||
<br />
|
||||
<sub><b>Tobias</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/marekful">
|
||||
<img src="https://avatars.githubusercontent.com/u/10281476?v=4" width="80;" alt="marekful"/>
|
||||
@ -245,15 +195,15 @@
|
||||
<br />
|
||||
<sub><b>Snyk Bot</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/azerioxal">
|
||||
<img src="https://avatars.githubusercontent.com/u/5369885?v=4" width="80;" alt="azerioxal"/>
|
||||
<br />
|
||||
<sub><b>Kenneth Church</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/m42e">
|
||||
<img src="https://avatars.githubusercontent.com/u/2410802?v=4" width="80;" alt="m42e"/>
|
||||
@ -261,13 +211,6 @@
|
||||
<sub><b>Matthias Bilger</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/CrazyWolf13">
|
||||
<img src="https://avatars.githubusercontent.com/u/96661824?v=4" width="80;" alt="CrazyWolf13"/>
|
||||
<br />
|
||||
<sub><b>Tobias</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/pinarruiz">
|
||||
<img src="https://avatars.githubusercontent.com/u/37040888?v=4" width="80;" alt="pinarruiz"/>
|
||||
@ -290,10 +233,10 @@
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/walkxcode">
|
||||
<img src="https://avatars.githubusercontent.com/u/71191962?v=4" width="80;" alt="walkxcode"/>
|
||||
<a href="https://github.com/lammersbjorn">
|
||||
<img src="https://avatars.githubusercontent.com/u/71191962?v=4" width="80;" alt="lammersbjorn"/>
|
||||
<br />
|
||||
<sub><b>Walkx</b></sub>
|
||||
<sub><b>Bjorn Lammers</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
@ -340,6 +283,13 @@
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/alhazmy13">
|
||||
<img src="https://avatars.githubusercontent.com/u/4659608?v=4" width="80;" alt="alhazmy13"/>
|
||||
<br />
|
||||
<sub><b>Abdullah Alhazmy</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/altearius">
|
||||
<img src="https://avatars.githubusercontent.com/u/270430?v=4" width="80;" alt="altearius"/>
|
||||
@ -354,6 +304,13 @@
|
||||
<sub><b>UrekD</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/hockwill">
|
||||
<img src="https://avatars.githubusercontent.com/u/100539627?v=4" width="80;" alt="hockwill"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/z3r0l1nk">
|
||||
<img src="https://avatars.githubusercontent.com/u/31653632?v=4" width="80;" alt="z3r0l1nk"/>
|
||||
@ -361,6 +318,14 @@
|
||||
<sub><b>Mihai</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/zcq100">
|
||||
<img src="https://avatars.githubusercontent.com/u/425234?v=4" width="80;" alt="zcq100"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/wozboz">
|
||||
<img src="https://avatars.githubusercontent.com/u/51856582?v=4" width="80;" alt="wozboz"/>
|
||||
@ -368,21 +333,49 @@
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/conlan0">
|
||||
<img src="https://avatars.githubusercontent.com/u/87742085?v=4" width="80;" alt="conlan0"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/dasunsrule32">
|
||||
<img src="https://avatars.githubusercontent.com/u/649815?v=4" width="80;" alt="dasunsrule32"/>
|
||||
<br />
|
||||
<sub><b>Aaron Echols</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/aviolaris">
|
||||
<img src="https://avatars.githubusercontent.com/u/48277853?v=4" width="80;" alt="aviolaris"/>
|
||||
<br />
|
||||
<sub><b>Andreas Violaris</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Tracreed">
|
||||
<img src="https://avatars.githubusercontent.com/u/6306365?v=4" width="80;" alt="Tracreed"/>
|
||||
<br />
|
||||
<sub><b>David Alasow</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Totto16">
|
||||
<img src="https://avatars.githubusercontent.com/u/32566573?v=4" width="80;" alt="Totto16"/>
|
||||
<br />
|
||||
<sub><b>Totto16</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/toddejohnson">
|
||||
<img src="https://avatars.githubusercontent.com/u/507545?v=4" width="80;" alt="toddejohnson"/>
|
||||
<br />
|
||||
<sub><b>Todd Johnson</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/remygrandin">
|
||||
<img src="https://avatars.githubusercontent.com/u/1934515?v=4" width="80;" alt="remygrandin"/>
|
||||
@ -397,20 +390,6 @@
|
||||
<sub><b>Dimitri</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Tracreed">
|
||||
<img src="https://avatars.githubusercontent.com/u/6306365?v=4" width="80;" alt="Tracreed"/>
|
||||
<br />
|
||||
<sub><b>David Alasow</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/aviolaris">
|
||||
<img src="https://avatars.githubusercontent.com/u/48277853?v=4" width="80;" alt="aviolaris"/>
|
||||
<br />
|
||||
<sub><b>Andreas Violaris</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/rubenandre">
|
||||
<img src="https://avatars.githubusercontent.com/u/9402773?v=4" width="80;" alt="rubenandre"/>
|
||||
@ -418,6 +397,13 @@
|
||||
<sub><b>Rúben Silva</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/alucarddelta">
|
||||
<img src="https://avatars.githubusercontent.com/u/20882097?v=4" width="80;" alt="alucarddelta"/>
|
||||
<br />
|
||||
<sub><b>Brent</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/rtm516">
|
||||
<img src="https://avatars.githubusercontent.com/u/5401186?v=4" width="80;" alt="rtm516"/>
|
||||
@ -427,10 +413,10 @@
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/zcq100">
|
||||
<img src="https://avatars.githubusercontent.com/u/425234?v=4" width="80;" alt="zcq100"/>
|
||||
<a href="https://github.com/berksmbl">
|
||||
<img src="https://avatars.githubusercontent.com/u/10000339?v=4" width="80;" alt="berksmbl"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
<sub><b>Berk Sümbül</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@ -447,42 +433,6 @@
|
||||
<sub><b>Stanly0726</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Bogyie">
|
||||
<img src="https://avatars.githubusercontent.com/u/82003678?v=4" width="80;" alt="Bogyie"/>
|
||||
<br />
|
||||
<sub><b>Bogyeong Kim</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Tuzi555">
|
||||
<img src="https://avatars.githubusercontent.com/u/62188066?v=4" width="80;" alt="Tuzi555"/>
|
||||
<br />
|
||||
<sub><b>Jakub Tuzar</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/berksmbl">
|
||||
<img src="https://avatars.githubusercontent.com/u/10000339?v=4" width="80;" alt="berksmbl"/>
|
||||
<br />
|
||||
<sub><b>Berk Sümbül</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/alucarddelta">
|
||||
<img src="https://avatars.githubusercontent.com/u/20882097?v=4" width="80;" alt="alucarddelta"/>
|
||||
<br />
|
||||
<sub><b>Brent</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/k073l">
|
||||
<img src="https://avatars.githubusercontent.com/u/21180271?v=4" width="80;" alt="k073l"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/kt-alt">
|
||||
<img src="https://avatars.githubusercontent.com/u/51970249?v=4" width="80;" alt="kt-alt"/>
|
||||
@ -491,32 +441,32 @@
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/mmihaly">
|
||||
<img src="https://avatars.githubusercontent.com/u/50031464?v=4" width="80;" alt="mmihaly"/>
|
||||
<a href="https://github.com/Bogyie">
|
||||
<img src="https://avatars.githubusercontent.com/u/82003678?v=4" width="80;" alt="Bogyie"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
<sub><b>Bogyeong Kim</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/patrickheeney">
|
||||
<img src="https://avatars.githubusercontent.com/u/1407228?v=4" width="80;" alt="patrickheeney"/>
|
||||
<a href="https://github.com/webysther">
|
||||
<img src="https://avatars.githubusercontent.com/u/750007?v=4" width="80;" alt="webysther"/>
|
||||
<br />
|
||||
<sub><b>Patrick Heeney</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/rokiden">
|
||||
<img src="https://avatars.githubusercontent.com/u/11071229?v=4" width="80;" alt="rokiden"/>
|
||||
<br />
|
||||
<sub><b>Denis Kazimirov</b></sub>
|
||||
<sub><b>Webysther Sperandio</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/zigotica">
|
||||
<img src="https://avatars.githubusercontent.com/u/178855?v=4" width="80;" alt="zigotica"/>
|
||||
<a href="https://github.com/jtuzar">
|
||||
<img src="https://avatars.githubusercontent.com/u/62188066?v=4" width="80;" alt="jtuzar"/>
|
||||
<br />
|
||||
<sub><b>Sergi Meseguer</b></sub>
|
||||
<sub><b>Jakub Tuzar</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/ssrangisetti">
|
||||
<img src="https://avatars.githubusercontent.com/u/46807508?v=4" width="80;" alt="ssrangisetti"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@ -527,8 +477,44 @@
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/ssrangisetti">
|
||||
<img src="https://avatars.githubusercontent.com/u/46807508?v=4" width="80;" alt="ssrangisetti"/>
|
||||
<a href="https://github.com/zigotica">
|
||||
<img src="https://avatars.githubusercontent.com/u/178855?v=4" width="80;" alt="zigotica"/>
|
||||
<br />
|
||||
<sub><b>Sergi Meseguer</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/rokiden">
|
||||
<img src="https://avatars.githubusercontent.com/u/11071229?v=4" width="80;" alt="rokiden"/>
|
||||
<br />
|
||||
<sub><b>Denis Kazimirov</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/patrickheeney">
|
||||
<img src="https://avatars.githubusercontent.com/u/1407228?v=4" width="80;" alt="patrickheeney"/>
|
||||
<br />
|
||||
<sub><b>Patrick Heeney</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/mmihaly">
|
||||
<img src="https://avatars.githubusercontent.com/u/50031464?v=4" width="80;" alt="mmihaly"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/m42cel">
|
||||
<img src="https://avatars.githubusercontent.com/u/82040674?v=4" width="80;" alt="m42cel"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/k073l">
|
||||
<img src="https://avatars.githubusercontent.com/u/21180271?v=4" width="80;" alt="k073l"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
@ -541,39 +527,25 @@
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/hockeymikey">
|
||||
<img src="https://avatars.githubusercontent.com/u/1435185?v=4" width="80;" alt="hockeymikey"/>
|
||||
<a href="https://github.com/alexdelprete">
|
||||
<img src="https://avatars.githubusercontent.com/u/7027842?v=4" width="80;" alt="alexdelprete"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
<sub><b>Alessandro Del Prete</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/thomaswienecke">
|
||||
<img src="https://avatars.githubusercontent.com/u/11446531?v=4" width="80;" alt="thomaswienecke"/>
|
||||
<a href="https://github.com/alayham">
|
||||
<img src="https://avatars.githubusercontent.com/u/518776?v=4" width="80;" alt="alayham"/>
|
||||
<br />
|
||||
<sub><b>Thomas Wienecke</b></sub>
|
||||
<sub><b>Al-Ayham Saleh</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/deneor">
|
||||
<img src="https://avatars.githubusercontent.com/u/1063265?v=4" width="80;" alt="deneor"/>
|
||||
<a href="https://github.com/a-mnich">
|
||||
<img src="https://avatars.githubusercontent.com/u/56564725?v=4" width="80;" alt="a-mnich"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/daentech">
|
||||
<img src="https://avatars.githubusercontent.com/u/358678?v=4" width="80;" alt="daentech"/>
|
||||
<br />
|
||||
<sub><b>Dan Gilbert</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/moemoeq">
|
||||
<img src="https://avatars.githubusercontent.com/u/1808434?v=4" width="80;" alt="moemoeq"/>
|
||||
<br />
|
||||
<sub><b>CHAIYEON CHO</b></sub>
|
||||
<sub><b>Alexander Mnich</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@ -584,25 +556,82 @@
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/a-mnich">
|
||||
<img src="https://avatars.githubusercontent.com/u/56564725?v=4" width="80;" alt="a-mnich"/>
|
||||
<a href="https://github.com/moemoeq">
|
||||
<img src="https://avatars.githubusercontent.com/u/1808434?v=4" width="80;" alt="moemoeq"/>
|
||||
<br />
|
||||
<sub><b>Alexander Mnich</b></sub>
|
||||
<sub><b>CHAIYEON CHO</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/alexdelprete">
|
||||
<img src="https://avatars.githubusercontent.com/u/7027842?v=4" width="80;" alt="alexdelprete"/>
|
||||
<a href="https://github.com/daentech">
|
||||
<img src="https://avatars.githubusercontent.com/u/358678?v=4" width="80;" alt="daentech"/>
|
||||
<br />
|
||||
<sub><b>Alessandro Del Prete</b></sub>
|
||||
<sub><b>Dan Gilbert</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/deneor">
|
||||
<img src="https://avatars.githubusercontent.com/u/1063265?v=4" width="80;" alt="deneor"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/GuilhermeLCS95">
|
||||
<img src="https://avatars.githubusercontent.com/u/116608998?v=4" width="80;" alt="GuilhermeLCS95"/>
|
||||
<br />
|
||||
<sub><b>GuilhermeLCS</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/alayham">
|
||||
<img src="https://avatars.githubusercontent.com/u/518776?v=4" width="80;" alt="alayham"/>
|
||||
<a href="https://github.com/lucolvin">
|
||||
<img src="https://avatars.githubusercontent.com/u/97006355?v=4" width="80;" alt="lucolvin"/>
|
||||
<br />
|
||||
<sub><b>Al-Ayham Saleh</b></sub>
|
||||
<sub><b>Luke</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/TJonesy">
|
||||
<img src="https://avatars.githubusercontent.com/u/1951223?v=4" width="80;" alt="TJonesy"/>
|
||||
<br />
|
||||
<sub><b>Taylor Jones</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/twsouthwick">
|
||||
<img src="https://avatars.githubusercontent.com/u/583206?v=4" width="80;" alt="twsouthwick"/>
|
||||
<br />
|
||||
<sub><b>Taylor Southwick</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/thomaswienecke">
|
||||
<img src="https://avatars.githubusercontent.com/u/11446531?v=4" width="80;" alt="thomaswienecke"/>
|
||||
<br />
|
||||
<sub><b>Thomas Wienecke</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/hockeymikey">
|
||||
<img src="https://avatars.githubusercontent.com/u/1435185?v=4" width="80;" alt="hockeymikey"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/rubjo">
|
||||
<img src="https://avatars.githubusercontent.com/u/42270947?v=4" width="80;" alt="rubjo"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/turnrye">
|
||||
<img src="https://avatars.githubusercontent.com/u/701035?v=4" width="80;" alt="turnrye"/>
|
||||
<br />
|
||||
<sub><b>Ryan Turner</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@ -662,28 +691,6 @@
|
||||
<sub><b>Steven Kast</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/AmadeusGraves">
|
||||
<img src="https://avatars.githubusercontent.com/u/18572939?v=4" width="80;" alt="AmadeusGraves"/>
|
||||
<br />
|
||||
<sub><b>Ángel Fernández Sánchez</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/turnrye">
|
||||
<img src="https://avatars.githubusercontent.com/u/701035?v=4" width="80;" alt="turnrye"/>
|
||||
<br />
|
||||
<sub><b>Ryan Turner</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/rubjo">
|
||||
<img src="https://avatars.githubusercontent.com/u/42270947?v=4" width="80;" alt="rubjo"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/PrynsTag">
|
||||
<img src="https://avatars.githubusercontent.com/u/56314705?v=4" width="80;" alt="PrynsTag"/>
|
||||
@ -704,7 +711,8 @@
|
||||
<br />
|
||||
<sub><b>OKAMOTO Shigehiro</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/bubylou">
|
||||
<img src="https://avatars.githubusercontent.com/u/3878640?v=4" width="80;" alt="bubylou"/>
|
||||
@ -712,6 +720,20 @@
|
||||
<sub><b>Nicholas Malcolm</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/michaelfeinbier">
|
||||
<img src="https://avatars.githubusercontent.com/u/503543?v=4" width="80;" alt="michaelfeinbier"/>
|
||||
<br />
|
||||
<sub><b>Michael Feinbier</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/stinkybernie">
|
||||
<img src="https://avatars.githubusercontent.com/u/155188453?v=4" width="80;" alt="stinkybernie"/>
|
||||
<br />
|
||||
<sub><b>Michael D</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/miclav">
|
||||
<img src="https://avatars.githubusercontent.com/u/11891522?v=4" width="80;" alt="miclav"/>
|
||||
@ -725,13 +747,27 @@
|
||||
<br />
|
||||
<sub><b>Mert Sefa AKGUN</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/maximemoreillon">
|
||||
<img src="https://avatars.githubusercontent.com/u/29086128?v=4" width="80;" alt="maximemoreillon"/>
|
||||
<br />
|
||||
<sub><b>Maxime Moreillon</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/ethan-hann">
|
||||
<img src="https://avatars.githubusercontent.com/u/36464732?v=4" width="80;" alt="ethan-hann"/>
|
||||
<a href="https://github.com/Glitch3dPenguin">
|
||||
<img src="https://avatars.githubusercontent.com/u/3271160?v=4" width="80;" alt="Glitch3dPenguin"/>
|
||||
<br />
|
||||
<sub><b>Ethan Hann</b></sub>
|
||||
<sub><b>Max Kulik</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/AmadeusGraves">
|
||||
<img src="https://avatars.githubusercontent.com/u/18572939?v=4" width="80;" alt="AmadeusGraves"/>
|
||||
<br />
|
||||
<sub><b>Ángel Fernández Sánchez</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@ -761,6 +797,14 @@
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/nOw-Ay">
|
||||
<img src="https://avatars.githubusercontent.com/u/74311152?v=4" width="80;" alt="nOw-Ay"/>
|
||||
<br />
|
||||
<sub><b>Noé Busson</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/markxoe">
|
||||
@ -768,13 +812,12 @@
|
||||
<br />
|
||||
<sub><b>Mark Oude Elberink</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/lxjv">
|
||||
<img src="https://avatars.githubusercontent.com/u/63261955?v=4" width="80;" alt="lxjv"/>
|
||||
<a href="https://github.com/ivyturner">
|
||||
<img src="https://avatars.githubusercontent.com/u/63261955?v=4" width="80;" alt="ivyturner"/>
|
||||
<br />
|
||||
<sub><b>Laker Turner</b></sub>
|
||||
<sub><b>Ivy Rose Turner</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@ -797,7 +840,8 @@
|
||||
<br />
|
||||
<sub><b>Jnach</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/imlonghao">
|
||||
<img src="https://avatars.githubusercontent.com/u/4951333?v=4" width="80;" alt="imlonghao"/>
|
||||
@ -811,8 +855,7 @@
|
||||
<br />
|
||||
<sub><b>Aniket Teredesai</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/huangshaohuai">
|
||||
<img src="https://avatars.githubusercontent.com/u/24775925?v=4" width="80;" alt="huangshaohuai"/>
|
||||
@ -827,13 +870,6 @@
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/dr460nf1r3">
|
||||
<img src="https://avatars.githubusercontent.com/u/12834713?v=4" width="80;" alt="dr460nf1r3"/>
|
||||
<br />
|
||||
<sub><b>Nico</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/baifengheixi">
|
||||
<img src="https://avatars.githubusercontent.com/u/98794233?v=4" width="80;" alt="baifengheixi"/>
|
||||
@ -847,20 +883,27 @@
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/XertDev">
|
||||
<img src="https://avatars.githubusercontent.com/u/16572811?v=4" width="80;" alt="XertDev"/>
|
||||
<br />
|
||||
<sub><b>Xert</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/emiran-orange">
|
||||
<img src="https://avatars.githubusercontent.com/u/71817149?v=4" width="80;" alt="emiran-orange"/>
|
||||
<a href="https://github.com/willbrowningme">
|
||||
<img src="https://avatars.githubusercontent.com/u/20662079?v=4" width="80;" alt="willbrowningme"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
<sub><b>Will Browning</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/ThibautSnoeijs">
|
||||
<img src="https://avatars.githubusercontent.com/u/108188070?v=4" width="80;" alt="ThibautSnoeijs"/>
|
||||
<br />
|
||||
<sub><b>Thibaut</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
@ -877,6 +920,21 @@
|
||||
<sub><b>Dylan Bersans</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/dyauss">
|
||||
<img src="https://avatars.githubusercontent.com/u/50002238?v=4" width="80;" alt="dyauss"/>
|
||||
<br />
|
||||
<sub><b>Thandy Norberto</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/ddenev">
|
||||
<img src="https://avatars.githubusercontent.com/u/1393766?v=4" width="80;" alt="ddenev"/>
|
||||
<br />
|
||||
<sub><b>Dragomir Denev</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/dougaldhub">
|
||||
<img src="https://avatars.githubusercontent.com/u/25713235?v=4" width="80;" alt="dougaldhub"/>
|
||||
@ -897,8 +955,7 @@
|
||||
<br />
|
||||
<sub><b>DeepSource Bot</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/DawidPietrykowski">
|
||||
<img src="https://avatars.githubusercontent.com/u/53954695?v=4" width="80;" alt="DawidPietrykowski"/>
|
||||
@ -912,6 +969,14 @@
|
||||
<br />
|
||||
<sub><b>David</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/danfein">
|
||||
<img src="https://avatars.githubusercontent.com/u/4053985?v=4" width="80;" alt="danfein"/>
|
||||
<br />
|
||||
<sub><b>Dan</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/clsty">
|
||||
@ -927,6 +992,13 @@
|
||||
<sub><b>Bumsoo Kim</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/NicholasWilsonDEV">
|
||||
<img src="https://avatars.githubusercontent.com/u/183866110?v=4" width="80;" alt="NicholasWilsonDEV"/>
|
||||
<br />
|
||||
<sub><b>Nicholas Wilson</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/BhasherBEL">
|
||||
<img src="https://avatars.githubusercontent.com/u/45831883?v=4" width="80;" alt="BhasherBEL"/>
|
||||
@ -977,28 +1049,14 @@
|
||||
<sub><b>0n1cOn3</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/maximemoreillon">
|
||||
<img src="https://avatars.githubusercontent.com/u/29086128?v=4" width="80;" alt="maximemoreillon"/>
|
||||
<br />
|
||||
<sub><b>Maxime Moreillon</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Glitch3dPenguin">
|
||||
<img src="https://avatars.githubusercontent.com/u/3271160?v=4" width="80;" alt="Glitch3dPenguin"/>
|
||||
<br />
|
||||
<sub><b>Max Kulik</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/markusdd">
|
||||
<img src="https://avatars.githubusercontent.com/u/25175069?v=4" width="80;" alt="markusdd"/>
|
||||
<br />
|
||||
<sub><b>Markus Krause</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/asenov">
|
||||
<img src="https://avatars.githubusercontent.com/u/280619?v=4" width="80;" alt="asenov"/>
|
||||
@ -1026,8 +1084,7 @@
|
||||
<br />
|
||||
<sub><b>Kieren Connell</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/kieraneglin">
|
||||
<img src="https://avatars.githubusercontent.com/u/569917?v=4" width="80;" alt="kieraneglin"/>
|
||||
@ -1035,6 +1092,14 @@
|
||||
<sub><b>Kieran</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/johnhorton2010">
|
||||
<img src="https://avatars.githubusercontent.com/u/2205098?v=4" width="80;" alt="johnhorton2010"/>
|
||||
<br />
|
||||
<sub><b>John Horton</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/Singebob">
|
||||
<img src="https://avatars.githubusercontent.com/u/24290044?v=4" width="80;" alt="Singebob"/>
|
||||
@ -1069,14 +1134,21 @@
|
||||
<br />
|
||||
<sub><b>Iaroslav Dronskii</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/nealian">
|
||||
<img src="https://avatars.githubusercontent.com/u/865115?v=4" width="80;" alt="nealian"/>
|
||||
<br />
|
||||
<sub><b>Ian Neal</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/ip2location">
|
||||
<img src="https://avatars.githubusercontent.com/u/6367210?v=4" width="80;" alt="ip2location"/>
|
||||
<br />
|
||||
<sub><b>IP2Location</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/FraglyG">
|
||||
@ -1105,6 +1177,21 @@
|
||||
<br />
|
||||
<sub><b>FormatToday</b></sub>
|
||||
</a>
|
||||
</td>
|
||||
<td align="center">
|
||||
<a href="https://github.com/pvillaverde">
|
||||
<img src="https://avatars.githubusercontent.com/u/31769405?v=4" width="80;" alt="pvillaverde"/>
|
||||
<br />
|
||||
<sub><b>Fedello</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
<tr>
|
||||
<td align="center">
|
||||
<a href="https://github.com/emiran-orange">
|
||||
<img src="https://avatars.githubusercontent.com/u/71817149?v=4" width="80;" alt="emiran-orange"/>
|
||||
<br />
|
||||
<sub><b>Null</b></sub>
|
||||
</a>
|
||||
</td></tr>
|
||||
</table>
|
||||
<!-- readme: contributors -end -->
|
||||
|
@ -112,7 +112,7 @@ services:
|
||||
# volumes:
|
||||
# - /root/my-config.yml:/app/user-data/conf.yml
|
||||
ports:
|
||||
- 4000:8080
|
||||
- 8080:8080
|
||||
# Set any environmental variables
|
||||
environment:
|
||||
- NODE_ENV=production
|
||||
@ -182,7 +182,7 @@ dashy should be up within 1-2min after you've started the install task procedure
|
||||
If you do not want to use Docker, you can run Dashy directly on your host system. For this, you will need both [git](https://git-scm.com/downloads) and the latest or LTS version of [Node.js](https://nodejs.org/) installed, and optionally [yarn](https://yarnpkg.com/)
|
||||
|
||||
1. Get Code: `git clone https://github.com/Lissy93/dashy.git` and `cd dashy`
|
||||
2. Configuration: Fill in you're settings in `./user-data/conf.yml`
|
||||
2. Configuration: Fill in your settings in `./user-data/conf.yml`
|
||||
3. Install dependencies: `yarn`
|
||||
4. Build: `yarn build`
|
||||
5. Run: `yarn start`
|
||||
|
@ -111,7 +111,7 @@ For example, these will all render the same rocket (🚀) emoji: `icon: ':rocket
|
||||
|
||||
## Home-Lab Icons
|
||||
|
||||
The [dashboard-icons](https://github.com/walkxcode/Dashboard-Icons) repo by [@WalkxCode](https://github.com/WalkxCode) provides a comprehensive collection of 360+ high-quality PNG icons for commonly self-hosted services. Dashy natively supports these icons, and you can use them just by specifying the icon name (without extension) preceded by `hl-`. See [here](https://github.com/walkxcode/Dashboard-Icons/tree/main/png) for a full list of all available icons. Note that these are fetched and cached strait from GitHub, so if you require offline access, the [Local Icons](#local-icons) method may be a better option for you.
|
||||
The [dashboard-icons](https://github.com/walkxcode/Dashboard-Icons) repo by [@WalkxCode](https://github.com/WalkxCode) provides a comprehensive collection of 360+ high-quality PNG icons for commonly self-hosted services. Dashy natively supports these icons, and you can use them just by specifying the icon name (without extension) preceded by `hl-`. See [here](https://github.com/walkxcode/Dashboard-Icons/tree/main/png) for a full list of all available icons. Note that these are fetched and cached straight from GitHub, so if you require offline access, the [Local Icons](#local-icons) method may be a better option for you.
|
||||
|
||||
For example:
|
||||
|
||||
|
@ -8,9 +8,9 @@ You can edit additional pages using the interactive editor, exactly the same was
|
||||
|
||||
### Using Local Sub-Pages
|
||||
|
||||
To get started, create a new `.yml` config file for your sub-page, placing it within `/app/public`. Then within your primary `conf.yml`, choose a name, and specify the path to the new file.
|
||||
To get started, create a new `.yml` config file for your sub-page, placing it within `/app/user-data`. Then within your primary `conf.yml`, choose a name, and specify the path to the new file.
|
||||
|
||||
For example:
|
||||
This is an example. Make sure to add this to the topmost line above appConfig:, or anywhere else appropriately, to match the yml syntax.
|
||||
|
||||
```yaml
|
||||
pages:
|
||||
@ -20,7 +20,17 @@ pages:
|
||||
path: 'work.yml'
|
||||
```
|
||||
|
||||
If you're sub-page is located within `/app/public`, then you only need to specify the filename, but if it's anywhere else, then the full path is required.
|
||||
The next step is to create the new page, if you mounted `/app/user-data` in the docker command and not a volume, you can simply create the new page into that folder on the host.
|
||||
|
||||
If you mounted `/app/user-data/conf.yml` in docker, you can either switch to the volume or create another bind mount to your new additional page.
|
||||
|
||||
If you're sub-page is located within `/app/user-data`, then you only need to specify the filename, but if it's anywhere else, then the full path is required.
|
||||
|
||||
A default template a page can be found here: [https://github.com/lissy93/dashy/blob/master/user-data/conf.yml](https://github.com/lissy93/dashy/blob/master/user-data/conf.yml) Keep in mind the appConfig cannot be used on subpages and should be removed, for further info see [Restrictions](#restrictions)
|
||||
|
||||
The last very important step is to rebuild dashy, this can be easily done through to UI, by opening the settings menu on the top right, navigato to update config and then recompile application.
|
||||
|
||||
Now if you reload the page, on the top right there should be a new button to navigate to the new page. 🎉
|
||||
|
||||
### Using Remote Sub-Pages
|
||||
|
||||
@ -71,7 +81,7 @@ A normal section will contain zero or more items, for example:
|
||||
url: http://stackoverflow.com/
|
||||
```
|
||||
|
||||
But items can also be grouped together, referred to as sub-items. This is useful for a group of less frequently used items, which you don't want to take up too much space, or for action buttons (_coming soon_).
|
||||
But items can also be grouped together, referred to as sub-items. This is useful for a group of less frequently used items, which you don't want to take up too much space.
|
||||
|
||||
Item groups may also have an optional title.
|
||||
|
||||
|
@ -118,9 +118,10 @@ Dashy supports [Widgets](/docs/widgets.md) for displaying dynamic content. Below
|
||||
- [OWM Privacy Policy](https://openweather.co.uk/privacy-policy)
|
||||
- **[RSS Feed](/docs/widgets.md#rss-feed)**: `https://api.rss2json.com/v1/api.json`
|
||||
- [Rss2Json Privacy Policy](https://rss2json.com/privacy-policy)
|
||||
- **[IP Address](/docs/widgets.md#public-ip)**: `https://ipapi.co/json` or `http://ip-api.com/json`
|
||||
- **[IP Address](/docs/widgets.md#public-ip)**: `https://ipapi.co/json` or `http://ip-api.com/json` or `https://api.ip2location.io/`
|
||||
- [IPGeoLocation Privacy Policy](https://ipgeolocation.io/privacy.html)
|
||||
- [IP-API Privacy Policy](https://ip-api.com/docs/legal)
|
||||
- [IP2Location.io Privacy Policy](https://ip2location.io/privacy-policy)
|
||||
- **[IP Blacklist](/docs/widgets.md#ip-blacklist)**: `https://api.blacklistchecker.com`
|
||||
- [Blacklist Checker Privacy Policy](https://blacklistchecker.com/privacy)
|
||||
- **[Domain Monitor](/docs/widgets.md#domain-monitor)**: `http://api.whoapi.com`
|
||||
@ -131,8 +132,8 @@ Dashy supports [Widgets](/docs/widgets.md) for displaying dynamic content. Below
|
||||
- [BlockCypher Privacy Policy](https://www.blockcypher.com/privacy.html)
|
||||
- **[Code::Stats](/docs/widgets.md#code-stats)**: `https://codestats.net`
|
||||
- [Code::Stats Privacy Policy](https://codestats.net/tos#privacy)
|
||||
- **[AnonAddy](/docs/widgets.md#anonaddy)**: `https://app.anonaddy.com`
|
||||
- [AnonAddy Privacy Policy](https://anonaddy.com/privacy/)
|
||||
- **[addy.io](/docs/widgets.md#addyio)**: `https://app.addy.io`
|
||||
- [addy.io Privacy Policy](https://addy.io/privacy/)
|
||||
- **[Vulnerability Feed](/docs/widgets.md#vulnerability-feed)**: `https://www.cvedetails.com`
|
||||
- [CVE Details Privacy Policy](https://www.cvedetails.com/privacy.php)
|
||||
- **[Exchange Rate](/docs/widgets.md#exchange-rates)**: `https://v6.exchangerate-api.com`
|
||||
|
100
docs/widgets.md
@ -18,7 +18,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
|
||||
- [Crypto Wallet Balance](#wallet-balance)
|
||||
- [Code Stats](#code-stats)
|
||||
- [Mullvad Status](#mullvad-status)
|
||||
- [Email Aliases (AnonAddy)](#anonaddy)
|
||||
- [Email Aliases (addy.io)](#addyio)
|
||||
- [Vulnerability Feed](#vulnerability-feed)
|
||||
- [Exchange Rates](#exchange-rates)
|
||||
- [Public Holidays](#public-holidays)
|
||||
@ -40,6 +40,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
|
||||
- [Mvg Connection](#mvg-connection)
|
||||
- [Custom search](#custom-search)
|
||||
- [Rescuetime overview](#rescuetime-overview)
|
||||
- [Minecraft Server](#minecraft-server)
|
||||
- **[Self-Hosted Services Widgets](#self-hosted-services-widgets)**
|
||||
- [System Info](#system-info)
|
||||
- [Cron Monitoring](#cron-monitoring-health-checks)
|
||||
@ -67,6 +68,7 @@ Dashy has support for displaying dynamic content in the form of widgets. There a
|
||||
- [Drone CI Build](#drone-ci-builds)
|
||||
- [Linkding](#linkding)
|
||||
- [Uptime Kuma](#uptime-kuma)
|
||||
- [Tactical RMM](#tactical-rmm)
|
||||
- **[System Resource Monitoring](#system-resource-monitoring)**
|
||||
- [CPU Usage Current](#current-cpu-usage)
|
||||
- [CPU Usage Per Core](#cpu-usage-per-core)
|
||||
@ -287,7 +289,7 @@ Unless image fetched from remote source, no external data request is made.
|
||||
|
||||
### Public IP
|
||||
|
||||
Often find yourself searching "What's my IP", just so you can check your VPN is still connected? This widget displays your public IP address, along with ISP name and approx location. Data can be fetched from either [IpApi.co](https://ipapi.co/), [IP-API.com](https://ip-api.com/) or [IpGeolocation.io](https://ipgeolocation.io/).
|
||||
Often find yourself searching "What's my IP", just so you can check your VPN is still connected? This widget displays your public IP address, along with ISP name and approx location. Data can be fetched from either [IpApi.co](https://ipapi.co/), [IP-API.com](https://ip-api.com/), [IpGeolocation.io](https://ipgeolocation.io/) or [IP2Location.io](https://ip2location.io/).
|
||||
|
||||
<p align="center"><img width="400" src="https://i.ibb.co/vc3c8zN/public-ip.png" /></p>
|
||||
|
||||
@ -297,8 +299,8 @@ _All fields are optional._
|
||||
|
||||
**Field** | **Type** | **Required** | **Description**
|
||||
--- | --- | --- | ---
|
||||
**`provider`** | `string` | _Optional_ | The name of the service to fetch IP address from. Can be either `ipapi.co`, `ip-api` or `ipgeolocation`. Defaults to `ipapi.co`. Note, `ip-api` doesn't work on HTTPS, and if you set to `ipgeolocation` then you must also provide an API key
|
||||
**`apiKey`** | `string` | _Optional_ | Only required if provider is set to `ipgeolocation`. You can get a free API key [here](https://ipgeolocation.io/signup.html)
|
||||
**`provider`** | `string` | _Optional_ | The name of the service to fetch IP address from. Can be either `ipapi.co`, `ip-api`, `ipgeolocation` or `ip2location.io`. Defaults to `ipapi.co`. Note, `ip-api` doesn't work on HTTPS, and if you set to `ipgeolocation` or `ip2location.io` then you must also provide an API key
|
||||
**`apiKey`** | `string` | _Optional_ | Only required if provider is set to `ipgeolocation` or `ip2location.io`. You can get a free IPGeolocation API key [here](https://ipgeolocation.io/signup.html) or a free IP2Location.io API key [here](https://ip2location.io/pricing)
|
||||
|
||||
#### Example
|
||||
|
||||
@ -321,7 +323,7 @@ Or
|
||||
- **Auth**: 🟠 Optional
|
||||
- **Price**: 🟢 Free
|
||||
- **Host**: Managed Instance Only
|
||||
- **Privacy**: _See [IPGeoLocation Privacy Policy](https://ipgeolocation.io/privacy.html) or [IP-API Privacy Policy](https://ip-api.com/docs/legal)_
|
||||
- **Privacy**: _See [IPGeoLocation Privacy Policy](https://ipgeolocation.io/privacy.html) or [IP-API Privacy Policy](https://ip-api.com/docs/legal) or [IP2Location.io Privacy Policy](https://ip2location.io/privacy-policy)
|
||||
|
||||
---
|
||||
|
||||
@ -573,11 +575,11 @@ _No Options._
|
||||
|
||||
---
|
||||
|
||||
### AnonAddy
|
||||
### addy.io
|
||||
|
||||
[AnonAddy](https://anonaddy.com/) is a free and open source mail forwarding service. Use it to protect your real email address, by using a different alias for each of your online accounts, and have all emails land in your normal inbox(es). Supports custom domains, email replies, PGP-encryption, multiple recipients and more
|
||||
[addy.io](https://addy.io/) is a free and open source mail forwarding service. Use it to protect your real email address, by using a different alias for each of your online accounts, and have all emails land in your normal inbox(es). Supports custom domains, email replies, PGP-encryption, multiple recipients and more
|
||||
|
||||
This widget display email addresses / aliases from AnonAddy. Click an email address to copy to clipboard, or use the toggle switch to enable/ disable it. Shows usage stats (bandwidth, used aliases etc), as well as total messages received, blocked and sent. Works with both self-hosted and managed instances of AnonAddy.
|
||||
This widget display email addresses / aliases from addy.io. Click an email address to copy to clipboard, or use the toggle switch to enable/ disable it. Shows usage stats (bandwidth, used aliases etc), as well as total messages received, blocked and sent. Works with both self-hosted and managed instances of addy.io.
|
||||
|
||||
<p align="center"><img width="400" src="https://i.ibb.co/ZhfyRdV/anonaddy.png" /></p>
|
||||
|
||||
@ -585,8 +587,8 @@ This widget display email addresses / aliases from AnonAddy. Click an email addr
|
||||
|
||||
**Field** | **Type** | **Required** | **Description**
|
||||
--- | --- | --- | ---
|
||||
**`apiKey`** | `string` | Required | Your AnonAddy API Key / Personal Access Token. You can generate this under [Account Settings](https://app.anonaddy.com/settings)
|
||||
**`hostname`** | `string` | _Optional_ | If your self-hosting AnonAddy, then supply the host name. By default it will use the public hosted instance
|
||||
**`apiKey`** | `string` | Required | Your addy.io API Key / Personal Access Token. You can generate this under [Account Settings](https://app.addy.io/settings)
|
||||
**`hostname`** | `string` | _Optional_ | If your self-hosting addy.io, then supply the host name. By default it will use the public hosted instance
|
||||
**`apiVersion`** | `string` | _Optional_ | If you're using an API version that is not version `v1`, then specify it here
|
||||
**`limit`** | `number` | _Optional_ | Limit the number of emails shown per page. Defaults to `10`
|
||||
**`sortBy`** | `string` | _Optional_ | Specify the sort order for email addresses. Defaults to `updated_at`. Can be either: `local_part`, `domain`, `email`, `emails_forwarded`, `emails_blocked`, `emails_replied`, `emails_sent`, `created_at`, `updated_at` or `deleted_at`. Precede with a `-` character to reverse order.
|
||||
@ -614,7 +616,7 @@ This widget display email addresses / aliases from AnonAddy. Click an email addr
|
||||
- **Auth**: 🔴 Required
|
||||
- **Price**: 🟠 Free for Self-Hosted / Free Plan available on managed instance or $1/month for premium
|
||||
- **Host**: Self-Hosted or Managed
|
||||
- **Privacy**: _See [AnonAddy Privacy Policy](https://anonaddy.com/privacy/)_
|
||||
- **Privacy**: _See [addy.io Privacy Policy](https://addy.io/privacy/)_
|
||||
|
||||
---
|
||||
|
||||
@ -1377,6 +1379,45 @@ Show an overview of how you have spent your time for the current day.
|
||||
|
||||
---
|
||||
|
||||
### Minecraft Server
|
||||
|
||||
Show minecraft server status
|
||||
|
||||
<p align="center"><img width="380" src="https://i.ibb.co/hcmd4Wf/minecraft-widget.png" /></p>
|
||||
|
||||
#### Options
|
||||
|
||||
**Field** | **Type** | **Required** | **Description**
|
||||
--- | --- | --- | ---
|
||||
**`title`** | `string` | _Optional_ | Display title for server uses server address if not set.
|
||||
**`server`** | `string` | Required | Server hostname or ip(:port) will use srv records.
|
||||
**`bedrock`** | `boolean` | _Optional_ | If server is a bedrock edition server. (default false)
|
||||
**`showMods`** | `boolean` | _Optional_ | Display mod list if available
|
||||
**`showPlayers`** | `boolean` | _Optional_ | Display player list if available
|
||||
**`showPlugins`** | `boolean` | _Optional_ | Display plugin list if available
|
||||
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
- type: minecraft-status
|
||||
options:
|
||||
title: Venity Network
|
||||
server: play.venitymc.com
|
||||
bedrock: true
|
||||
showMods: true
|
||||
showPlayers: true
|
||||
showPlugins: true
|
||||
```
|
||||
#### Info
|
||||
|
||||
- **CORS**: 🟢 Enabled
|
||||
- **Auth**: 🟢 Not Required
|
||||
- **Price**: 🟢 Free
|
||||
- **Host**: [Minecraft Server Status](https://mcsrvstat.us/)
|
||||
- **Privacy**: _See [Minecraft Server Status FAQ](https://mcsrvstat.us/faq)_
|
||||
|
||||
---
|
||||
|
||||
|
||||
|
||||
## Self-Hosted Services Widgets
|
||||
@ -2333,6 +2374,41 @@ Linkding is a self-hosted bookmarking service, which has a clean interface and i
|
||||
- **Host**: Self-Hosted (see [Uptime Kuma](https://github.com/louislam/uptime-kuma) )
|
||||
- **Privacy**: _See [Uptime Kuma](https://github.com/louislam/uptime-kuma)_
|
||||
|
||||
---
|
||||
|
||||
### Tactical RMM
|
||||
|
||||
[Tactical RMM](https://github.com/amidaware/tacticalrmm) is a self-hosted remote monitoring & management tool.
|
||||
|
||||
<p align="center"><a href="https://ibb.co/NVHWpD1"><img src="https://i.ibb.co/ng5Qfd3/Capture.png" alt="Capture" border="0"></a></p>
|
||||
|
||||
|
||||
#### Options
|
||||
|
||||
| **Field** | **Type** | **Required** | **Description** |
|
||||
| ------------ | -------- | ------------ | ------------------------------------------------------------------------ |
|
||||
| **`url`** | `string` | Required | The status endpoint URL (https://api.example.com/core/status/) |
|
||||
| **`token`** | `string` | Required | The MON_TOKEN (see https://docs.tacticalrmm.com/tipsntricks/#monitor-your-trmm-instance-via-the-built-in-monitoring-endpoint). |
|
||||
|
||||
#### Example
|
||||
|
||||
```yaml
|
||||
- type: trmm
|
||||
useProxy: true
|
||||
options:
|
||||
token: PkPVKMzbmXgeQDlJWb0WXYvsIk3JvZyadURud2cSTdMia6hUbQ
|
||||
url: https://api.example.com/core/status/
|
||||
```
|
||||
|
||||
#### Info
|
||||
|
||||
- **CORS**: 🟠 Proxied
|
||||
- **Auth**: 🟢 Required
|
||||
- **Price**: 🟢 Free
|
||||
- **Host**: Self-Hosted (see [Tactical RMM](https://github.com/amidaware/tacticalrmm) )
|
||||
- **Privacy**: _See [Tactical RMM](https://github.com/amidaware/tacticalrmm)_
|
||||
|
||||
|
||||
---
|
||||
|
||||
## System Resource Monitoring
|
||||
@ -2364,7 +2440,7 @@ Here an example for Docker
|
||||
|
||||
Glances can be launched with the `glances` command. You'll need to run it in web server mode, using the `-w` option for the API to be reachable. If you don't plan on using the Web UI, then you can disable it using `--disable-webui`. See the [command reference docs](https://glances.readthedocs.io/en/latest/cmds.html) for more info.
|
||||
|
||||
If Glaces is running on a Windows system it is recommanded to add the following arguments ```--disable-plugin all --enable-plugin cpu,mem,diskio,ip,network,containers,quicklook,load,fs,alert -w``` This is due to Glances not being that stable on windows, so disabling all plugins that aren't used by Dashy widgets can save on ressources.
|
||||
If Glances is running on a Windows system it is recommanded to add the following arguments ```--disable-plugin all --enable-plugin cpu,mem,diskio,ip,network,containers,quicklook,load,fs,alert -w``` This is due to Glances not being that stable on windows, so disabling all plugins that aren't used by Dashy widgets can save on ressources.
|
||||
|
||||
#### Options
|
||||
|
||||
|
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "dashy",
|
||||
"version": "3.0.1",
|
||||
"version": "3.1.1",
|
||||
"license": "MIT",
|
||||
"main": "server",
|
||||
"author": "Alicia Sykes <alicia@omg.lol> (https://aliciasykes.com)",
|
||||
@ -30,11 +30,12 @@
|
||||
"frappe-charts": "^1.6.2",
|
||||
"js-yaml": "^4.1.0",
|
||||
"keycloak-js": "^20.0.3",
|
||||
"oidc-client-ts": "^3.0.1",
|
||||
"register-service-worker": "^1.7.2",
|
||||
"remedial": "^1.0.8",
|
||||
"rss-parser": "3.13.0",
|
||||
"rsup-progress": "^3.2.0",
|
||||
"simple-icons": "^7.19.0",
|
||||
"simple-icons": "^12.2.0",
|
||||
"v-jsoneditor": "^1.4.5",
|
||||
"v-tooltip": "^2.1.3",
|
||||
"vue": "^2.7.0",
|
||||
|
@ -5,9 +5,11 @@
|
||||
<meta charset="utf-8">
|
||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
||||
<meta name="viewport" content="width=device-width,initial-scale=1.0">
|
||||
<meta name="referrer" content="no-referrer">
|
||||
<!-- Favicon, App Icon -->
|
||||
<link rel="icon" type="image/png" sizes="64x64" href="<%= BASE_URL %>/web-icons/favicon-64x64.png">
|
||||
<link rel="icon" type="image/png" sizes="32x32" href="web-icons/favicon-32x32.png">
|
||||
<link rel="icon" type="image/png" sizes="16x16" href="web-icons/favicon-16x16.png">
|
||||
<link rel="icon" type="image/png" href="/favicon.ico" />
|
||||
<link rel="stylesheet" type="text/css" href="/loading-screen.css" />
|
||||
<!-- Default Page Title -->
|
||||
|
BIN
public/web-icons/favicon-16x16.png
Normal file
After Width: | Height: | Size: 794 B |
Before Width: | Height: | Size: 2.0 KiB After Width: | Height: | Size: 2.0 KiB |
Before Width: | Height: | Size: 5.5 KiB After Width: | Height: | Size: 5.3 KiB |
@ -5,7 +5,7 @@
|
||||
const { exec } = require('child_process');
|
||||
|
||||
module.exports = () => new Promise((resolve, reject) => {
|
||||
const buildProcess = exec('npm run build'); // Trigger the build command
|
||||
const buildProcess = exec('NODE_OPTIONS="--max-old-space-size=512" npm run build'); // Trigger the build command
|
||||
|
||||
let output = ''; // Will store console output
|
||||
|
||||
|
@ -34,6 +34,8 @@
|
||||
:statusSuccess="statusResponse ? statusResponse.successStatus : undefined"
|
||||
:statusText="statusResponse ? statusResponse.message : undefined"
|
||||
/>
|
||||
<!-- URL of the item (shown on hover, only on some themes) -->
|
||||
<p class="item-url">{{ item.url | shortUrl }}</p>
|
||||
<!-- Edit icon (displayed only when in edit mode) -->
|
||||
<EditModeIcon v-if="isEditMode" class="edit-mode-item" @click="openItemSettings()" />
|
||||
</a>
|
||||
@ -122,6 +124,26 @@ export default {
|
||||
}
|
||||
},
|
||||
},
|
||||
filters: {
|
||||
shortUrl(value) {
|
||||
if (!value || typeof value !== 'string') {
|
||||
return '';
|
||||
}
|
||||
try {
|
||||
// Use URL constructor to parse the input
|
||||
const url = new URL(value);
|
||||
return url.hostname;
|
||||
} catch (e) {
|
||||
// If the input is not a valid URL, try to handle it as an IP address
|
||||
const ipPattern = /^(\d{1,3}\.){3}\d{1,3}/;
|
||||
const match = value.match(ipPattern);
|
||||
if (match) {
|
||||
return match[0];
|
||||
}
|
||||
return '';
|
||||
}
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
editMenuOpen: false,
|
||||
@ -209,6 +231,9 @@ export default {
|
||||
&.span-7 { min-width: 14%; }
|
||||
&.span-8 { min-width: 12.5%; }
|
||||
}
|
||||
.item-url {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
|
||||
.item {
|
||||
|
@ -21,7 +21,6 @@
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import simpleIcons from 'simple-icons';
|
||||
import BrokenImage from '@/assets/interface-icons/broken-icon.svg';
|
||||
import ErrorHandler from '@/utils/ErrorHandler';
|
||||
import EmojiUnicodeRegex from '@/utils/EmojiUnicodeRegex';
|
||||
@ -29,6 +28,8 @@ import emojiLookup from '@/utils/emojis.json';
|
||||
import { asciiHash } from '@/utils/MiscHelpers';
|
||||
import { faviconApi as defaultFaviconApi, faviconApiEndpoints, iconCdns } from '@/utils/defaults';
|
||||
|
||||
const simpleicons = require('simple-icons');
|
||||
|
||||
export default {
|
||||
name: 'Icon',
|
||||
props: {
|
||||
@ -186,8 +187,8 @@ export default {
|
||||
},
|
||||
/* Returns the SVG path content */
|
||||
getSimpleIcon(img) {
|
||||
const imageName = img.replace('si-', '');
|
||||
const icon = simpleIcons.Get(imageName);
|
||||
const imageName = img.charAt(3).toUpperCase() + img.slice(4);
|
||||
const icon = simpleicons[`si${imageName}`];
|
||||
if (!icon) {
|
||||
this.imageNotFound(`No icon was found for '${imageName}' in Simple Icons`);
|
||||
return null;
|
||||
|
@ -24,6 +24,13 @@
|
||||
v-tooltip="tooltip($t('settings.sign-out-tooltip'))"
|
||||
class="layout-icon" tabindex="-2"
|
||||
/>
|
||||
<!-- If user logged in via oidc, show oidc logout button -->
|
||||
<IconLogout
|
||||
v-if="userType == userStateEnum.oidcEnabled"
|
||||
@click="oidcLogout()"
|
||||
v-tooltip="tooltip($t('settings.sign-out-tooltip'))"
|
||||
class="layout-icon" tabindex="-2"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
@ -32,6 +39,7 @@
|
||||
import router from '@/router';
|
||||
import { logout as registerLogout } from '@/utils/Auth';
|
||||
import { getKeycloakAuth } from '@/utils/KeycloakAuth';
|
||||
import { getOidcAuth } from '@/utils/OidcAuth';
|
||||
import { localStorageKeys, userStateEnum } from '@/utils/defaults';
|
||||
import IconLogout from '@/assets/interface-icons/user-logout.svg';
|
||||
|
||||
@ -56,6 +64,13 @@ export default {
|
||||
router.push({ path: '/login' });
|
||||
}, 500);
|
||||
},
|
||||
oidcLogout() {
|
||||
const oidc = getOidcAuth();
|
||||
this.$toasted.show(this.$t('login.logout-message'));
|
||||
setTimeout(() => {
|
||||
oidc.logout();
|
||||
}, 500);
|
||||
},
|
||||
keycloakLogout() {
|
||||
const keycloak = getKeycloakAuth();
|
||||
this.$toasted.show(this.$t('login.logout-message'));
|
||||
|
@ -77,11 +77,11 @@ export default {
|
||||
slug: repo.repo,
|
||||
desc: repo.desc,
|
||||
lang: repo.lang,
|
||||
link: repo.repo_link,
|
||||
link: `https://github.com/${repo.repo}`,
|
||||
stars: repo.stars,
|
||||
forks: repo.forks,
|
||||
newStars: parseInt(repo.added_stars, 10),
|
||||
avatar: repo.avatars[0] || 'https://github.com/fluidicon.png',
|
||||
newStars: repo.change,
|
||||
avatar: repo.build_by[0] || 'https://github.com/fluidicon.png',
|
||||
});
|
||||
});
|
||||
if (this.limit && this.limit < results.length) {
|
||||
|
@ -68,11 +68,11 @@ export default {
|
||||
networks.push({
|
||||
name: network.interface_name,
|
||||
speed: network.speed,
|
||||
online: network.is_up ? 'up' : 'down',
|
||||
currentDownload: network.rx,
|
||||
currentUpload: network.tx,
|
||||
totalDownload: network.cumulative_rx,
|
||||
totalUpload: network.cumulative_tx,
|
||||
online: network.speed ? 'up' : 'down', //v3 to v4 is_up no longer seems to be a default response field
|
||||
currentDownload: network.bytes_recv,
|
||||
currentUpload: network.bytes_sent,
|
||||
totalDownload: network.bytes_recv_gauge,
|
||||
totalUpload: network.bytes_sent_gauge,
|
||||
changeDownload: this.previous && network.rx > this.previous[index].rx,
|
||||
changeUpload: this.previous && network.tx > this.previous[index].tx,
|
||||
});
|
||||
|
@ -33,8 +33,8 @@ export default {
|
||||
/* eslint-disable prefer-destructuring */
|
||||
Object.keys(trafficData).forEach((keyName) => {
|
||||
let upOrDown = null;
|
||||
if (keyName.includes('_tx')) upOrDown = 'up';
|
||||
else if (keyName.includes('_rx')) upOrDown = 'down';
|
||||
if (keyName.includes('_sent')) upOrDown = 'up';
|
||||
else if (keyName.includes('_recv')) upOrDown = 'down';
|
||||
trafficData[keyName].forEach((dataPoint) => {
|
||||
const dataTime = this.getRoundedTime(dataPoint[0]);
|
||||
if (upOrDown === 'up') {
|
||||
|
@ -45,8 +45,17 @@ export default {
|
||||
/* Refreshes iframe contents, called by parent */
|
||||
update() {
|
||||
this.startLoading();
|
||||
this.updateCount += 1;
|
||||
(document.getElementById(this.frameId) || {}).src = this.frameUrl;
|
||||
const iframe = document.getElementById(this.frameId);
|
||||
if (iframe.contentWindow) {
|
||||
try {
|
||||
iframe.contentWindow.location.href = this.frameUrl;
|
||||
iframe.contentWindow.location.reload(true);
|
||||
} catch (e) {
|
||||
this.error('Failed to refresh iframe', e, true);
|
||||
}
|
||||
} else {
|
||||
this.error('Couldn\'t find iframe', null, true);
|
||||
}
|
||||
this.finishLoading();
|
||||
},
|
||||
},
|
||||
|
258
src/components/Widgets/MinecraftStatus.vue
Normal file
@ -0,0 +1,258 @@
|
||||
<template>
|
||||
<div class="minecraft-wrapper">
|
||||
<a class="minecraft-link" :href="serverLinkEndpoint">
|
||||
<h3 class="minecraft-title">{{ title }}</h3>
|
||||
</a>
|
||||
<div class="minecraft-icon-wrapper">
|
||||
<img :src="icon" alt="server-icon" class="minecraft-icon" />
|
||||
</div>
|
||||
<div class="minecraft-content-wrapper">
|
||||
<StatusIndicator class="status-indicator" :statusSuccess="status ? online : undefined"
|
||||
:statusText="status ? statusTooltip : undefined" />
|
||||
<span v-if="title != server" class="minecraft-server">{{ server }}<br /></span>
|
||||
<span v-if="!online" class="minecraft-status">Server Offline</span>
|
||||
<span v-if="online" class="minecraft-version">
|
||||
{{ software || (bedrock ? "Bedrock" : "Minecraft") }} {{ version }}
|
||||
</span>
|
||||
<ul v-if="online" class="minecraft-motd">
|
||||
<li v-for="(line, idx) in motd" :key="idx">{{ line }}</li>
|
||||
</ul>
|
||||
<div v-if="showPlayers" class="player-list">
|
||||
<span>{{ onlinePlayers }}/{{ maxPlayers }} Players</span>
|
||||
<ul>
|
||||
<li v-for="{ name, uuid } in players" :key="uuid">
|
||||
<a :href="playerLinkEndpoint(uuid)">
|
||||
<img :src="playerIconEndpoint(uuid)" :alt="`${name}'s Head'`"/>{{ name }}
|
||||
</a>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="showMods" class="mod-list">
|
||||
<span>{{ mods.length }} Mods</span>
|
||||
<ul>
|
||||
<li v-for="{ name, version } in mods" :key="name">
|
||||
{{ name }}={{ version }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
<div v-if="showPlugins" class="plugin-list">
|
||||
<span>{{ plugins.length }} Plugins</span>
|
||||
<ul>
|
||||
<li v-for="{ name, version } in plugins" :key="name">
|
||||
{{ name }}={{ version }}
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||
import { widgetApiEndpoints } from '@/utils/defaults';
|
||||
import StatusIndicator from '@/components/LinkItems/StatusIndicator.vue';
|
||||
|
||||
export default {
|
||||
mixins: [WidgetMixin],
|
||||
components: {
|
||||
StatusIndicator,
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
status: false,
|
||||
online: false,
|
||||
ip: '',
|
||||
port: 0,
|
||||
hostname: '',
|
||||
iconData: null,
|
||||
motd: null,
|
||||
version: null,
|
||||
software: null,
|
||||
gamemode: null,
|
||||
mods: [],
|
||||
plugins: [],
|
||||
players: [],
|
||||
onlinePlayers: null,
|
||||
maxPlayers: null,
|
||||
};
|
||||
},
|
||||
computed: {
|
||||
title() {
|
||||
return this.options.title || this.options.server || this.error('options.server not set');
|
||||
},
|
||||
alt() {
|
||||
return this.title;
|
||||
},
|
||||
icon() {
|
||||
return `https://api.mcsrvstat.us/icon/${this.server}`;
|
||||
},
|
||||
server() {
|
||||
return this.options.server || this.error('options.server not set');
|
||||
},
|
||||
bedrock() {
|
||||
return this.options.bedrock === true;
|
||||
},
|
||||
statusTooltip() {
|
||||
if (!this.status) {
|
||||
return 'Loading...';
|
||||
}
|
||||
if (!this.online) {
|
||||
return `${this.server} Offline`;
|
||||
}
|
||||
return `${this.onlinePlayers}/${this.maxPlayers} Online`;
|
||||
},
|
||||
showPlayers() {
|
||||
return this.options.showPlayers && this.players.length > 0;
|
||||
},
|
||||
showMods() {
|
||||
return this.options.showMods && this.mods.length > 0;
|
||||
},
|
||||
showPlugins() {
|
||||
return this.options.showPlugins && this.plugins.length > 0;
|
||||
},
|
||||
endpoint() {
|
||||
return `${widgetApiEndpoints.minecraftStatus}${this.bedrock ? 'bedrock/' : ''}3/${this.server}`;
|
||||
},
|
||||
serverLinkEndpoint() {
|
||||
return `${widgetApiEndpoints.minecraftServerLink}${this.server}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
playerIconEndpoint(uuid) {
|
||||
return `${widgetApiEndpoints.minecraftPlayerIcon}${uuid}/32.png`;
|
||||
},
|
||||
playerLinkEndpoint(uuid) {
|
||||
return `${widgetApiEndpoints.minecraftPlayerLink}${uuid}`;
|
||||
},
|
||||
/* Make GET request to McSrvStat.US API endpoint */
|
||||
fetchData() {
|
||||
this.startLoading();
|
||||
fetch(this.endpoint)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
this.error('Network response was not ok');
|
||||
}
|
||||
return response.json();
|
||||
})
|
||||
.then(data => {
|
||||
this.processData(data);
|
||||
})
|
||||
.catch(dataFetchError => {
|
||||
this.error('Unable to fetch data', dataFetchError);
|
||||
})
|
||||
.finally(() => {
|
||||
this.finishLoading();
|
||||
});
|
||||
},
|
||||
/* Assign data variables to the returned data */
|
||||
processData(data) {
|
||||
this.online = data.online;
|
||||
this.ip = data.ip;
|
||||
this.port = data.port;
|
||||
this.hostname = data.hostname;
|
||||
if (this.online) {
|
||||
this.version = data.version;
|
||||
this.iconData = data.icon;
|
||||
this.software = data.software;
|
||||
this.gamemode = data.gamemode;
|
||||
this.motd = data.motd.clean || [];
|
||||
this.players = data.players.list || [];
|
||||
this.onlinePlayers = data.players.online;
|
||||
this.maxPlayers = data.players.max;
|
||||
this.mods = data.mods || [];
|
||||
this.plugins = data.plugins || [];
|
||||
}
|
||||
this.status = true;
|
||||
},
|
||||
update() {
|
||||
this.fetchData();
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
|
||||
.minecraft-wrapper {
|
||||
margin-top: -1em;
|
||||
display: grid;
|
||||
justify-content: center;
|
||||
grid-template-columns: 64px 1fr;
|
||||
color: var(--widget-text-color);
|
||||
padding-top: 0.5rem;
|
||||
|
||||
.minecraft-link {
|
||||
grid-column: 1 / span 2;
|
||||
text-decoration: none;
|
||||
|
||||
.minecraft-title {
|
||||
font-size: 1.2rem;
|
||||
margin: 0.25rem auto;
|
||||
border-bottom: 1px solid var(--widget-text-color);
|
||||
color: var(--widget-text-color);
|
||||
}
|
||||
}
|
||||
|
||||
.minecraft-icon {
|
||||
display: flex;
|
||||
width: 100%;
|
||||
max-width: 64px;
|
||||
margin: 0.25rem auto 0;
|
||||
padding-top: 0.5rem;
|
||||
border-radius: var(--curve-factor);
|
||||
}
|
||||
|
||||
.minecraft-content-wrapper {
|
||||
position: relative;
|
||||
padding: 0.5rem;
|
||||
|
||||
ul.minecraft-motd {
|
||||
border-top: 1px dashed var(--widget-text-color);
|
||||
list-style-type: none;
|
||||
padding: 0.5rem 0;
|
||||
margin: 0.5rem 0 0 0;
|
||||
}
|
||||
|
||||
.player-list,
|
||||
.mod-list,
|
||||
.plugin-list {
|
||||
span {
|
||||
font-size: 1.2rem;
|
||||
border-top: 1px dashed var(--widget-text-color);
|
||||
padding: 0.25rem 0;
|
||||
display: block;
|
||||
}
|
||||
ul {
|
||||
list-style-type: '- ';
|
||||
padding: 0;
|
||||
margin: 0;
|
||||
li {
|
||||
padding: 1rem 0;
|
||||
margin: 0;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.player-list {
|
||||
ul {
|
||||
li {
|
||||
padding: 0;
|
||||
list-style-type: none;
|
||||
img {
|
||||
width: 1rem;
|
||||
height: 1rem;
|
||||
float: left;
|
||||
position: relative;
|
||||
margin-right: 1em;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</style>
|
||||
<style lang="scss">
|
||||
.minecraft-alt-tt {
|
||||
min-width: 20rem;
|
||||
}
|
||||
</style>
|
@ -84,9 +84,12 @@ export default {
|
||||
/* Assign data variables to the returned data */
|
||||
processData(holidays) {
|
||||
const results = [];
|
||||
const makeDate = (date) => timestampToDate(
|
||||
new Date(`${date.year}-${date.month}-${date.day}`).getTime(),
|
||||
);
|
||||
const makeDate = (date) => {
|
||||
const formattedMonth = date.month.toString().padStart(2, '0'); // Ensure two digits
|
||||
const formattedDay = date.day.toString().padStart(2, '0'); // Ensure two digits
|
||||
const dateString = `${date.year}-${formattedMonth}-${formattedDay}T00:00:00`;
|
||||
return timestampToDate(new Date(dateString).getTime());
|
||||
};
|
||||
const formatType = (ht) => capitalize(ht.replaceAll('_', ' '));
|
||||
holidays.forEach((holiday) => {
|
||||
results.push({
|
||||
|
@ -24,6 +24,8 @@ export default {
|
||||
endpoint() {
|
||||
if (this.provider === 'ipgeolocation') {
|
||||
return `${widgetApiEndpoints.publicIp2}?apiKey=${this.apiKey}`;
|
||||
} else if (this.provider === 'ip2location.io') {
|
||||
return `${widgetApiEndpoints.publicIp4}?key=${this.apiKey}`;
|
||||
} else if (this.provider === 'ipapi') {
|
||||
return widgetApiEndpoints.publicIp3;
|
||||
}
|
||||
@ -31,10 +33,11 @@ export default {
|
||||
},
|
||||
apiKey() {
|
||||
if (this.provider === 'ipgeolocation' && !this.options.apiKey) this.error('Missing API Key');
|
||||
if (this.provider === 'ip2location.io' && !this.options.apiKey) this.error('Missing API Key');
|
||||
return this.options.apiKey;
|
||||
},
|
||||
provider() {
|
||||
// Can be either `ip-api`, `ipapi.co` or `ipgeolocation`
|
||||
// Can be either `ip-api`, `ipapi.co`, `ipgeolocation` or `ip2location.io`
|
||||
return this.parseAsEnvVar(this.options.provider) || 'ipapi.co';
|
||||
},
|
||||
},
|
||||
@ -72,6 +75,12 @@ export default {
|
||||
this.location = `${ipInfo.city}, ${ipInfo.regionName}`;
|
||||
this.flagImg = getCountryFlag(ipInfo.countryCode);
|
||||
this.mapsUrl = getMapUrl({ lat: ipInfo.lat, lon: ipInfo.lon });
|
||||
} else if (this.provider === 'ip2location.io') {
|
||||
this.ipAddr = ipInfo.ip;
|
||||
this.ispName = ipInfo.isp || 'IP2Location.io Starter plan or higher required.';
|
||||
this.location = `${ipInfo.city_name}, ${ipInfo.region_name}`;
|
||||
this.flagImg = getCountryFlag(ipInfo.country_code);
|
||||
this.mapsUrl = getMapUrl({ lat: ipInfo.latitude, lon: ipInfo.longitude });
|
||||
} else {
|
||||
this.error('Unknown API provider fo IP address');
|
||||
}
|
||||
|
227
src/components/Widgets/TacticalRMM.vue
Normal file
@ -0,0 +1,227 @@
|
||||
<template>
|
||||
<div class="status-section">
|
||||
<template v-if="statusData">
|
||||
<div class="status-wrapper">
|
||||
<div class="status-item">
|
||||
<div class="title">Version</div>
|
||||
<div class="value">{{ statusData.version }}</div>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<div class="title">Agent Count</div>
|
||||
<div class="value">{{ statusData.agent_count }}</div>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<div class="title">Client Count</div>
|
||||
<div class="value">{{ statusData.client_count }}</div>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<div class="title">Site Count</div>
|
||||
<div class="value">{{ statusData.site_count }}</div>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<div class="title">Disk Usage</div>
|
||||
<div class="value">{{ statusData.disk_usage_percent }}%</div>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<div class="title">Memory Usage</div>
|
||||
<div class="value">{{ statusData.mem_usage_percent }}%</div>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<div class="title">Days Until Cert Expires</div>
|
||||
<div class="value">{{ statusData.days_until_cert_expires }}</div>
|
||||
</div>
|
||||
<div class="status-item">
|
||||
<div class="title">Cert Expired</div>
|
||||
<div class="value">{{ statusData.cert_expired ? 'Yes' : 'No' }}</div>
|
||||
</div>
|
||||
<div class="status-item services">
|
||||
<div class="title">Services Running</div>
|
||||
<div class="services-list">
|
||||
<div
|
||||
v-for="(status, service) in statusData.services_running"
|
||||
:key="service"
|
||||
class="service"
|
||||
>
|
||||
<span class="service-name">{{ service }}</span>
|
||||
<span :class="['service-status', status ? 'running' : 'stopped']">
|
||||
{{ status ? 'Running' : 'Stopped' }}
|
||||
</span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<template v-if="errorMessage">
|
||||
<div class="error-message">
|
||||
<span class="text">{{ errorMessage }}</span>
|
||||
</div>
|
||||
</template>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import axios from 'axios';
|
||||
import WidgetMixin from '@/mixins/WidgetMixin';
|
||||
import { serviceEndpoints } from '@/utils/defaults';
|
||||
|
||||
export default {
|
||||
mixins: [WidgetMixin],
|
||||
props: {
|
||||
options: {
|
||||
type: Object,
|
||||
default: () => ({}),
|
||||
},
|
||||
},
|
||||
data() {
|
||||
return {
|
||||
statusData: null,
|
||||
errorMessage: null,
|
||||
errorMessageConstants: {
|
||||
missingToken: 'No Token set',
|
||||
missingUrl: 'No URL set',
|
||||
},
|
||||
};
|
||||
},
|
||||
mounted() {
|
||||
this.fetchData();
|
||||
},
|
||||
computed: {
|
||||
token() {
|
||||
return this.parseAsEnvVar(this.options.token);
|
||||
},
|
||||
url() {
|
||||
return this.parseAsEnvVar(this.options.url);
|
||||
},
|
||||
authHeaders() {
|
||||
return {
|
||||
'Content-Type': 'application/json',
|
||||
};
|
||||
},
|
||||
proxyReqEndpoint() {
|
||||
const baseUrl = process.env.VUE_APP_DOMAIN || window.location.origin;
|
||||
return `${baseUrl}${serviceEndpoints.corsProxy}`;
|
||||
},
|
||||
},
|
||||
methods: {
|
||||
update() {
|
||||
this.startLoading();
|
||||
this.fetchData();
|
||||
},
|
||||
fetchData() {
|
||||
const {
|
||||
authHeaders, url, token, proxyReqEndpoint,
|
||||
} = this;
|
||||
|
||||
if (!this.optionsValid({ url, token })) {
|
||||
return;
|
||||
}
|
||||
|
||||
const targetURL = url;
|
||||
const customHeaders = JSON.stringify(authHeaders);
|
||||
|
||||
axios.post(
|
||||
proxyReqEndpoint,
|
||||
{ auth: token },
|
||||
{
|
||||
headers: {
|
||||
'Target-URL': targetURL,
|
||||
CustomHeaders: customHeaders,
|
||||
'Content-Type': 'application/json',
|
||||
},
|
||||
},
|
||||
)
|
||||
.then((response) => {
|
||||
this.processData(response.data);
|
||||
})
|
||||
.catch(() => {
|
||||
this.errorMessage = 'Failed to fetch data';
|
||||
})
|
||||
.finally(() => {
|
||||
this.finishLoading();
|
||||
});
|
||||
},
|
||||
processData(response) {
|
||||
this.statusData = response;
|
||||
},
|
||||
optionsValid({ url, token }) {
|
||||
const errors = [];
|
||||
if (!url) {
|
||||
errors.push(this.errorMessageConstants.missingUrl);
|
||||
}
|
||||
if (!token) {
|
||||
errors.push(this.errorMessageConstants.missingToken);
|
||||
}
|
||||
if (errors.length === 0) {
|
||||
return true;
|
||||
}
|
||||
this.errorMessage = errors.join('\n');
|
||||
return false;
|
||||
},
|
||||
},
|
||||
};
|
||||
</script>
|
||||
|
||||
<style scoped lang="scss">
|
||||
.status-section {
|
||||
background-color: var(--item-background);
|
||||
padding: 1em;
|
||||
border-radius: 8px;
|
||||
}
|
||||
|
||||
.status-wrapper {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
justify-content: space-between;
|
||||
color: var(--item-text-color);
|
||||
}
|
||||
|
||||
.status-item {
|
||||
width: 48%;
|
||||
margin: 1em 0;
|
||||
}
|
||||
|
||||
.title {
|
||||
font-weight: bold;
|
||||
color: var(--item-text-color);
|
||||
}
|
||||
|
||||
.value {
|
||||
margin-top: 0.5em;
|
||||
color: var(--item-text-color);
|
||||
}
|
||||
|
||||
.services-list {
|
||||
display: flex;
|
||||
flex-direction: column;
|
||||
}
|
||||
|
||||
.service {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin: 0.5em 0;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
.service-name {
|
||||
font-weight: bold;
|
||||
color: var(--item-text-color);
|
||||
}
|
||||
|
||||
.service-status {
|
||||
margin-left: 1em;
|
||||
}
|
||||
|
||||
.service-status.running {
|
||||
color: var(--success);
|
||||
font-weight: bold;
|
||||
}
|
||||
|
||||
.service-status.stopped {
|
||||
color: var(--danger);
|
||||
}
|
||||
|
||||
.error-message {
|
||||
color: var(--item-text-color);
|
||||
}
|
||||
</style>
|
@ -46,7 +46,7 @@ const COMPAT = {
|
||||
'adguard-filter-status': 'AdGuardFilterStatus',
|
||||
'adguard-stats': 'AdGuardStats',
|
||||
'adguard-top-domains': 'AdGuardTopDomains',
|
||||
anonaddy: 'AnonAddy',
|
||||
anonaddy: 'addy.io',
|
||||
apod: 'Apod',
|
||||
'blacklist-check': 'BlacklistCheck',
|
||||
clock: 'Clock',
|
||||
@ -86,6 +86,7 @@ const COMPAT = {
|
||||
iframe: 'IframeWidget',
|
||||
image: 'ImageWidget',
|
||||
joke: 'Jokes',
|
||||
'minecraft-status': 'MinecraftStatus',
|
||||
'mullvad-status': 'MullvadStatus',
|
||||
mvg: 'Mvg',
|
||||
linkding: 'Linkding',
|
||||
@ -115,6 +116,7 @@ const COMPAT = {
|
||||
'synology-download': 'SynologyDownload',
|
||||
'system-info': 'SystemInfo',
|
||||
'tfl-status': 'TflStatus',
|
||||
trmm: 'TacticalRMM',
|
||||
'uptime-kuma': 'UptimeKuma',
|
||||
'wallet-balance': 'WalletBalance',
|
||||
weather: 'Weather',
|
||||
|
@ -39,11 +39,17 @@ export default {
|
||||
document.removeEventListener('pointerup', onPointerUp);
|
||||
};
|
||||
|
||||
const onPointerMove = () => {
|
||||
clearTimeout(parseInt(el.dataset.longPressTimeout, 10));
|
||||
document.removeEventListener('pointermove', onPointerMove);
|
||||
};
|
||||
|
||||
const onPointerDown = (e) => {
|
||||
// If event was right-click, then immediately trigger
|
||||
if (e.button === 2) return;
|
||||
startTime = Date.now();
|
||||
document.addEventListener('pointerup', onPointerUp);
|
||||
el.addEventListener('pointermove', onPointerMove);
|
||||
el.addEventListener('click', swallowClick);
|
||||
const timeoutDuration = LONG_PRESS_DEFAULT_DELAY;
|
||||
const timeout = setTimeout(triggerEvent, timeoutDuration);
|
||||
|
@ -22,6 +22,7 @@ import clickOutside from '@/directives/ClickOutside'; // Directive for closing p
|
||||
import { toastedOptions, tooltipOptions, language as defaultLanguage } from '@/utils/defaults';
|
||||
import { initKeycloakAuth, isKeycloakEnabled } from '@/utils/KeycloakAuth';
|
||||
import { initHeaderAuth, isHeaderAuthEnabled } from '@/utils/HeaderAuth';
|
||||
import { initOidcAuth, isOidcEnabled } from '@/utils/OidcAuth';
|
||||
import Keys from '@/utils/StoreMutations';
|
||||
import ErrorHandler from '@/utils/ErrorHandler';
|
||||
|
||||
@ -62,7 +63,13 @@ const mount = () => new Vue({
|
||||
}).$mount('#app');
|
||||
|
||||
store.dispatch(Keys.INITIALIZE_CONFIG).then(() => {
|
||||
if (isKeycloakEnabled()) { // If Keycloak is enabled, initialize auth
|
||||
if (isOidcEnabled()) {
|
||||
initOidcAuth()
|
||||
.then(() => mount())
|
||||
.catch((e) => {
|
||||
ErrorHandler('Failed to authenticate with OIDC', e);
|
||||
});
|
||||
} else if (isKeycloakEnabled()) { // If Keycloak is enabled, initialize auth
|
||||
initKeycloakAuth()
|
||||
.then(() => mount())
|
||||
.catch((e) => {
|
||||
|
@ -8,7 +8,7 @@ export default {
|
||||
},
|
||||
/* Optionally specify the API version, defaults to V 3 */
|
||||
apiVersion() {
|
||||
return this.options.apiVersion || 3;
|
||||
return this.options.apiVersion || 4;
|
||||
},
|
||||
/* Optionally specify basic auth credentials for Glances instance */
|
||||
credentials() {
|
||||
|
@ -2,6 +2,7 @@
|
||||
* Mixin that all pre-built and custom widgets extend from.
|
||||
* Manages loading state, error handling, data updates and user options
|
||||
*/
|
||||
import axios from 'axios';
|
||||
import { Progress } from 'rsup-progress';
|
||||
import ErrorHandler from '@/utils/ErrorHandler';
|
||||
import { serviceEndpoints } from '@/utils/defaults';
|
||||
@ -71,9 +72,9 @@ const WidgetMixin = {
|
||||
this.updater = setInterval(() => { this.update(); }, this.updateInterval);
|
||||
},
|
||||
/* Called when an error occurs. Logs to handler, and passes to parent component */
|
||||
error(msg, stackTrace) {
|
||||
error(msg, stackTrace, quite = false) {
|
||||
ErrorHandler(msg, stackTrace);
|
||||
if (!this.options.ignoreErrors) {
|
||||
if (!this.options.ignoreErrors && !quite) {
|
||||
this.$emit('error', msg);
|
||||
}
|
||||
},
|
||||
@ -105,59 +106,27 @@ const WidgetMixin = {
|
||||
const method = protocol || 'GET';
|
||||
const url = this.useProxy ? this.proxyReqEndpoint : endpoint;
|
||||
const data = JSON.stringify(body || {});
|
||||
|
||||
const CustomHeaders = options || {};
|
||||
const headers = new Headers();
|
||||
|
||||
// If using a proxy, set the 'Target-URL' header
|
||||
if (this.useProxy) {
|
||||
headers.append('Target-URL', endpoint);
|
||||
}
|
||||
// Apply widget-specific custom headers
|
||||
Object.entries(CustomHeaders).forEach(([key, value]) => {
|
||||
headers.append(key, value);
|
||||
});
|
||||
|
||||
// If the request is a GET, delete the body
|
||||
const bodyContent = method.toUpperCase() === 'GET' ? undefined : data;
|
||||
|
||||
const CustomHeaders = options || null;
|
||||
const headers = this.useProxy
|
||||
? { 'Target-URL': endpoint, CustomHeaders: JSON.stringify(CustomHeaders) } : CustomHeaders;
|
||||
const timeout = this.options.timeout || this.defaultTimeout;
|
||||
|
||||
// Setup Fetch request configuration
|
||||
const requestConfig = {
|
||||
method,
|
||||
headers,
|
||||
body: bodyContent,
|
||||
signal: undefined, // This will be set below
|
||||
method, url, headers, data, timeout,
|
||||
};
|
||||
|
||||
const controller = new AbortController();
|
||||
const timeoutId = setTimeout(() => controller.abort(), timeout);
|
||||
requestConfig.signal = controller.signal;
|
||||
|
||||
// Make request using Fetch API
|
||||
// Make request
|
||||
return new Promise((resolve, reject) => {
|
||||
fetch(url, requestConfig)
|
||||
.then(async response => {
|
||||
const responseData = await response.json();
|
||||
if (responseData.error) {
|
||||
this.error('Proxy returned error from target server', responseData.error?.message);
|
||||
axios.request(requestConfig)
|
||||
.then((response) => {
|
||||
if (response.data.success === false) {
|
||||
this.error('Proxy returned error from target server', response.data.message);
|
||||
}
|
||||
if (responseData.success === false) {
|
||||
this.error('Proxy didn\'t return success from target server', responseData.message);
|
||||
}
|
||||
resolve(responseData);
|
||||
resolve(response.data);
|
||||
})
|
||||
.catch(error => {
|
||||
if (error.name === 'AbortError') {
|
||||
this.error('Request timed out', error);
|
||||
} else {
|
||||
this.error('Unable to fetch data', error);
|
||||
}
|
||||
reject(error);
|
||||
.catch((dataFetchError) => {
|
||||
this.error('Unable to fetch data', dataFetchError);
|
||||
reject(dataFetchError);
|
||||
})
|
||||
.finally(() => {
|
||||
clearTimeout(timeoutId);
|
||||
this.finishLoading();
|
||||
});
|
||||
});
|
||||
|
@ -1849,6 +1849,88 @@ html[data-theme='neomorphic'] {
|
||||
}
|
||||
|
||||
|
||||
html[data-theme="night-bat"] {
|
||||
// Main colors
|
||||
--primary: #4780ff;
|
||||
--background: #252931;
|
||||
--background-darker: #303540;
|
||||
// Typography
|
||||
--font-headings: 'Podkova', 'Roboto', serif;
|
||||
--font-body: 'Roboto', serif;
|
||||
--heading-text-color: #fff;
|
||||
// Items
|
||||
--item-background: #303540;
|
||||
--item-background-hover: var(--item-background);
|
||||
--item-shadow: 0px 3px 0px var(--primary), 2px 2px 6px var(--black);
|
||||
--item-hover-shadow: 0px 20px 0px 0 var(--primary), 2px 2px 6px var(--black);
|
||||
// Sections
|
||||
--item-group-heading-text-color: var(--white);
|
||||
--item-group-heading-text-color-hover: var(--white);
|
||||
--item-group-shadow: none;
|
||||
--item-group-background: none;
|
||||
--item-group-outer-background: none;
|
||||
// Nav Links
|
||||
--nav-link-background-color: var(--background);
|
||||
--nav-link-background-color-hover: var(--background);
|
||||
--nav-link-border-color: transparent;
|
||||
--nav-link-border-color-hover: transparent;
|
||||
--nav-link-shadow: 4px 4px 0px var(--background-darker), -3px 0px 0px var(--primary), 2px 2px 6px var(--black);
|
||||
--nav-link-shadow-hover: 6px 6px 0px var(--background-darker), -4px 0px 0px var(--primary), 2px 2px 9px var(--black);
|
||||
// Misc
|
||||
--curve-factor: 4px;
|
||||
--curve-factor-navbar: 8px;
|
||||
|
||||
--widget-text-color: var(--white);
|
||||
|
||||
// Style overrides
|
||||
label.lbl-toggle h3 { font-size: 1.3rem; font-weight: bold; }
|
||||
.content-inner { border-top: 1px dashed var(--primary); }
|
||||
.item.size-large .tile-title p.description { height: 3rem; }
|
||||
.item, .nav-outer nav .nav-item { border-radius: 1px; }
|
||||
.item.size-large { margin: 0.5rem; }
|
||||
// Show outline when collapsed
|
||||
.is-collapsed {
|
||||
background: var(--item-background);
|
||||
box-shadow: var(--item-shadow);
|
||||
&:hover {
|
||||
background: var(--item-background-hover);
|
||||
box-shadow: var(--item-hover-shadow);
|
||||
}
|
||||
}
|
||||
.widget-base {
|
||||
background: var(--background-darker);
|
||||
padding: 1rem 0.5rem;
|
||||
margin: 0.5rem 0;
|
||||
}
|
||||
|
||||
.item-wrapper {
|
||||
.item-url {
|
||||
display: block;
|
||||
opacity: 0;
|
||||
position: absolute;
|
||||
bottom: -1.9rem;
|
||||
font-size: 0.8rem;
|
||||
color: var(--background);
|
||||
transition: all 0.2s cubic-bezier(0.8, 0.8, 0.4, 1.4);
|
||||
}
|
||||
a {
|
||||
transition: all 0.2s cubic-bezier(0.8, 0.8, 0.4, 1.4);
|
||||
height: calc(100% - 1rem);
|
||||
}
|
||||
&:hover {
|
||||
a { height: calc(100% - 2rem); }
|
||||
.item-icon {
|
||||
transform: scale(0.9);
|
||||
}
|
||||
.item-url {
|
||||
display: block;
|
||||
opacity: 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
html[data-theme='cherry-blossom'] {
|
||||
--primary: #e1e8ee;
|
||||
--background: #11171d;
|
||||
@ -1999,7 +2081,7 @@ html[data-theme="tama"] {
|
||||
// Background Image
|
||||
body {
|
||||
//update the query terms after the '?', to customize for images you want
|
||||
background: url('https://source.unsplash.com/random/1920x1080/?dark,calm,nature,background');
|
||||
background: url('https://picsum.photos/1920/1080');
|
||||
background-color: var(--background-darker);
|
||||
background-size: cover;
|
||||
}
|
||||
|
@ -3,6 +3,7 @@ import ConfigAccumulator from '@/utils/ConfigAccumalator';
|
||||
import ErrorHandler from '@/utils/ErrorHandler';
|
||||
import { cookieKeys, localStorageKeys, userStateEnum } from '@/utils/defaults';
|
||||
import { isKeycloakEnabled } from '@/utils/KeycloakAuth';
|
||||
import { isOidcEnabled } from '@/utils/OidcAuth';
|
||||
|
||||
/* Uses config accumulator to get and return app config */
|
||||
const getAppConfig = () => {
|
||||
@ -96,7 +97,7 @@ export const isAuthEnabled = () => {
|
||||
/* Returns true if guest access is enabled */
|
||||
export const isGuestAccessEnabled = () => {
|
||||
const appConfig = getAppConfig();
|
||||
if (appConfig.auth && typeof appConfig.auth === 'object' && !isKeycloakEnabled()) {
|
||||
if (appConfig.auth && typeof appConfig.auth === 'object' && !isKeycloakEnabled() && !isOidcEnabled()) {
|
||||
return appConfig.auth.enableGuestAccess || false;
|
||||
}
|
||||
return false;
|
||||
@ -229,8 +230,10 @@ export const getUserState = () => {
|
||||
loggedIn,
|
||||
guestAccess,
|
||||
keycloakEnabled,
|
||||
oidcEnabled,
|
||||
} = userStateEnum; // Numeric enum options
|
||||
if (isKeycloakEnabled()) return keycloakEnabled; // Keycloak auth configured
|
||||
if (isOidcEnabled()) return oidcEnabled;
|
||||
if (!isAuthEnabled()) return notConfigured; // No auth enabled
|
||||
if (isLoggedIn()) return loggedIn; // User is logged in
|
||||
if (isGuestAccessEnabled()) return guestAccess; // Guest is viewing
|
||||
|
@ -541,6 +541,38 @@
|
||||
]
|
||||
}
|
||||
},
|
||||
"enableOidc": {
|
||||
"title": "Enable OIDC?",
|
||||
"type": "boolean",
|
||||
"default": false,
|
||||
"description": "If set to true, enable OIDC. See appConfig.auth.oidc"
|
||||
},
|
||||
"oidc": {
|
||||
"type": "object",
|
||||
"description": "Configuration for OIDC",
|
||||
"additionalProperties": false,
|
||||
"required": [
|
||||
"clientId",
|
||||
"endpoint"
|
||||
],
|
||||
"properties": {
|
||||
"endpoint": {
|
||||
"title": "OIDC Endpoint",
|
||||
"type": "string",
|
||||
"description": "Endpoint of OIDC provider"
|
||||
},
|
||||
"clientId": {
|
||||
"title": "OIDC Client Id",
|
||||
"type": "string",
|
||||
"description": "ClientId from OIDC provider"
|
||||
},
|
||||
"scope" : {
|
||||
"title": "OIDC Scope",
|
||||
"type": "string",
|
||||
"description": "The scope(s) to request from the OIDC provider"
|
||||
}
|
||||
}
|
||||
},
|
||||
"enableHeaderAuth": {
|
||||
"title": "Enable HeaderAuth?",
|
||||
"type": "boolean",
|
||||
|
90
src/utils/OidcAuth.js
Normal file
@ -0,0 +1,90 @@
|
||||
import { UserManager, WebStorageStateStore } from 'oidc-client-ts';
|
||||
import ConfigAccumulator from '@/utils/ConfigAccumalator';
|
||||
import { localStorageKeys } from '@/utils/defaults';
|
||||
import ErrorHandler from '@/utils/ErrorHandler';
|
||||
import { statusMsg, statusErrorMsg } from '@/utils/CoolConsole';
|
||||
|
||||
const getAppConfig = () => {
|
||||
const Accumulator = new ConfigAccumulator();
|
||||
const config = Accumulator.config();
|
||||
return config.appConfig || {};
|
||||
};
|
||||
|
||||
class OidcAuth {
|
||||
constructor() {
|
||||
const { auth } = getAppConfig();
|
||||
const { clientId, endpoint, scope } = auth.oidc;
|
||||
const settings = {
|
||||
userStore: new WebStorageStateStore({ store: window.localStorage }),
|
||||
authority: endpoint,
|
||||
client_id: clientId,
|
||||
redirect_uri: `${window.location.origin}`,
|
||||
response_type: 'code',
|
||||
scope: scope || 'openid profile email roles groups',
|
||||
response_mode: 'query',
|
||||
filterProtocolClaims: true,
|
||||
};
|
||||
|
||||
this.userManager = new UserManager(settings);
|
||||
}
|
||||
|
||||
async login() {
|
||||
const url = new URL(window.location.href);
|
||||
const code = url.searchParams.get('code');
|
||||
|
||||
if (code) {
|
||||
await this.userManager.signinCallback(window.location.href);
|
||||
window.location.href = '/';
|
||||
return;
|
||||
}
|
||||
|
||||
const user = await this.userManager.getUser();
|
||||
|
||||
if (user === null) {
|
||||
await this.userManager.signinRedirect();
|
||||
} else {
|
||||
const { roles, groups } = user.profile;
|
||||
const info = {
|
||||
groups,
|
||||
roles,
|
||||
};
|
||||
|
||||
statusMsg(`user: ${user.profile.preferred_username}`, JSON.stringify(info));
|
||||
|
||||
localStorage.setItem(localStorageKeys.KEYCLOAK_INFO, JSON.stringify(info));
|
||||
localStorage.setItem(localStorageKeys.USERNAME, user.profile.preferred_username);
|
||||
}
|
||||
}
|
||||
|
||||
async logout() {
|
||||
localStorage.removeItem(localStorageKeys.USERNAME);
|
||||
localStorage.removeItem(localStorageKeys.KEYCLOAK_INFO);
|
||||
|
||||
try {
|
||||
await this.userManager.signoutRedirect();
|
||||
} catch (reason) {
|
||||
statusErrorMsg('logout', 'could not log out. Redirecting to OIDC instead', reason);
|
||||
window.location.href = this.userManager.settings.authority;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export const isOidcEnabled = () => {
|
||||
const { auth } = getAppConfig();
|
||||
if (!auth) return false;
|
||||
return auth.enableOidc || false;
|
||||
};
|
||||
|
||||
let oidc;
|
||||
|
||||
export const initOidcAuth = () => {
|
||||
oidc = new OidcAuth();
|
||||
return oidc.login();
|
||||
};
|
||||
|
||||
export const getOidcAuth = () => {
|
||||
if (!oidc) {
|
||||
ErrorHandler("OIDC not initialized, can't get instance of class");
|
||||
}
|
||||
return oidc;
|
||||
};
|
@ -89,6 +89,7 @@ module.exports = {
|
||||
'tama',
|
||||
'neomorphic',
|
||||
'glass-2',
|
||||
'night-bat',
|
||||
],
|
||||
/* Default color options for the theme configurator swatches */
|
||||
swatches: [
|
||||
@ -220,7 +221,7 @@ module.exports = {
|
||||
},
|
||||
/* API endpoints for widgets that need to fetch external data */
|
||||
widgetApiEndpoints: {
|
||||
anonAddy: 'https://app.anonaddy.com',
|
||||
anonAddy: 'https://app.addy.io',
|
||||
astronomyPictureOfTheDay: 'https://apod.as93.net/apod',
|
||||
blacklistCheck: 'https://api.blacklistchecker.com/check',
|
||||
codeStats: 'https://codestats.net/',
|
||||
@ -233,17 +234,22 @@ module.exports = {
|
||||
ethGasHistory: 'https://ethgas.watch/api/gas/trend',
|
||||
exchangeRates: 'https://v6.exchangerate-api.com/v6/',
|
||||
flights: 'https://aerodatabox.p.rapidapi.com/flights/airports/icao/',
|
||||
githubTrending: 'https://gh-trending-repos.herokuapp.com/',
|
||||
githubTrending: 'https://trend.doforce.xyz/',
|
||||
hackernewsTrending: 'https://hacker-news.firebaseio.com/v0',
|
||||
healthChecks: 'https://healthchecks.io/api/v1/checks',
|
||||
holidays: 'https://kayaposoft.com/enrico/json/v2.0/?action=getHolidaysForDateRange',
|
||||
jokes: 'https://v2.jokeapi.dev/joke/',
|
||||
news: 'https://api.currentsapi.services/v1/latest-news',
|
||||
minecraftPlayerIcon: 'https://mc-heads.net/avatar/',
|
||||
minecraftPlayerLink: 'https://minecraftuuid.com/?search=',
|
||||
minecraftServerLink: 'https://mcsrvstat.us/server/',
|
||||
minecraftStatus: 'https://api.mcsrvstat.us/',
|
||||
mullvad: 'https://am.i.mullvad.net/json',
|
||||
mvg: 'https://www.mvg.de/api/fib/v2/',
|
||||
publicIp: 'https://ipapi.co/json',
|
||||
publicIp2: 'https://api.ipgeolocation.io/ipgeo',
|
||||
publicIp3: 'http://ip-api.com/json',
|
||||
publicIp4: 'https://api.ip2location.io/',
|
||||
readMeStats: 'https://github-readme-stats.vercel.app/api',
|
||||
rescueTime: 'https://www.rescuetime.com/anapi/data',
|
||||
rssToJson: 'https://api.rss2json.com/v1/api.json',
|
||||
@ -305,6 +311,7 @@ module.exports = {
|
||||
guestAccess: 2,
|
||||
notLoggedIn: 3,
|
||||
keycloakEnabled: 4,
|
||||
oidcEnabled: 5,
|
||||
},
|
||||
/* Progressive Web App settings, used by Vue Config */
|
||||
pwa: {
|
||||
@ -317,6 +324,7 @@ module.exports = {
|
||||
iconPaths: {
|
||||
favicon64: './web-icons/favicon-64x64.png',
|
||||
favicon32: './web-icons/favicon-32x32.png',
|
||||
favicon16: './web-icons/favicon-16x16.png',
|
||||
maskIcon: './web-icons/dashy-logo.png',
|
||||
msTileImage: './web-icons/dashy-logo.png',
|
||||
},
|
||||
|
@ -1,5 +1,7 @@
|
||||
{
|
||||
"compilerOptions": {
|
||||
"incremental": true,
|
||||
"tsBuildInfoFile": "/app/.tsbuildinfo",
|
||||
"target": "esnext",
|
||||
"module": "esnext",
|
||||
"strict": false,
|
||||
|
@ -49,6 +49,7 @@ const plugins = !isServer ? [
|
||||
|
||||
// Webpack Config
|
||||
const configureWebpack = {
|
||||
devtool: 'source-map',
|
||||
mode,
|
||||
plugins,
|
||||
module: {
|
||||
@ -95,5 +96,8 @@ module.exports = {
|
||||
devServer,
|
||||
chainWebpack: config => {
|
||||
config.module.rules.delete('svg');
|
||||
config.cache({
|
||||
type: 'filesystem',
|
||||
});
|
||||
},
|
||||
};
|
||||
|