mirror of
https://github.com/IceWhaleTech/CasaOS.git
synced 2025-12-23 13:04:42 +00:00
Compare commits
65 Commits
v0.4.4-alp
...
v0.4.4-3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
7807cfdb01 | ||
|
|
9e5381710f | ||
|
|
fa62c65526 | ||
|
|
3aea945277 | ||
|
|
4d8ca182cb | ||
|
|
b727606a0a | ||
|
|
428be5f2c2 | ||
|
|
995d67543d | ||
|
|
590beac43a | ||
|
|
e7bf227232 | ||
|
|
eedfdde311 | ||
|
|
38c7b5a569 | ||
|
|
8c0b219621 | ||
|
|
23fc677f30 | ||
|
|
a06508783c | ||
|
|
37fee157dd | ||
|
|
3f1c7098bd | ||
|
|
b11d046c52 | ||
|
|
d6a9ba65ed | ||
|
|
5f1df76dbf | ||
|
|
0cf353c56e | ||
|
|
5dc6297047 | ||
|
|
f26ae2793c | ||
|
|
d7641e1b93 | ||
|
|
37c496fd6a | ||
|
|
cb15c06f7e | ||
|
|
89a0ea34b0 | ||
|
|
d8dd815baa | ||
|
|
a77b5d1954 | ||
|
|
d0fb2f06f5 | ||
|
|
dd8032a8be | ||
|
|
760882e147 | ||
|
|
dfeed76a66 | ||
|
|
28d724731a | ||
|
|
4549d8778b | ||
|
|
05cadaabf3 | ||
|
|
1a0c15208c | ||
|
|
4f5b4b0887 | ||
|
|
cbfe44be61 | ||
|
|
e1bbb998df | ||
|
|
f48cddf924 | ||
|
|
23ce3487e1 | ||
|
|
6246421dae | ||
|
|
f867453573 | ||
|
|
78e7a8b411 | ||
|
|
1aa8fb600b | ||
|
|
7ecfea71ab | ||
|
|
d911d80254 | ||
|
|
9bfe37305c | ||
|
|
94dd2e00c7 | ||
|
|
c5d2cebe92 | ||
|
|
955e8dea07 | ||
|
|
4c7b3a749b | ||
|
|
e86a61596b | ||
|
|
c9617e583f | ||
|
|
dda15b0821 | ||
|
|
50816c68b0 | ||
|
|
c5de0319fb | ||
|
|
78b7c6ce09 | ||
|
|
b420a2d930 | ||
|
|
c67ee1731c | ||
|
|
eaca399ef9 | ||
|
|
e0e9f97764 | ||
|
|
2fefee87fa | ||
|
|
280ad4fcf9 |
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
34
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -8,39 +8,57 @@ assignees: ''
|
|||||||
---
|
---
|
||||||
|
|
||||||
**Describe the bug**
|
**Describe the bug**
|
||||||
A clear and concise description of what the bug is.
|
|
||||||
|
> A clear and concise description of what the bug is.
|
||||||
|
|
||||||
**To Reproduce**
|
**To Reproduce**
|
||||||
Steps to reproduce the behavior:
|
|
||||||
|
> Steps to reproduce the behavior:
|
||||||
|
|
||||||
1. Go to '...'
|
1. Go to '...'
|
||||||
2. Click on '....'
|
2. Click on '....'
|
||||||
3. Scroll down to '....'
|
3. Scroll down to '....'
|
||||||
4. See error
|
4. See error
|
||||||
|
|
||||||
**Expected behavior**
|
**Expected behavior**
|
||||||
A clear and concise description of what you expected to happen.
|
|
||||||
|
> A clear and concise description of what you expected to happen.
|
||||||
|
|
||||||
**Screenshots**
|
**Screenshots**
|
||||||
If applicable, add screenshots to help explain your problem.
|
|
||||||
|
> If applicable, add screenshots to help explain your problem.
|
||||||
|
|
||||||
**Desktop (please complete the following information):**
|
**Desktop (please complete the following information):**
|
||||||
|
|
||||||
|
```
|
||||||
- OS: [e.g. iOS]
|
- OS: [e.g. iOS]
|
||||||
- Browser [e.g. chrome, safari]
|
- Browser [e.g. chrome, safari]
|
||||||
- Version [e.g. 22]
|
- Version [e.g. 22]
|
||||||
|
```
|
||||||
|
|
||||||
|
**System Time**
|
||||||
|
|
||||||
|
> Run `timedatectl` and share the output
|
||||||
|
|
||||||
|
```
|
||||||
|
(timedatectl output here)
|
||||||
|
```
|
||||||
|
|
||||||
**Logs**
|
**Logs**
|
||||||
|
|
||||||
run following command to collect corresponding logs:
|
> Run following command to collect corresponding logs:
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
sudo journalctl -xef -u casaos-gateway
|
sudo journalctl -xef -u casaos-gateway
|
||||||
sudo journalctl -xef -u casaos-user-service
|
sudo journalctl -xef -u casaos-user-service
|
||||||
sudo journalctl -xef -u casaos-local-storage
|
sudo journalctl -xef -u casaos-local-storage
|
||||||
|
sudo journalctl -xef -u casaos-app-management
|
||||||
sudo journalctl -xef -u casaos.service
|
sudo journalctl -xef -u casaos.service
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
|
||||||
|
> Add any other context about the problem here.
|
||||||
|
>
|
||||||
|
> If you are a Zimaboard user, make it explicit with when you got your Zimaboard.
|
||||||
|
|||||||
23
.github/ISSUE_TEMPLATE/feedback.yml
vendored
23
.github/ISSUE_TEMPLATE/feedback.yml
vendored
@@ -1,23 +0,0 @@
|
|||||||
name: "Feedback"
|
|
||||||
description: Feedback, showcases, thoughts, needs and questions, etc.
|
|
||||||
title: "[Feedback] "
|
|
||||||
labels: ["feedback"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
### ❤️ Thanks for your feedback!
|
|
||||||
> Come join our [Discord community](https://discord.gg/knqAbbBbeX) and paint the ideal home cloud with us.
|
|
||||||
- type: textarea
|
|
||||||
id: description
|
|
||||||
attributes:
|
|
||||||
label: Description
|
|
||||||
placeholder: What do you want to tell us?
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
- type: textarea
|
|
||||||
id: additional
|
|
||||||
attributes:
|
|
||||||
label: Additional Information
|
|
||||||
description: Please add logs/files/screenshots if you have them to help us better understanding.
|
|
||||||
|
|
||||||
15
.github/ISSUE_TEMPLATE/submit-application.md
vendored
15
.github/ISSUE_TEMPLATE/submit-application.md
vendored
@@ -1,15 +0,0 @@
|
|||||||
---
|
|
||||||
name: Submit application
|
|
||||||
about: Add an app to this project
|
|
||||||
title: ''
|
|
||||||
labels: ''
|
|
||||||
assignees: LinkLeong
|
|
||||||
|
|
||||||
---
|
|
||||||
|
|
||||||
Tested platform
|
|
||||||
e.g. linux/amd64,linux/arm-v7,linux-arm64
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
Please export and upload the configuration file of this application
|
|
||||||
2
.github/workflows/casa.yml
vendored
2
.github/workflows/casa.yml
vendored
@@ -65,7 +65,7 @@ jobs:
|
|||||||
# ls
|
# ls
|
||||||
|
|
||||||
|
|
||||||
- name: Set enviroment for github-release
|
- name: Set environment for github-release
|
||||||
run: |
|
run: |
|
||||||
echo "VERSION=$(cat types/system.go | grep CURRENTVERSION | awk '$2 == "CURRENTVERSION"{print $4}' | sed 's/"//g')" >>$GITHUB_ENV
|
echo "VERSION=$(cat types/system.go | grep CURRENTVERSION | awk '$2 == "CURRENTVERSION"{print $4}' | sed 's/"//g')" >>$GITHUB_ENV
|
||||||
echo "BODY=$(cat types/system.go | grep BODY | awk -F= '{print $2}' | sed 's/"//g')" >>$GITHUB_ENV
|
echo "BODY=$(cat types/system.go | grep BODY | awk -F= '{print $2}' | sed 's/"//g')" >>$GITHUB_ENV
|
||||||
|
|||||||
9
.github/workflows/demo.yml
vendored
9
.github/workflows/demo.yml
vendored
@@ -33,8 +33,9 @@ jobs:
|
|||||||
|
|
||||||
- name: Get old instance and snapshot name, create new instance name
|
- name: Get old instance and snapshot name, create new instance name
|
||||||
run: |
|
run: |
|
||||||
echo "OLD_INSTANCE_SNAPSHOT_NAME=$(aws lightsail get-instance-snapshots | grep '"name": "updateto_to_0.4.1-1676285322' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
|
echo "OLD_INSTANCE_SNAPSHOT_NAME=updateto_to_0.4.4-1684926517" >> $GITHUB_ENV
|
||||||
echo "OLD_INSTANCE_NAME=$(aws lightsail get-instances | grep '"name": "CasaOS-Demo-[0-9]' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
|
echo "OLD_INSTANCE_NAME=$(aws lightsail get-instances | grep '"name": "CasaOS-Demo-[0-9]' | tail -1 | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
|
||||||
|
# echo "OLD_INSTANCE_NAME=CasaOS-Demo-1687680295" >> $GITHUB_ENV
|
||||||
echo "NEW_INSTANCE_NAME= CasaOS-Demo-$(date +%s)" >> $GITHUB_ENV
|
echo "NEW_INSTANCE_NAME= CasaOS-Demo-$(date +%s)" >> $GITHUB_ENV
|
||||||
|
|
||||||
- name: Create instances from snapshot
|
- name: Create instances from snapshot
|
||||||
@@ -75,5 +76,9 @@ jobs:
|
|||||||
run: |
|
run: |
|
||||||
aws lightsail delete-instance \
|
aws lightsail delete-instance \
|
||||||
--instance-name ${{ env.OLD_INSTANCE_NAME }}
|
--instance-name ${{ env.OLD_INSTANCE_NAME }}
|
||||||
|
- name: Demo Reset Error Handling
|
||||||
|
if: ${{ failure() }}
|
||||||
|
run: |
|
||||||
|
curl -X POST -H "Content-Type: application/json" -d '{"msg_type":"text","content":{"text":"Demo Reset Error"}}' ${{ secrets.SSH_ROBOT_URL }}
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
46
.github/workflows/publish_npm.yaml
vendored
Normal file
46
.github/workflows/publish_npm.yaml
vendored
Normal file
@@ -0,0 +1,46 @@
|
|||||||
|
name: publish npm
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- v*.*.*
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
publish-npm:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
- uses: actions/checkout@v3
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
- uses: actions/setup-node@v3
|
||||||
|
with:
|
||||||
|
node-version: 16
|
||||||
|
registry-url: https://registry.npmjs.org/
|
||||||
|
|
||||||
|
- run: git tag --sort=-creatordate | head -n 1
|
||||||
|
- name: Get version
|
||||||
|
id: get_version
|
||||||
|
run: echo "VERSION=$(git tag --sort=-creatordate | head -n 1)" >> $GITHUB_OUTPUT
|
||||||
|
- name: Get commit id
|
||||||
|
id: get_commit_id
|
||||||
|
run: echo "COMMIT_ID=$( git rev-parse --short "$GITHUB_SHA" )" >> $GITHUB_OUTPUT
|
||||||
|
|
||||||
|
- run: echo "${{ steps.get_version.outputs.VERSION }}-${{ steps.get_commit_id.outputs.COMMIT_ID }}"
|
||||||
|
- name: Set version
|
||||||
|
run: |
|
||||||
|
sudo apt-get install jq
|
||||||
|
jq '.version="${{ steps.get_version.outputs.VERSION }}-${{ steps.get_commit_id.outputs.COMMIT_ID }}"' package.json > package.json.new
|
||||||
|
mv package.json.new package.json
|
||||||
|
- name: Generate SDK
|
||||||
|
run: |
|
||||||
|
npm cache clean --force
|
||||||
|
npm install @openapitools/openapi-generator-cli -g
|
||||||
|
- run: npm i
|
||||||
|
- run: npm run start
|
||||||
|
- run: npm publish --access public
|
||||||
|
env:
|
||||||
|
NODE_AUTH_TOKEN: ${{secrets.npm_token}}
|
||||||
12
.github/workflows/push_test_server.yml
vendored
12
.github/workflows/push_test_server.yml
vendored
@@ -3,6 +3,8 @@ on:
|
|||||||
push:
|
push:
|
||||||
branches:
|
branches:
|
||||||
- main
|
- main
|
||||||
|
workflow_dispatch:
|
||||||
|
|
||||||
permissions:
|
permissions:
|
||||||
contents: write
|
contents: write
|
||||||
jobs:
|
jobs:
|
||||||
@@ -19,7 +21,7 @@ jobs:
|
|||||||
- name: git global
|
- name: git global
|
||||||
run: sudo git config --global --add safe.directory '*'
|
run: sudo git config --global --add safe.directory '*'
|
||||||
- name: set version
|
- name: set version
|
||||||
run: sudo git tag v99.99.99-alpha
|
run: sudo git tag v00.00.00-alpha
|
||||||
|
|
||||||
- name: Fetch all tags
|
- name: Fetch all tags
|
||||||
run: sudo git fetch --force --tags
|
run: sudo git fetch --force --tags
|
||||||
@@ -44,10 +46,16 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
# either 'goreleaser' (default) or 'goreleaser-pro'
|
# either 'goreleaser' (default) or 'goreleaser-pro'
|
||||||
distribution: goreleaser
|
distribution: goreleaser
|
||||||
version: latest
|
version: 1.14.1
|
||||||
args: release --rm-dist --snapshot
|
args: release --rm-dist --snapshot
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
GoogleID: ${{ secrets.GoogleID }}
|
||||||
|
GoogleSecret: ${{ secrets.GoogleSecret }}
|
||||||
|
DropboxKey: ${{ secrets.DropboxKey }}
|
||||||
|
DropboxSecret: ${{ secrets.DropboxSecret }}
|
||||||
|
OneDriveID: ${{ secrets.OneDriveID }}
|
||||||
|
OneDriveSecret: ${{ secrets.OneDriveSecret }}
|
||||||
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
|
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
|
||||||
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
||||||
|
|
||||||
|
|||||||
6
.github/workflows/release.yml
vendored
6
.github/workflows/release.yml
vendored
@@ -42,6 +42,12 @@ jobs:
|
|||||||
args: release --rm-dist
|
args: release --rm-dist
|
||||||
env:
|
env:
|
||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
GoogleID: ${{ secrets.GoogleID }}
|
||||||
|
GoogleSecret: ${{ secrets.GoogleSecret }}
|
||||||
|
DropboxKey: ${{ secrets.DropboxKey }}
|
||||||
|
DropboxSecret: ${{ secrets.DropboxSecret }}
|
||||||
|
OneDriveID: ${{ secrets.OneDriveID }}
|
||||||
|
OneDriveSecret: ${{ secrets.OneDriveSecret }}
|
||||||
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
|
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
|
||||||
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
||||||
|
|
||||||
|
|||||||
@@ -113,24 +113,22 @@ builds:
|
|||||||
goarm:
|
goarm:
|
||||||
- "7"
|
- "7"
|
||||||
archives:
|
archives:
|
||||||
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}"
|
- name_template: >-
|
||||||
|
{{ .Os }}-{{- if eq .Arch "arm" }}arm-7{{- else }}{{ .Arch }}{{- end }}-{{ .ProjectName }}-v{{ .Version }}
|
||||||
id: casaos
|
id: casaos
|
||||||
builds:
|
builds:
|
||||||
- casaos-amd64
|
- casaos-amd64
|
||||||
- casaos-arm64
|
- casaos-arm64
|
||||||
- casaos-arm-7
|
- casaos-arm-7
|
||||||
replacements:
|
|
||||||
arm: arm-7
|
|
||||||
files:
|
files:
|
||||||
- build/**/*
|
- build/**/*
|
||||||
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}"
|
- name_template: >-
|
||||||
|
{{ .Os }}-{{- if eq .Arch "arm" }}arm-7{{- else }}{{ .Arch }}{{- end }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}
|
||||||
id: casaos-migration-tool
|
id: casaos-migration-tool
|
||||||
builds:
|
builds:
|
||||||
- casaos-migration-tool-amd64
|
- casaos-migration-tool-amd64
|
||||||
- casaos-migration-tool-arm64
|
- casaos-migration-tool-arm64
|
||||||
- casaos-migration-tool-arm-7
|
- casaos-migration-tool-arm-7
|
||||||
replacements:
|
|
||||||
arm: arm-7
|
|
||||||
files:
|
files:
|
||||||
- build/sysroot/etc/**/*
|
- build/sysroot/etc/**/*
|
||||||
checksum:
|
checksum:
|
||||||
|
|||||||
@@ -19,6 +19,12 @@ builds:
|
|||||||
ldflags:
|
ldflags:
|
||||||
- -X main.commit={{.Commit}}
|
- -X main.commit={{.Commit}}
|
||||||
- -X main.date={{.Date}}
|
- -X main.date={{.Date}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/google_drive.client_id={{.Env.GoogleID}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/google_drive.client_secret={{.Env.GoogleSecret}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/onedrive.client_id={{.Env.OneDriveID}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/onedrive.client_secret={{.Env.OneDriveSecret}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/dropbox.app_key={{.Env.DropboxKey}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/dropbox.app_secret={{.Env.DropboxSecret}}
|
||||||
- -s
|
- -s
|
||||||
- -w
|
- -w
|
||||||
- -extldflags "-static"
|
- -extldflags "-static"
|
||||||
@@ -40,6 +46,12 @@ builds:
|
|||||||
ldflags:
|
ldflags:
|
||||||
- -X main.commit={{.Commit}}
|
- -X main.commit={{.Commit}}
|
||||||
- -X main.date={{.Date}}
|
- -X main.date={{.Date}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/google_drive.client_id={{.Env.GoogleID}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/google_drive.client_secret={{.Env.GoogleSecret}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/onedrive.client_id={{.Env.OneDriveID}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/onedrive.client_secret={{.Env.OneDriveSecret}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/dropbox.app_key={{.Env.DropboxKey}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/dropbox.app_secret={{.Env.DropboxSecret}}
|
||||||
- -s
|
- -s
|
||||||
- -w
|
- -w
|
||||||
- -extldflags "-static"
|
- -extldflags "-static"
|
||||||
@@ -61,6 +73,12 @@ builds:
|
|||||||
ldflags:
|
ldflags:
|
||||||
- -X main.commit={{.Commit}}
|
- -X main.commit={{.Commit}}
|
||||||
- -X main.date={{.Date}}
|
- -X main.date={{.Date}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/google_drive.client_id={{.Env.GoogleID}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/google_drive.client_secret={{.Env.GoogleSecret}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/onedrive.client_id={{.Env.OneDriveID}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/onedrive.client_secret={{.Env.OneDriveSecret}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/dropbox.app_key={{.Env.DropboxKey}}
|
||||||
|
- -X github.com/IceWhaleTech/CasaOS/drivers/dropbox.app_secret={{.Env.DropboxSecret}}
|
||||||
- -s
|
- -s
|
||||||
- -w
|
- -w
|
||||||
- -extldflags "-static"
|
- -extldflags "-static"
|
||||||
@@ -143,24 +161,22 @@ builds:
|
|||||||
goarm:
|
goarm:
|
||||||
- "7"
|
- "7"
|
||||||
archives:
|
archives:
|
||||||
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}"
|
- name_template: >-
|
||||||
|
{{ .Os }}-{{- if eq .Arch "arm" }}arm-7{{- else }}{{ .Arch }}{{- end }}-{{ .ProjectName }}-v{{ .Version }}
|
||||||
id: casaos
|
id: casaos
|
||||||
builds:
|
builds:
|
||||||
- casaos-amd64
|
- casaos-amd64
|
||||||
- casaos-arm64
|
- casaos-arm64
|
||||||
- casaos-arm-7
|
- casaos-arm-7
|
||||||
replacements:
|
|
||||||
arm: arm-7
|
|
||||||
files:
|
files:
|
||||||
- build/**/*
|
- build/**/*
|
||||||
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}"
|
- name_template: >-
|
||||||
|
{{ .Os }}-{{- if eq .Arch "arm" }}arm-7{{- else }}{{ .Arch }}{{- end }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}
|
||||||
id: casaos-migration-tool
|
id: casaos-migration-tool
|
||||||
builds:
|
builds:
|
||||||
- casaos-migration-tool-amd64
|
- casaos-migration-tool-amd64
|
||||||
- casaos-migration-tool-arm64
|
- casaos-migration-tool-arm64
|
||||||
- casaos-migration-tool-arm-7
|
- casaos-migration-tool-arm-7
|
||||||
replacements:
|
|
||||||
arm: arm-7
|
|
||||||
files:
|
files:
|
||||||
- build/sysroot/etc/**/*
|
- build/sysroot/etc/**/*
|
||||||
checksum:
|
checksum:
|
||||||
|
|||||||
18
README.md
18
README.md
@@ -83,7 +83,7 @@ Furthermore, the personal cloud could combine personal data to train personalize
|
|||||||
- Multiple hardware and base system support
|
- Multiple hardware and base system support
|
||||||
- ZimaBoard, NUC, RPi, old computers, whatever is available.
|
- ZimaBoard, NUC, RPi, old computers, whatever is available.
|
||||||
- Selected apps in the app store, one-click installation
|
- Selected apps in the app store, one-click installation
|
||||||
- Nextcloud, HomeAssiant, AdGuard, Jellyfin, *arr and more!
|
- Nextcloud, HomeAssistant, AdGuard, Jellyfin, *arr and more!
|
||||||
- Easily install numerous Docker apps
|
- Easily install numerous Docker apps
|
||||||
- Over 100,000 apps from the Docker ecosystem can be easily installed
|
- Over 100,000 apps from the Docker ecosystem can be easily installed
|
||||||
- Elegant drive and file management
|
- Elegant drive and file management
|
||||||
@@ -104,7 +104,7 @@ CasaOS fully supports ZimaBoard, Intel NUC, and Raspberry Pi. Also, more compute
|
|||||||
### System Compatibility
|
### System Compatibility
|
||||||
|
|
||||||
Official Support
|
Official Support
|
||||||
- Debian 11 (✅ Tested, Recommended)
|
- Debian 12 (✅ Tested, Recommended)
|
||||||
- Ubuntu Server 20.04 (✅ Tested)
|
- Ubuntu Server 20.04 (✅ Tested)
|
||||||
- Raspberry Pi OS (✅ Tested)
|
- Raspberry Pi OS (✅ Tested)
|
||||||
|
|
||||||
@@ -146,13 +146,13 @@ curl -fsSL https://get.icewhale.io/casaos-uninstall.sh | sudo bash
|
|||||||
|
|
||||||
## Community
|
## Community
|
||||||
|
|
||||||
The word Casa comes from the Spanish word for "home". Project CasaOS originated as a pre-installed system for crowdfunded product [ZimaBoard](https://www.zimaboard.com) on Kickstarter.
|
The word Casa comes from the Spanish word for "home". Project CasaOS originated as a pre-installed system for the crowdfunded product [ZimaBoard](https://www.zimaboard.com) on Kickstarter.
|
||||||
|
|
||||||
After looking at many systems and software on the market, the team found no server system designed for home scenarios, sadly true.
|
After looking at many systems and software on the market, the team found no server system designed for home scenarios, sadly true.
|
||||||
|
|
||||||
So, we set out to build this open source project to develop CasaOS with our own hands, everyone in the community, and you.
|
So, we set out to build this open-source project to develop CasaOS with our own hands, everyone in the community, and you.
|
||||||
|
|
||||||
We believes that through community-driven collaborative innovation and open communication with global developers, we can reshape the digital home experience like never before.
|
We believe that through community-driven collaborative innovation and open communication with global developers, we can reshape the digital home experience like never before.
|
||||||
|
|
||||||
**A warm welcome for you to get help or share great ideas in the [Discord](https://discord.gg/knqAbbBbeX)!**
|
**A warm welcome for you to get help or share great ideas in the [Discord](https://discord.gg/knqAbbBbeX)!**
|
||||||
|
|
||||||
@@ -162,8 +162,8 @@ We believes that through community-driven collaborative innovation and open comm
|
|||||||
|
|
||||||
CasaOS is a community-driven open source project and the people involved are CasaOS users. That means CasaOS will always need contributions from community members just like you!
|
CasaOS is a community-driven open source project and the people involved are CasaOS users. That means CasaOS will always need contributions from community members just like you!
|
||||||
|
|
||||||
- See <https://wiki.casaos.io/en/contribute> for ways of contribution to CasaOS
|
- See <https://wiki.casaos.io/en/contribute> for ways of contributing to CasaOS
|
||||||
- See <https://wiki.casaos.io/en/contribute/development> if you want to be involved in code contribution specificially
|
- See <https://wiki.casaos.io/en/contribute/development> if you want to be involved in code contribution specifically
|
||||||
|
|
||||||
## Donate
|
## Donate
|
||||||
<p ><a href="https://www.buymeacoffee.com/icewhaletech"> <img align="center" src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" height="50" width="210" alt="bappi2097" target="_blank" /></a></p>
|
<p ><a href="https://www.buymeacoffee.com/icewhaletech"> <img align="center" src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" height="50" width="210" alt="bappi2097" target="_blank" /></a></p>
|
||||||
@@ -199,6 +199,8 @@ Everyone's contribution is greatly appreciated. ([Emoji Key](https://allcontribu
|
|||||||
</tr>
|
</tr>
|
||||||
<tr>
|
<tr>
|
||||||
<td align="center"><a href="https://github.com/llwaini"><img src="https://avatars.githubusercontent.com/u/59589857?v=4?s=100" width="100px;" alt=""/><br /><sub><b>llwaini</b></sub></a><br /><a href="#projectManagement-llwaini" title="Project Management">📆</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=llwaini" title="Tests">⚠️</a> <a href="#tutorial-llwaini" title="Tutorials">✅</a></td>
|
<td align="center"><a href="https://github.com/llwaini"><img src="https://avatars.githubusercontent.com/u/59589857?v=4?s=100" width="100px;" alt=""/><br /><sub><b>llwaini</b></sub></a><br /><a href="#projectManagement-llwaini" title="Project Management">📆</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=llwaini" title="Tests">⚠️</a> <a href="#tutorial-llwaini" title="Tutorials">✅</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/CorrectRoadH"><img src="https://avatars.githubusercontent.com/u/29306285?v=4?s=100" width="100px;" alt=""/><br /><sub><b>CorrectRoadH</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=correctroadh" title="Code">💻</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=correctroadh" title="Documentation">📖</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/zhanghengxin"><img src="https://avatars.githubusercontent.com/u/24197448?v=4?s=100" width="100px;" alt=""/><br /><sub><b>zhanghengxin</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=zhanghengxin" title="Code">💻</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=zhanghengxin" title="Documentation">📖</a></td>
|
||||||
</tr>
|
</tr>
|
||||||
</table>
|
</table>
|
||||||
|
|
||||||
@@ -207,7 +209,7 @@ Everyone's contribution is greatly appreciated. ([Emoji Key](https://allcontribu
|
|||||||
|
|
||||||
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind are welcome!
|
||||||
|
|
||||||
## Changelog
|
## Changelog
|
||||||
|
|
||||||
|
|||||||
@@ -59,6 +59,22 @@ paths:
|
|||||||
$ref: "#/components/responses/GetHealthPortsOK"
|
$ref: "#/components/responses/GetHealthPortsOK"
|
||||||
"500":
|
"500":
|
||||||
$ref: "#/components/responses/ResponseInternalServerError"
|
$ref: "#/components/responses/ResponseInternalServerError"
|
||||||
|
/health/logs:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Health methods
|
||||||
|
summary: Get log
|
||||||
|
operationId: getHealthlogs
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/octet-stream:
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
format: binary
|
||||||
|
"500":
|
||||||
|
$ref: "#/components/responses/ResponseInternalServerError"
|
||||||
|
|
||||||
/file/test:
|
/file/test:
|
||||||
get:
|
get:
|
||||||
@@ -73,6 +89,52 @@ paths:
|
|||||||
$ref: "#/components/responses/ResponseOK"
|
$ref: "#/components/responses/ResponseOK"
|
||||||
"500":
|
"500":
|
||||||
$ref: "#/components/responses/ResponseInternalServerError"
|
$ref: "#/components/responses/ResponseInternalServerError"
|
||||||
|
/zt/info:
|
||||||
|
get:
|
||||||
|
tags:
|
||||||
|
- Zerotier methods
|
||||||
|
summary: Get Zerotier info
|
||||||
|
description: |-
|
||||||
|
Get Zerotier info.
|
||||||
|
operationId: getZerotierInfo
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
$ref: "#/components/responses/GetZTInfoOK"
|
||||||
|
"500":
|
||||||
|
$ref: "#/components/responses/ResponseInternalServerError"
|
||||||
|
/zt/{network_id}/status:
|
||||||
|
put:
|
||||||
|
tags:
|
||||||
|
- Zerotier methods
|
||||||
|
summary: Set Zerotier network status
|
||||||
|
description: |-
|
||||||
|
Set Zerotier network status.
|
||||||
|
operationId: setZerotierNetworkStatus
|
||||||
|
parameters:
|
||||||
|
- name: network_id
|
||||||
|
in: path
|
||||||
|
description: network id
|
||||||
|
required: true
|
||||||
|
schema:
|
||||||
|
type: string
|
||||||
|
requestBody:
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
type: object
|
||||||
|
properties:
|
||||||
|
status:
|
||||||
|
enum:
|
||||||
|
- online
|
||||||
|
- offline
|
||||||
|
type: string
|
||||||
|
example: "online"
|
||||||
|
responses:
|
||||||
|
"200":
|
||||||
|
$ref: "#/components/responses/GetZTInfoOK"
|
||||||
|
"500":
|
||||||
|
$ref: "#/components/responses/ResponseInternalServerError"
|
||||||
|
|
||||||
components:
|
components:
|
||||||
securitySchemes:
|
securitySchemes:
|
||||||
access_token:
|
access_token:
|
||||||
@@ -116,6 +178,13 @@ components:
|
|||||||
- properties:
|
- properties:
|
||||||
data:
|
data:
|
||||||
$ref: "#/components/schemas/HealthPorts"
|
$ref: "#/components/schemas/HealthPorts"
|
||||||
|
GetZTInfoOK:
|
||||||
|
description: OK
|
||||||
|
content:
|
||||||
|
application/json:
|
||||||
|
schema:
|
||||||
|
$ref: "#/components/schemas/ZTInfo"
|
||||||
|
|
||||||
|
|
||||||
schemas:
|
schemas:
|
||||||
BaseResponse:
|
BaseResponse:
|
||||||
@@ -153,3 +222,14 @@ components:
|
|||||||
type: integer
|
type: integer
|
||||||
example: 53
|
example: 53
|
||||||
x-go-name: UDP
|
x-go-name: UDP
|
||||||
|
ZTInfo:
|
||||||
|
properties:
|
||||||
|
id:
|
||||||
|
type: string
|
||||||
|
example: "1234567890"
|
||||||
|
name:
|
||||||
|
type: string
|
||||||
|
example: "CasaOS"
|
||||||
|
status:
|
||||||
|
type: string
|
||||||
|
example: "online"
|
||||||
@@ -1,7 +1,6 @@
|
|||||||
[Unit]
|
[Unit]
|
||||||
After=casaos-message-bus.service
|
After=casaos-message-bus.service
|
||||||
After=rclone.service
|
After=rclone.service
|
||||||
ConditionFileNotEmpty=/etc/casaos/casaos.conf
|
|
||||||
Description=CasaOS Main Service
|
Description=CasaOS Main Service
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
|
|||||||
28
cmd/message-bus-docgen/main.go
Normal file
28
cmd/message-bus-docgen/main.go
Normal file
@@ -0,0 +1,28 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/external"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/codegen/message_bus"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/common"
|
||||||
|
"github.com/samber/lo"
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
eventTypes := lo.Map(common.EventTypes, func(item message_bus.EventType, index int) external.EventType {
|
||||||
|
return external.EventType{
|
||||||
|
Name: item.Name,
|
||||||
|
SourceID: item.SourceID,
|
||||||
|
PropertyTypeList: lo.Map(
|
||||||
|
item.PropertyTypeList, func(item message_bus.PropertyType, index int) external.PropertyType {
|
||||||
|
return external.PropertyType{
|
||||||
|
Name: item.Name,
|
||||||
|
Description: item.Description,
|
||||||
|
Example: item.Example,
|
||||||
|
}
|
||||||
|
},
|
||||||
|
),
|
||||||
|
}
|
||||||
|
})
|
||||||
|
|
||||||
|
external.PrintEventTypesAsMarkdown(common.SERVICENAME, common.VERSION, eventTypes)
|
||||||
|
}
|
||||||
@@ -77,7 +77,7 @@ func init() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
config.InitSetup(configFlag)
|
config.InitSetup(configFlag, "")
|
||||||
|
|
||||||
if len(dbFlag) == 0 {
|
if len(dbFlag) == 0 {
|
||||||
dbFlag = config.AppInfo.DBPath + "/db"
|
dbFlag = config.AppInfo.DBPath + "/db"
|
||||||
|
|||||||
@@ -8,10 +8,12 @@ import (
|
|||||||
"compress/gzip"
|
"compress/gzip"
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net/http"
|
||||||
"net/url"
|
"net/url"
|
||||||
"path"
|
"path"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
|
"github.com/deepmap/oapi-codegen/pkg/runtime"
|
||||||
"github.com/getkin/kin-openapi/openapi3"
|
"github.com/getkin/kin-openapi/openapi3"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
)
|
)
|
||||||
@@ -20,6 +22,12 @@ const (
|
|||||||
Access_tokenScopes = "access_token.Scopes"
|
Access_tokenScopes = "access_token.Scopes"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
// Defines values for SetZerotierNetworkStatusJSONBodyStatus.
|
||||||
|
const (
|
||||||
|
Offline SetZerotierNetworkStatusJSONBodyStatus = "offline"
|
||||||
|
Online SetZerotierNetworkStatusJSONBodyStatus = "online"
|
||||||
|
)
|
||||||
|
|
||||||
// BaseResponse defines model for BaseResponse.
|
// BaseResponse defines model for BaseResponse.
|
||||||
type BaseResponse struct {
|
type BaseResponse struct {
|
||||||
// Message message returned by server side if there is any
|
// Message message returned by server side if there is any
|
||||||
@@ -38,6 +46,13 @@ type HealthServices struct {
|
|||||||
Running *[]string `json:"running,omitempty"`
|
Running *[]string `json:"running,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ZTInfo defines model for ZTInfo.
|
||||||
|
type ZTInfo struct {
|
||||||
|
Id *string `json:"id,omitempty"`
|
||||||
|
Name *string `json:"name,omitempty"`
|
||||||
|
Status *string `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
// GetHealthPortsOK defines model for GetHealthPortsOK.
|
// GetHealthPortsOK defines model for GetHealthPortsOK.
|
||||||
type GetHealthPortsOK struct {
|
type GetHealthPortsOK struct {
|
||||||
Data *HealthPorts `json:"data,omitempty"`
|
Data *HealthPorts `json:"data,omitempty"`
|
||||||
@@ -54,23 +69,46 @@ type GetHealthServicesOK struct {
|
|||||||
Message *string `json:"message,omitempty"`
|
Message *string `json:"message,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetZTInfoOK defines model for GetZTInfoOK.
|
||||||
|
type GetZTInfoOK = ZTInfo
|
||||||
|
|
||||||
// ResponseInternalServerError defines model for ResponseInternalServerError.
|
// ResponseInternalServerError defines model for ResponseInternalServerError.
|
||||||
type ResponseInternalServerError = BaseResponse
|
type ResponseInternalServerError = BaseResponse
|
||||||
|
|
||||||
// ResponseOK defines model for ResponseOK.
|
// ResponseOK defines model for ResponseOK.
|
||||||
type ResponseOK = BaseResponse
|
type ResponseOK = BaseResponse
|
||||||
|
|
||||||
|
// SetZerotierNetworkStatusJSONBody defines parameters for SetZerotierNetworkStatus.
|
||||||
|
type SetZerotierNetworkStatusJSONBody struct {
|
||||||
|
Status *SetZerotierNetworkStatusJSONBodyStatus `json:"status,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetZerotierNetworkStatusJSONBodyStatus defines parameters for SetZerotierNetworkStatus.
|
||||||
|
type SetZerotierNetworkStatusJSONBodyStatus string
|
||||||
|
|
||||||
|
// SetZerotierNetworkStatusJSONRequestBody defines body for SetZerotierNetworkStatus for application/json ContentType.
|
||||||
|
type SetZerotierNetworkStatusJSONRequestBody SetZerotierNetworkStatusJSONBody
|
||||||
|
|
||||||
// ServerInterface represents all server handlers.
|
// ServerInterface represents all server handlers.
|
||||||
type ServerInterface interface {
|
type ServerInterface interface {
|
||||||
// Test file methods
|
// Test file methods
|
||||||
// (GET /file/test)
|
// (GET /file/test)
|
||||||
GetFileTest(ctx echo.Context) error
|
GetFileTest(ctx echo.Context) error
|
||||||
|
// Get log
|
||||||
|
// (GET /health/logs)
|
||||||
|
GetHealthlogs(ctx echo.Context) error
|
||||||
// Get port in use
|
// Get port in use
|
||||||
// (GET /health/ports)
|
// (GET /health/ports)
|
||||||
GetHealthPorts(ctx echo.Context) error
|
GetHealthPorts(ctx echo.Context) error
|
||||||
// Get service status
|
// Get service status
|
||||||
// (GET /health/services)
|
// (GET /health/services)
|
||||||
GetHealthServices(ctx echo.Context) error
|
GetHealthServices(ctx echo.Context) error
|
||||||
|
// Get Zerotier info
|
||||||
|
// (GET /zt/info)
|
||||||
|
GetZerotierInfo(ctx echo.Context) error
|
||||||
|
// Set Zerotier network status
|
||||||
|
// (PUT /zt/{network_id}/status)
|
||||||
|
SetZerotierNetworkStatus(ctx echo.Context, networkId string) error
|
||||||
}
|
}
|
||||||
|
|
||||||
// ServerInterfaceWrapper converts echo contexts to parameters.
|
// ServerInterfaceWrapper converts echo contexts to parameters.
|
||||||
@@ -89,6 +127,17 @@ func (w *ServerInterfaceWrapper) GetFileTest(ctx echo.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetHealthlogs converts echo context to params.
|
||||||
|
func (w *ServerInterfaceWrapper) GetHealthlogs(ctx echo.Context) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx.Set(Access_tokenScopes, []string{""})
|
||||||
|
|
||||||
|
// Invoke the callback with all the unmarshalled arguments
|
||||||
|
err = w.Handler.GetHealthlogs(ctx)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// GetHealthPorts converts echo context to params.
|
// GetHealthPorts converts echo context to params.
|
||||||
func (w *ServerInterfaceWrapper) GetHealthPorts(ctx echo.Context) error {
|
func (w *ServerInterfaceWrapper) GetHealthPorts(ctx echo.Context) error {
|
||||||
var err error
|
var err error
|
||||||
@@ -111,6 +160,35 @@ func (w *ServerInterfaceWrapper) GetHealthServices(ctx echo.Context) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// GetZerotierInfo converts echo context to params.
|
||||||
|
func (w *ServerInterfaceWrapper) GetZerotierInfo(ctx echo.Context) error {
|
||||||
|
var err error
|
||||||
|
|
||||||
|
ctx.Set(Access_tokenScopes, []string{""})
|
||||||
|
|
||||||
|
// Invoke the callback with all the unmarshalled arguments
|
||||||
|
err = w.Handler.GetZerotierInfo(ctx)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// SetZerotierNetworkStatus converts echo context to params.
|
||||||
|
func (w *ServerInterfaceWrapper) SetZerotierNetworkStatus(ctx echo.Context) error {
|
||||||
|
var err error
|
||||||
|
// ------------- Path parameter "network_id" -------------
|
||||||
|
var networkId string
|
||||||
|
|
||||||
|
err = runtime.BindStyledParameterWithLocation("simple", false, "network_id", runtime.ParamLocationPath, ctx.Param("network_id"), &networkId)
|
||||||
|
if err != nil {
|
||||||
|
return echo.NewHTTPError(http.StatusBadRequest, fmt.Sprintf("Invalid format for parameter network_id: %s", err))
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.Set(Access_tokenScopes, []string{""})
|
||||||
|
|
||||||
|
// Invoke the callback with all the unmarshalled arguments
|
||||||
|
err = w.Handler.SetZerotierNetworkStatus(ctx, networkId)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
// This is a simple interface which specifies echo.Route addition functions which
|
// This is a simple interface which specifies echo.Route addition functions which
|
||||||
// are present on both echo.Echo and echo.Group, since we want to allow using
|
// are present on both echo.Echo and echo.Group, since we want to allow using
|
||||||
// either of them for path registration
|
// either of them for path registration
|
||||||
@@ -140,32 +218,39 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
|
|||||||
}
|
}
|
||||||
|
|
||||||
router.GET(baseURL+"/file/test", wrapper.GetFileTest)
|
router.GET(baseURL+"/file/test", wrapper.GetFileTest)
|
||||||
|
router.GET(baseURL+"/health/logs", wrapper.GetHealthlogs)
|
||||||
router.GET(baseURL+"/health/ports", wrapper.GetHealthPorts)
|
router.GET(baseURL+"/health/ports", wrapper.GetHealthPorts)
|
||||||
router.GET(baseURL+"/health/services", wrapper.GetHealthServices)
|
router.GET(baseURL+"/health/services", wrapper.GetHealthServices)
|
||||||
|
router.GET(baseURL+"/zt/info", wrapper.GetZerotierInfo)
|
||||||
|
router.PUT(baseURL+"/zt/:network_id/status", wrapper.SetZerotierNetworkStatus)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Base64 encoded, gzipped, json marshaled Swagger object
|
// Base64 encoded, gzipped, json marshaled Swagger object
|
||||||
var swaggerSpec = []string{
|
var swaggerSpec = []string{
|
||||||
|
|
||||||
"H4sIAAAAAAAC/8xW4W/bthP9Vwj+fh+aQbaMBAUKAf2QNksaBIODJcMGxIZLU2eJjURyd6QTL9D/PpCS",
|
"H4sIAAAAAAAC/8xX72/bNhD9VwhuH5pBsbxk3ToB/dAfaxoUW4Ilw4bGhktLZ4mNRKp3pyRuoP99oCjb",
|
||||||
"Y8V2g6Rdh31yRB7fvfdyx+MDl6a2RoN2xLMHjkDWaIL4cQbuE4jKlZcGHY0vwpo02oF24U9hbaWkcMro",
|
"sq386pqhn2xRp7v3Hnnk47WMbVFaA4ZJRtcSgUprCJqHA+C3oHLOji0yHb1zY7E1DIbdX1WWuY4Va2vC",
|
||||||
"9AsZHdZIllCLuFtV4wXPbh74/xEWPOP/Szep0jaO0g+C4NcuJ2+SB27RWECnWga5cBHsOYgeRd40zbRp",
|
"j2SNG6M4g0I1b/P8aCajs2v5PcJMRvK7cFUq9HEUvlQEf7Y1ZR1cyxJtCcjaI0gUN8luS9GBKOu6Htd1",
|
||||||
"moTnQBKVDdx4xscXvEk2cq4Al0rCf1zRmuXzotapzrUD1KIKpwB/RjT4KnEvl7TLZJ2btclZm71H7pVG",
|
"HcgEKEZdOmwykkfvZB2s6JwAXugYvnFGC5R3knp/emhm9oFkbqvvE8obay7oHRoGNCp3SAF/Q7T41TCs",
|
||||||
"fw+X4EqTdGDR8Scnsu3/Rw1EoogbT4G6DYbgPGrI2XzFqNVHKgemFsyVgMAUMaFXPOFwL2pbAc84TziC",
|
"y7iNZFFb+OLCV++A+4p63IXFqVIHbbJmlte+iDbXQAFEKm1erCdqXwgErtBAIqZzQZ4f6QSEngnOAEFo",
|
||||||
"yMe6WvHMoYeEu5UNO+RQ6aIl3i/cHV5O2vCjHNTx+xH83egRTGkHBUSnuxWBKAKV+0FhBlrUYe3642WI",
|
"EsrMZSDhShVlDjKSMpAIKjky+VxGjBUEkuele0OM2qQeeLdZtnBxXLofzVA0z8vkz4bLZNowpNAo3Y4o",
|
||||||
"8PlXAN8evRLwt5PLvoDHOt3RoI2bodc6KN6bmktBwtCQWgi+Y9MWjybhL8EbFMLBnVi9HDfKIZAelVtd",
|
"ROWgXO2mdteowo2dvjp2EVVyQ8Kn+w9M+Nfr4y6BZW9scTCWJ1gZ4xj3lpaxImVpQD6F3JJpA0cdyPvk",
|
||||||
"hdppFQgpgWjmzC3EGlWhMkoQOSBPeOfHsXelQfVXLOdNLmHVBaxap5RemN0Sm/jR6EhaJZ1HiB8w0Ywx",
|
"200Vw6Wa3z+vY9N22hYLnazX+HFv/6enP//y7NdhX16vUTf+lSJ1dNIXS6y42mBgTa5ND+IGIkFcoeb5",
|
||||||
"1m6Q8SiB1ZAr8X7C31iEBSANpKkMDmKFQ8ZygbcHE84IJYF7P+Glc5ayNEVxNyyUK/3cE2DXfENp6vRc",
|
"iVvdHp2KYyCasD2Hpou0W7sZqARQLtDIFxVnFvXnpuFWuVWp30HLXrfc15tgVA2H+3GpY64QmgcYGSGE",
|
||||||
"wu+lqOAaZJlWpjBpLZROW/O6n9lcaA04C/AzrYrSzd6NRvZ+aHUx4d9KtgpAP5Ctu1MxxWxeeXiesKoL",
|
"8C/IVhiDKCDR6vlIPikRZoC0G9vc4m7TgxCJROH5zkgKwpiAn49kxlxSFIaoLgep5qyaVgTYbg+D2Bbh",
|
||||||
"JqpA4aMgMb5qSf37jFo26VYVTHTLih1fnjOLZqlyIFYrklBVQoPxxGpwpcmJLQyyXC0WgKAdIwlaoDI0",
|
"YQx/ZyqHU4izMLepDQulTeint/2ZTJUxgBOXfmJ0mvHk2XBYXg1Kk47kl4LNXaJHRMuXuikxmeYV3A5Y",
|
||||||
"DCinBpki8hAuqZzliqQnUkZTwmwFgoAtFSkX7jJ2c6bcJz9nCNaQcgZX0zdrN1onduW3NA+YQfbFKM1u",
|
"F6lQuYPgl5AH9f8j8mjCjVUwMh6VeHF8KEq0FzoBEoWmGPJcGbAViQI4swmJmUWR6NkMEAwLisEo1JYG",
|
||||||
"jEd2okgazDen83ZhWBTprf7zeD7/MIc/DoaT2C7Kxd7dCOYJXwJS2yTLw9CuxoIWVvGMHw1HwyOecCtc",
|
"Lssbi0ITVeC20UQkmuKKSFtDgShzUATiQpNmt9uKswPNb6upQCgtabY4Hz9ZqOGV2KbvYe4Ii+Kj1Uac",
|
||||||
"GXs0XagKUgcUJ0sBbrfRroEcC2Frz4Y8QmJs2fOcZ+FxcKqCJnLx9u49gw5Ho69Npce4tDfqmoS/fc2R",
|
"2QrFa02xxWT1deIHBmkanptPL6bTl1P4Z2cwatpFc6eTHWEZyAtA8k1yseea2ZZgVKllJPcHw8G+DGSp",
|
||||||
"faM73ke+rgWu9vEPtomCeHbDT/vL03AuLeO9nNr1ZOk82RHcH0DfonnnffjPKz8Dx4IOpjTzBD3dbeb9",
|
"OGt6NJzpHEIGas6+FHi70U6BWLiwhWYD2aTEpmUPExk5d/FGO07EzfnSMYd7w+FN5+YyLuwcxnUgnz7k",
|
||||||
"yqk3kvYWRIDtJgkjJ5wnZhYMhCzZ526G/PSZdTB7i2Vr9n2Xfb336I9xsBPSSX3WxN4cjE/dpxPwZtpM",
|
"kz5z0exHVVEonPfhd7KplGR0Jt90h8fuuzBrTg63MqkjyRZff8A0Uf2Mb7AUNmbgXWIEVaxbi5nFQrGM",
|
||||||
"Q0BIRnHfY8Uzni4Pu3uPh4AOftv1N9fjk/HBZnBuZQ+P5ecPPKn1kOh+4ERxhsbbNl8X98tOl+wInTZ/",
|
"5FQbh7z3YO7zWV9ZrwNgkdu0o5Ln2q9TufAItwvlrcSXrI2t28XjMHY8hDaiIrgnc+qYi97GcWlbTyD8",
|
||||||
"BwAA///xoj5w+wwAAA==",
|
"eSrsTICKM/GhdQM/fBBtmt6m2nAx/0m+zm3mcRRsibRU7xLxM4eLc/1G8d4DWtaAwkX2CrSIaOzRF8qz",
|
||||||
|
"vBc9jixrJDqqLMe3dLk2wJcWzyc6qcOVESurHplOuhXa79oZ2BbsZCXYHz70ZDFXpUJVAANSc3NdL7LI",
|
||||||
|
"qxMZeBfnzo+Vh1vhbebgU6URksXtYrXBbW5nYx8MxC9tMn/QNWzdBnfMqqkKJ+7SqtrZrPk3Du5jZJcj",
|
||||||
|
"dvoRYm6t7be2qm6Z8zvWV8enN9O87tDPxm5K/EXSL4MKcxnJ8GKv9WXSBbQFNhfJk9Oj10c7q0Wx0fV1",
|
||||||
|
"cNcHa2exK3S1yyo9QFuVvl4b9/vWKb61wYzrfwMAAP//9tkexLESAAA=",
|
||||||
}
|
}
|
||||||
|
|
||||||
// GetSwagger returns the content of the embedded swagger specification file
|
// GetSwagger returns the content of the embedded swagger specification file
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package common
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
SERVICENAME = "casaos"
|
SERVICENAME = "casaos"
|
||||||
VERSION = "0.4.4"
|
VERSION = "0.4.4.3"
|
||||||
BODY = " "
|
BODY = " "
|
||||||
|
RANW_NAME = "IceWhale-RemoteAccess"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -1,23 +1,12 @@
|
|||||||
package common
|
package common
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/codegen/message_bus"
|
"github.com/IceWhaleTech/CasaOS/codegen/message_bus"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
|
||||||
// devtype -> action -> event
|
// devtype -> action -> event
|
||||||
EventTypes map[string]map[string]message_bus.EventType
|
var EventTypes = []message_bus.EventType{
|
||||||
|
{Name: "casaos:system:utilization", SourceID: SERVICENAME, PropertyTypeList: []message_bus.PropertyType{}},
|
||||||
PropertyNameLookupMaps = map[string]map[string]string{
|
{Name: "casaos:file:recover", SourceID: SERVICENAME, PropertyTypeList: []message_bus.PropertyType{}},
|
||||||
"system": {
|
{Name: "casaos:file:operate", SourceID: SERVICENAME, PropertyTypeList: []message_bus.PropertyType{}},
|
||||||
fmt.Sprintf("%s:%s", SERVICENAME, "utilization"): "ID_BUS",
|
|
||||||
},
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ActionPastTense = map[string]string{
|
|
||||||
"add": "added",
|
|
||||||
"remove": "removed",
|
|
||||||
}
|
|
||||||
)
|
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ package drivers
|
|||||||
import (
|
import (
|
||||||
_ "github.com/IceWhaleTech/CasaOS/drivers/dropbox"
|
_ "github.com/IceWhaleTech/CasaOS/drivers/dropbox"
|
||||||
_ "github.com/IceWhaleTech/CasaOS/drivers/google_drive"
|
_ "github.com/IceWhaleTech/CasaOS/drivers/google_drive"
|
||||||
|
_ "github.com/IceWhaleTech/CasaOS/drivers/onedrive"
|
||||||
)
|
)
|
||||||
|
|
||||||
// All do nothing,just for import
|
// All do nothing,just for import
|
||||||
|
|||||||
@@ -96,5 +96,8 @@ func (d *Dropbox) Remove(ctx context.Context, obj model.Obj) error {
|
|||||||
func (d *Dropbox) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
func (d *Dropbox) Put(ctx context.Context, dstDir model.Obj, stream model.FileStreamer, up driver.UpdateProgress) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func (d *Dropbox) GetInfo(ctx context.Context) (string, string, string, error) {
|
||||||
|
return "", "", "", nil
|
||||||
|
}
|
||||||
|
|
||||||
var _ driver.Driver = (*Dropbox)(nil)
|
var _ driver.Driver = (*Dropbox)(nil)
|
||||||
|
|||||||
@@ -2,12 +2,9 @@ package dropbox
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/op"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const ICONURL = "./img/driver/Dropbox.svg"
|
const ICONURL = "./img/driver/Dropbox.svg"
|
||||||
const APPKEY = "tciqajyazzdygt9"
|
|
||||||
const APPSECRET = "e7gtmv441cwdf0n"
|
|
||||||
|
|
||||||
type Addition struct {
|
type Addition struct {
|
||||||
driver.RootID
|
driver.RootID
|
||||||
@@ -15,7 +12,7 @@ type Addition struct {
|
|||||||
AppKey string `json:"app_key" type:"string" default:"tciqajyazzdygt9" omit:"true"`
|
AppKey string `json:"app_key" type:"string" default:"tciqajyazzdygt9" omit:"true"`
|
||||||
AppSecret string `json:"app_secret" type:"string" default:"e7gtmv441cwdf0n" omit:"true"`
|
AppSecret string `json:"app_secret" type:"string" default:"e7gtmv441cwdf0n" omit:"true"`
|
||||||
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" omit:"true"`
|
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" omit:"true"`
|
||||||
AuthUrl string `json:"auth_url" type:"string" default:"https://www.dropbox.com/oauth2/authorize?client_id=tciqajyazzdygt9&redirect_uri=https://cloudoauth.files.casaos.app&response_type=code&token_access_type=offline&state=${HOST}%2Fv1%2Frecover%2FDropbox&&force_reapprove=true&force_reauthentication=true"`
|
AuthUrl string `json:"auth_url" type:"string" default:""`
|
||||||
Icon string `json:"icon" type:"string" default:"./img/driver/Dropbox.svg"`
|
Icon string `json:"icon" type:"string" default:"./img/driver/Dropbox.svg"`
|
||||||
Code string `json:"code" type:"string" help:"code from auth_url" omit:"true"`
|
Code string `json:"code" type:"string" help:"code from auth_url" omit:"true"`
|
||||||
}
|
}
|
||||||
@@ -25,9 +22,3 @@ var config = driver.Config{
|
|||||||
OnlyProxy: true,
|
OnlyProxy: true,
|
||||||
DefaultRoot: "root",
|
DefaultRoot: "root",
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
op.RegisterDriver(func() driver.Driver {
|
|
||||||
return &Dropbox{}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -10,6 +10,11 @@ import (
|
|||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
app_key = "private build"
|
||||||
|
app_secret = "private build"
|
||||||
|
)
|
||||||
|
|
||||||
func (d *Dropbox) getRefreshToken() error {
|
func (d *Dropbox) getRefreshToken() error {
|
||||||
url := "https://api.dropbox.com/oauth2/token"
|
url := "https://api.dropbox.com/oauth2/token"
|
||||||
var resp base.TokenResp
|
var resp base.TokenResp
|
||||||
@@ -100,3 +105,12 @@ func (d *Dropbox) getFiles(path string) ([]File, error) {
|
|||||||
|
|
||||||
return res, nil
|
return res, nil
|
||||||
}
|
}
|
||||||
|
func GetConfig() Dropbox {
|
||||||
|
dp := Dropbox{}
|
||||||
|
dp.RootFolderID = ""
|
||||||
|
dp.AuthUrl = "https://www.dropbox.com/oauth2/authorize?client_id=" + app_key + "&redirect_uri=https://cloudoauth.files.casaos.app&response_type=code&token_access_type=offline&state=${HOST}%2Fv1%2Frecover%2FDropbox&&force_reapprove=true&force_reauthentication=true"
|
||||||
|
dp.AppKey = app_key
|
||||||
|
dp.AppSecret = app_secret
|
||||||
|
dp.Icon = "./img/driver/Dropbox.svg"
|
||||||
|
return dp
|
||||||
|
}
|
||||||
|
|||||||
@@ -80,6 +80,9 @@ func (d *GoogleDrive) GetUserInfo(ctx context.Context) (string, error) {
|
|||||||
return user.User.EmailAddress, nil
|
return user.User.EmailAddress, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (d *GoogleDrive) GetInfo(ctx context.Context) (string, string, string, error) {
|
||||||
|
return "", "", "", nil
|
||||||
|
}
|
||||||
func (d *GoogleDrive) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
func (d *GoogleDrive) MakeDir(ctx context.Context, parentDir model.Obj, dirName string) error {
|
||||||
data := base.Json{
|
data := base.Json{
|
||||||
"name": dirName,
|
"name": dirName,
|
||||||
|
|||||||
@@ -2,22 +2,19 @@ package google_drive
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/op"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
const ICONURL = "./img/driver/GoogleDrive.svg"
|
const ICONURL = "./img/driver/GoogleDrive.svg"
|
||||||
const CLIENTID = "921743327851-urr4f7jjfp4ts639evqb3i4m4qb4u4cc.apps.googleusercontent.com"
|
|
||||||
const CLIENTSECRET = "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"
|
|
||||||
|
|
||||||
type Addition struct {
|
type Addition struct {
|
||||||
driver.RootID
|
driver.RootID
|
||||||
RefreshToken string `json:"refresh_token" required:"true" omit:"true"`
|
RefreshToken string `json:"refresh_token" required:"true" omit:"true"`
|
||||||
OrderBy string `json:"order_by" type:"string" help:"such as: folder,name,modifiedTime" omit:"true"`
|
OrderBy string `json:"order_by" type:"string" help:"such as: folder,name,modifiedTime" omit:"true"`
|
||||||
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" omit:"true"`
|
OrderDirection string `json:"order_direction" type:"select" options:"asc,desc" omit:"true"`
|
||||||
ClientID string `json:"client_id" required:"true" default:"921743327851-urr4f7jjfp4ts639evqb3i4m4qb4u4cc.apps.googleusercontent.com" omit:"true"`
|
ClientID string `json:"client_id" required:"true" default:"" omit:"true"`
|
||||||
ClientSecret string `json:"client_secret" required:"true" default:"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" omit:"true"`
|
ClientSecret string `json:"client_secret" required:"true" default:"" omit:"true"`
|
||||||
ChunkSize int64 `json:"chunk_size" type:"number" help:"chunk size while uploading (unit: MB)" omit:"true"`
|
ChunkSize int64 `json:"chunk_size" type:"number" help:"chunk size while uploading (unit: MB)" omit:"true"`
|
||||||
AuthUrl string `json:"auth_url" type:"string" default:"https://accounts.google.com/o/oauth2/auth/oauthchooseaccount?response_type=code&client_id=921743327851-urr4f7jjfp4ts639evqb3i4m4qb4u4cc.apps.googleusercontent.com&redirect_uri=https%3A%2F%2Fcloudoauth.files.casaos.app&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive&access_type=offline&approval_prompt=force&state=${HOST}%2Fv1%2Frecover%2FGoogleDrive&service=lso&o2v=1&flowName=GeneralOAuthFlow"`
|
AuthUrl string `json:"auth_url" type:"string" default:""`
|
||||||
Icon string `json:"icon" type:"string" default:"./img/driver/GoogleDrive.svg"`
|
Icon string `json:"icon" type:"string" default:"./img/driver/GoogleDrive.svg"`
|
||||||
Code string `json:"code" type:"string" help:"code from auth_url" omit:"true"`
|
Code string `json:"code" type:"string" help:"code from auth_url" omit:"true"`
|
||||||
}
|
}
|
||||||
@@ -27,9 +24,3 @@ var config = driver.Config{
|
|||||||
OnlyProxy: true,
|
OnlyProxy: true,
|
||||||
DefaultRoot: "root",
|
DefaultRoot: "root",
|
||||||
}
|
}
|
||||||
|
|
||||||
func init() {
|
|
||||||
op.RegisterDriver(func() driver.Driver {
|
|
||||||
return &GoogleDrive{}
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -16,6 +16,11 @@ import (
|
|||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
client_id = "private build"
|
||||||
|
client_secret = "private build"
|
||||||
|
)
|
||||||
|
|
||||||
// do others that not defined in Driver interface
|
// do others that not defined in Driver interface
|
||||||
|
|
||||||
func (d *GoogleDrive) getRefreshToken() error {
|
func (d *GoogleDrive) getRefreshToken() error {
|
||||||
@@ -150,3 +155,13 @@ func (d *GoogleDrive) chunkUpload(ctx context.Context, stream model.FileStreamer
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
func GetConfig() GoogleDrive {
|
||||||
|
config := GoogleDrive{}
|
||||||
|
config.ClientID = client_id
|
||||||
|
config.ClientSecret = client_secret
|
||||||
|
config.RootFolderID = "root"
|
||||||
|
config.AuthUrl = "https://accounts.google.com/o/oauth2/auth/oauthchooseaccount?response_type=code&client_id=" + client_id + "&redirect_uri=https%3A%2F%2Fcloudoauth.files.casaos.app&scope=https%3A%2F%2Fwww.googleapis.com%2Fauth%2Fdrive&access_type=offline&approval_prompt=force&state=${HOST}%2Fv1%2Frecover%2FGoogleDrive&service=lso&o2v=1&flowName=GeneralOAuthFlow"
|
||||||
|
config.Icon = "./img/driver/GoogleDrive.svg"
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|||||||
70
drivers/onedrive/drive.go
Normal file
70
drivers/onedrive/drive.go
Normal file
@@ -0,0 +1,70 @@
|
|||||||
|
package onedrive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Onedrive struct {
|
||||||
|
model.StorageA
|
||||||
|
Addition
|
||||||
|
AccessToken string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Onedrive) Config() driver.Config {
|
||||||
|
return config
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Onedrive) GetAddition() driver.Additional {
|
||||||
|
return &d.Addition
|
||||||
|
}
|
||||||
|
func (d *Onedrive) Init(ctx context.Context) error {
|
||||||
|
if d.ChunkSize < 1 {
|
||||||
|
d.ChunkSize = 5
|
||||||
|
}
|
||||||
|
if len(d.RefreshToken) == 0 {
|
||||||
|
return d.getRefreshToken()
|
||||||
|
}
|
||||||
|
return d.refreshToken()
|
||||||
|
}
|
||||||
|
func (d *Onedrive) GetUserInfo(ctx context.Context) (string, error) {
|
||||||
|
return "", nil
|
||||||
|
}
|
||||||
|
func (d *Onedrive) GetInfo(ctx context.Context) (string, string, string, error) {
|
||||||
|
url := d.GetMetaUrl(false, "/")
|
||||||
|
user := Info{}
|
||||||
|
resp, err := d.Request(url, http.MethodGet, nil, &user)
|
||||||
|
if err != nil {
|
||||||
|
return "", "", "", err
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("resp", zap.Any("resp", resp))
|
||||||
|
return user.LastModifiedBy.User.DisplayName, user.ParentReference.DriveID, user.ParentReference.DriveType, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Onedrive) GetSpaceSize(ctx context.Context) (used string, total string, err error) {
|
||||||
|
host := onedriveHostMap[d.Region]
|
||||||
|
url := fmt.Sprintf("%s/v1.0/me/drive/quota", host.Api)
|
||||||
|
size := About{}
|
||||||
|
resp, err := d.Request(url, http.MethodGet, nil, &size)
|
||||||
|
if err != nil {
|
||||||
|
return used, total, err
|
||||||
|
}
|
||||||
|
logger.Info("resp", zap.Any("resp", resp))
|
||||||
|
used = strconv.Itoa(size.Used)
|
||||||
|
total = strconv.Itoa(size.Total)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (d *Onedrive) Drop(ctx context.Context) error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
var _ driver.Driver = (*Onedrive)(nil)
|
||||||
69
drivers/onedrive/meta.go
Normal file
69
drivers/onedrive/meta.go
Normal file
@@ -0,0 +1,69 @@
|
|||||||
|
package onedrive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
||||||
|
)
|
||||||
|
|
||||||
|
const ICONURL = "./img/driver/OneDrive.svg"
|
||||||
|
|
||||||
|
type Host struct {
|
||||||
|
Oauth string
|
||||||
|
Api string
|
||||||
|
}
|
||||||
|
|
||||||
|
type TokenErr struct {
|
||||||
|
Error string `json:"error"`
|
||||||
|
ErrorDescription string `json:"error_description"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type RespErr struct {
|
||||||
|
Error struct {
|
||||||
|
Code string `json:"code"`
|
||||||
|
Message string `json:"message"`
|
||||||
|
} `json:"error"`
|
||||||
|
}
|
||||||
|
type Addition struct {
|
||||||
|
Region string `json:"region" type:"select" required:"true" options:"global,cn,us,de" default:"global"`
|
||||||
|
IsSharepoint bool `json:"is_sharepoint"`
|
||||||
|
ClientID string `json:"client_id" required:"true"`
|
||||||
|
ClientSecret string `json:"client_secret" required:"true"`
|
||||||
|
RedirectUri string `json:"redirect_uri" required:"true" default:""`
|
||||||
|
RefreshToken string `json:"refresh_token" required:"true"`
|
||||||
|
SiteId string `json:"site_id"`
|
||||||
|
ChunkSize int64 `json:"chunk_size" type:"number" default:"5"`
|
||||||
|
RootFolderID string `json:"root_folder_id"`
|
||||||
|
AuthUrl string `json:"auth_url" type:"string" default:""`
|
||||||
|
Icon string `json:"icon" type:"string" default:""`
|
||||||
|
Code string `json:"code" type:"string" help:"code from auth_url" omit:"true"`
|
||||||
|
}
|
||||||
|
type About struct {
|
||||||
|
Total int `json:"total"`
|
||||||
|
Used int `json:"used"`
|
||||||
|
State string `json:"state"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type Info struct {
|
||||||
|
LastModifiedBy struct {
|
||||||
|
Application struct {
|
||||||
|
DisplayName string `json:"displayName"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
} `json:"application"`
|
||||||
|
Device struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
} `json:"device"`
|
||||||
|
User struct {
|
||||||
|
DisplayName string `json:"displayName"`
|
||||||
|
ID string `json:"id"`
|
||||||
|
} `json:"user"`
|
||||||
|
} `json:"lastModifiedBy"`
|
||||||
|
ParentReference struct {
|
||||||
|
DriveID string `json:"driveId"`
|
||||||
|
DriveType string `json:"driveType"`
|
||||||
|
} `json:"parentReference"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var config = driver.Config{
|
||||||
|
Name: "Onedrive",
|
||||||
|
LocalSort: true,
|
||||||
|
DefaultRoot: "/",
|
||||||
|
}
|
||||||
182
drivers/onedrive/util.go
Normal file
182
drivers/onedrive/util.go
Normal file
@@ -0,0 +1,182 @@
|
|||||||
|
package onedrive
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/url"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/drivers/base"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
client_id = "private build"
|
||||||
|
client_secret = "private build"
|
||||||
|
)
|
||||||
|
var onedriveHostMap = map[string]Host{
|
||||||
|
"global": {
|
||||||
|
Oauth: "https://login.microsoftonline.com",
|
||||||
|
Api: "https://graph.microsoft.com",
|
||||||
|
},
|
||||||
|
"cn": {
|
||||||
|
Oauth: "https://login.chinacloudapi.cn",
|
||||||
|
Api: "https://microsoftgraph.chinacloudapi.cn",
|
||||||
|
},
|
||||||
|
"us": {
|
||||||
|
Oauth: "https://login.microsoftonline.us",
|
||||||
|
Api: "https://graph.microsoft.us",
|
||||||
|
},
|
||||||
|
"de": {
|
||||||
|
Oauth: "https://login.microsoftonline.de",
|
||||||
|
Api: "https://graph.microsoft.de",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
func EncodePath(path string, all ...bool) string {
|
||||||
|
seg := strings.Split(path, "/")
|
||||||
|
toReplace := []struct {
|
||||||
|
Src string
|
||||||
|
Dst string
|
||||||
|
}{
|
||||||
|
{Src: "%", Dst: "%25"},
|
||||||
|
{"%", "%25"},
|
||||||
|
{"?", "%3F"},
|
||||||
|
{"#", "%23"},
|
||||||
|
}
|
||||||
|
for i := range seg {
|
||||||
|
if len(all) > 0 && all[0] {
|
||||||
|
seg[i] = url.PathEscape(seg[i])
|
||||||
|
} else {
|
||||||
|
for j := range toReplace {
|
||||||
|
seg[i] = strings.ReplaceAll(seg[i], toReplace[j].Src, toReplace[j].Dst)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(seg, "/")
|
||||||
|
}
|
||||||
|
func (d *Onedrive) GetMetaUrl(auth bool, path string) string {
|
||||||
|
host := onedriveHostMap[d.Region]
|
||||||
|
path = EncodePath(path, true)
|
||||||
|
if auth {
|
||||||
|
return host.Oauth
|
||||||
|
}
|
||||||
|
if d.IsSharepoint {
|
||||||
|
if path == "/" || path == "\\" {
|
||||||
|
return fmt.Sprintf("%s/v1.0/sites/%s/drive/root", host.Api, d.SiteId)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%s/v1.0/sites/%s/drive/root:%s:", host.Api, d.SiteId, path)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if path == "/" || path == "\\" {
|
||||||
|
return fmt.Sprintf("%s/v1.0/me/drive/root", host.Api)
|
||||||
|
} else {
|
||||||
|
return fmt.Sprintf("%s/v1.0/me/drive/root:%s:", host.Api, path)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Onedrive) refreshToken() error {
|
||||||
|
var err error
|
||||||
|
for i := 0; i < 3; i++ {
|
||||||
|
err = d._refreshToken()
|
||||||
|
if err == nil {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Onedrive) getRefreshToken() error {
|
||||||
|
url := d.GetMetaUrl(true, "") + "/common/oauth2/v2.0/token"
|
||||||
|
var resp base.TokenResp
|
||||||
|
var e TokenErr
|
||||||
|
|
||||||
|
res, err := base.RestyClient.R().SetResult(&resp).SetError(&e).SetFormData(map[string]string{
|
||||||
|
"grant_type": "authorization_code",
|
||||||
|
"client_id": d.ClientID,
|
||||||
|
"client_secret": d.ClientSecret,
|
||||||
|
"code": d.Code,
|
||||||
|
"redirect_uri": d.RedirectUri,
|
||||||
|
}).Post(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.Info("get refresh token", zap.String("res", res.String()))
|
||||||
|
if e.Error != "" {
|
||||||
|
return fmt.Errorf("%s", e.ErrorDescription)
|
||||||
|
}
|
||||||
|
if resp.RefreshToken == "" {
|
||||||
|
return errors.New("refresh token is empty")
|
||||||
|
}
|
||||||
|
d.RefreshToken, d.AccessToken = resp.RefreshToken, resp.AccessToken
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Onedrive) _refreshToken() error {
|
||||||
|
url := d.GetMetaUrl(true, "") + "/common/oauth2/v2.0/token"
|
||||||
|
var resp base.TokenResp
|
||||||
|
var e TokenErr
|
||||||
|
|
||||||
|
res, err := base.RestyClient.R().SetResult(&resp).SetError(&e).SetFormData(map[string]string{
|
||||||
|
"grant_type": "refresh_token",
|
||||||
|
"client_id": d.ClientID,
|
||||||
|
"client_secret": d.ClientSecret,
|
||||||
|
"redirect_uri": d.RedirectUri,
|
||||||
|
"refresh_token": d.RefreshToken,
|
||||||
|
}).Post(url)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
logger.Info("get refresh token", zap.String("res", res.String()))
|
||||||
|
if e.Error != "" {
|
||||||
|
return fmt.Errorf("%s", e.ErrorDescription)
|
||||||
|
}
|
||||||
|
if resp.RefreshToken == "" {
|
||||||
|
return errors.New("refresh token is empty")
|
||||||
|
}
|
||||||
|
d.RefreshToken, d.AccessToken = resp.RefreshToken, resp.AccessToken
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (d *Onedrive) Request(url string, method string, callback base.ReqCallback, resp interface{}) ([]byte, error) {
|
||||||
|
req := base.RestyClient.R()
|
||||||
|
req.SetHeader("Authorization", "Bearer "+d.AccessToken)
|
||||||
|
if callback != nil {
|
||||||
|
callback(req)
|
||||||
|
}
|
||||||
|
if resp != nil {
|
||||||
|
req.SetResult(resp)
|
||||||
|
}
|
||||||
|
var e RespErr
|
||||||
|
req.SetError(&e)
|
||||||
|
res, err := req.Execute(method, url)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
if e.Error.Code != "" {
|
||||||
|
if e.Error.Code == "InvalidAuthenticationToken" {
|
||||||
|
err = d.refreshToken()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return d.Request(url, method, callback, resp)
|
||||||
|
}
|
||||||
|
return nil, errors.New(e.Error.Message)
|
||||||
|
}
|
||||||
|
return res.Body(), nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetConfig() Onedrive {
|
||||||
|
config := Onedrive{}
|
||||||
|
config.ClientID = client_id
|
||||||
|
config.ClientSecret = client_secret
|
||||||
|
config.RootFolderID = "/"
|
||||||
|
config.AuthUrl = "https://login.microsoftonline.com/common/oauth2/v2.0/authorize?client_id=" + client_id + "&response_type=code&redirect_uri=https%3A%2F%2Fcloudoauth.files.casaos.app&scope=offline_access+files.readwrite.all&state=${HOST}%2Fv1%2Frecover%2FOnedrive"
|
||||||
|
config.Icon = "./img/driver/OneDrive.svg"
|
||||||
|
config.Region = "global"
|
||||||
|
config.RedirectUri = "https://cloudoauth.files.casaos.app"
|
||||||
|
|
||||||
|
return config
|
||||||
|
}
|
||||||
4
go.mod
4
go.mod
@@ -4,7 +4,7 @@ go 1.20
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
|
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
|
||||||
github.com/IceWhaleTech/CasaOS-Common v0.4.4-alpha8
|
github.com/IceWhaleTech/CasaOS-Common v0.4.7-alpha4
|
||||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||||
github.com/deckarep/golang-set/v2 v2.3.0
|
github.com/deckarep/golang-set/v2 v2.3.0
|
||||||
github.com/deepmap/oapi-codegen v1.12.4
|
github.com/deepmap/oapi-codegen v1.12.4
|
||||||
@@ -33,6 +33,7 @@ require (
|
|||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/robfig/cron/v3 v3.0.1
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
|
github.com/samber/lo v1.38.1
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shirou/gopsutil/v3 v3.23.2
|
github.com/shirou/gopsutil/v3 v3.23.2
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
@@ -106,7 +107,6 @@ require (
|
|||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/pmezard/go-difflib v1.0.0 // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/samber/lo v1.38.1 // indirect
|
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.1 // indirect
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||||
|
|||||||
4
go.sum
4
go.sum
@@ -1,7 +1,7 @@
|
|||||||
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d h1:62lEBImTxZ83pgzywgDNIrPPuQ+j4ep9QjqrWBn1hrU=
|
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d h1:62lEBImTxZ83pgzywgDNIrPPuQ+j4ep9QjqrWBn1hrU=
|
||||||
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ=
|
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ=
|
||||||
github.com/IceWhaleTech/CasaOS-Common v0.4.4-alpha8 h1:UhCg3d9Cxhx7KVmqh8oUrUl1qFmFdcHee3Zkk4+P2JA=
|
github.com/IceWhaleTech/CasaOS-Common v0.4.7-alpha4 h1:bsVQ+kdVkmPsqX6lxxETaShiMb9I8OgiR4xrEQ/vyss=
|
||||||
github.com/IceWhaleTech/CasaOS-Common v0.4.4-alpha8/go.mod h1:2IuYyy5qW1BE6jqC6M+tOU+WtUec1K565rLATBJ9p/0=
|
github.com/IceWhaleTech/CasaOS-Common v0.4.7-alpha4/go.mod h1:2IuYyy5qW1BE6jqC6M+tOU+WtUec1K565rLATBJ9p/0=
|
||||||
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
||||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||||
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
|
|||||||
@@ -34,14 +34,16 @@ type Reader interface {
|
|||||||
// List files in the path
|
// List files in the path
|
||||||
// if identify files by path, need to set ID with path,like path.Join(dir.GetID(), obj.GetName())
|
// if identify files by path, need to set ID with path,like path.Join(dir.GetID(), obj.GetName())
|
||||||
// if identify files by id, need to set ID with corresponding id
|
// if identify files by id, need to set ID with corresponding id
|
||||||
List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error)
|
// List(ctx context.Context, dir model.Obj, args model.ListArgs) ([]model.Obj, error)
|
||||||
// Link get url/filepath/reader of file
|
// Link get url/filepath/reader of file
|
||||||
Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error)
|
// Link(ctx context.Context, file model.Obj, args model.LinkArgs) (*model.Link, error)
|
||||||
}
|
}
|
||||||
type User interface {
|
type User interface {
|
||||||
// GetRoot get root directory of user
|
// GetRoot get root directory of user
|
||||||
GetUserInfo(ctx context.Context) (string, error)
|
GetUserInfo(ctx context.Context) (string, error)
|
||||||
|
GetInfo(ctx context.Context) (string, string, string, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type Getter interface {
|
type Getter interface {
|
||||||
GetRoot(ctx context.Context) (model.Obj, error)
|
GetRoot(ctx context.Context) (model.Obj, error)
|
||||||
}
|
}
|
||||||
|
|||||||
23
main.go
23
main.go
@@ -18,7 +18,6 @@ import (
|
|||||||
|
|
||||||
util_http "github.com/IceWhaleTech/CasaOS-Common/utils/http"
|
util_http "github.com/IceWhaleTech/CasaOS-Common/utils/http"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/codegen/message_bus"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/common"
|
"github.com/IceWhaleTech/CasaOS/common"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
@@ -48,6 +47,9 @@ var (
|
|||||||
//go:embed api/casaos/openapi.yaml
|
//go:embed api/casaos/openapi.yaml
|
||||||
_docYAML string
|
_docYAML string
|
||||||
|
|
||||||
|
//go:embed build/sysroot/etc/casaos/casaos.conf.sample
|
||||||
|
_confSample string
|
||||||
|
|
||||||
configFlag = flag.String("c", "", "config address")
|
configFlag = flag.String("c", "", "config address")
|
||||||
dbFlag = flag.String("db", "", "db path")
|
dbFlag = flag.String("db", "", "db path")
|
||||||
versionFlag = flag.Bool("v", false, "version")
|
versionFlag = flag.Bool("v", false, "version")
|
||||||
@@ -63,7 +65,7 @@ func init() {
|
|||||||
println("git commit:", commit)
|
println("git commit:", commit)
|
||||||
println("build date:", date)
|
println("build date:", date)
|
||||||
|
|
||||||
config.InitSetup(*configFlag)
|
config.InitSetup(*configFlag, _confSample)
|
||||||
|
|
||||||
logger.LogInit(config.AppInfo.LogPath, config.AppInfo.LogSaveName, config.AppInfo.LogFileExt)
|
logger.LogInit(config.AppInfo.LogPath, config.AppInfo.LogSaveName, config.AppInfo.LogFileExt)
|
||||||
if len(*dbFlag) == 0 {
|
if len(*dbFlag) == 0 {
|
||||||
@@ -81,6 +83,7 @@ func init() {
|
|||||||
|
|
||||||
route.InitFunction()
|
route.InitFunction()
|
||||||
|
|
||||||
|
//service.MyService.System().GenreateSystemEntry()
|
||||||
///
|
///
|
||||||
//service.MountLists = make(map[string]*mountlib.MountPoint)
|
//service.MountLists = make(map[string]*mountlib.MountPoint)
|
||||||
//configfile.Install()
|
//configfile.Install()
|
||||||
@@ -101,20 +104,17 @@ func main() {
|
|||||||
if *versionFlag {
|
if *versionFlag {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
v1Router := route.InitV1Router()
|
v1Router := route.InitV1Router()
|
||||||
|
|
||||||
v2Router := route.InitV2Router()
|
v2Router := route.InitV2Router()
|
||||||
v2DocRouter := route.InitV2DocRouter(_docHTML, _docYAML)
|
v2DocRouter := route.InitV2DocRouter(_docHTML, _docYAML)
|
||||||
v3file := route.InitFile()
|
v3File := route.InitFile()
|
||||||
v4dir := route.InitDir()
|
|
||||||
mux := &util_http.HandlerMultiplexer{
|
mux := &util_http.HandlerMultiplexer{
|
||||||
HandlerMap: map[string]http.Handler{
|
HandlerMap: map[string]http.Handler{
|
||||||
"v1": v1Router,
|
"v1": v1Router,
|
||||||
"v2": v2Router,
|
"v2": v2Router,
|
||||||
|
"v3": v3File,
|
||||||
"doc": v2DocRouter,
|
"doc": v2DocRouter,
|
||||||
"v3": v3file,
|
|
||||||
"v4": v4dir,
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -143,6 +143,8 @@ func main() {
|
|||||||
"/v1/cloud",
|
"/v1/cloud",
|
||||||
"/v1/recover",
|
"/v1/recover",
|
||||||
"/v1/other",
|
"/v1/other",
|
||||||
|
"/v1/zt",
|
||||||
|
"/v1/test",
|
||||||
route.V2APIPath,
|
route.V2APIPath,
|
||||||
route.V2DocPath,
|
route.V2DocPath,
|
||||||
route.V3FilePath,
|
route.V3FilePath,
|
||||||
@@ -158,13 +160,10 @@ func main() {
|
|||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
var events []message_bus.EventType
|
|
||||||
events = append(events, message_bus.EventType{Name: "casaos:system:utilization", SourceID: common.SERVICENAME, PropertyTypeList: []message_bus.PropertyType{}})
|
|
||||||
events = append(events, message_bus.EventType{Name: "casaos:file:recover", SourceID: common.SERVICENAME, PropertyTypeList: []message_bus.PropertyType{}})
|
|
||||||
events = append(events, message_bus.EventType{Name: "casaos:file:operate", SourceID: common.SERVICENAME, PropertyTypeList: []message_bus.PropertyType{}})
|
|
||||||
// register at message bus
|
// register at message bus
|
||||||
for i := 0; i < 10; i++ {
|
for i := 0; i < 10; i++ {
|
||||||
response, err := service.MyService.MessageBus().RegisterEventTypesWithResponse(context.Background(), events)
|
response, err := service.MyService.MessageBus().RegisterEventTypesWithResponse(context.Background(), common.EventTypes)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("error when trying to register one or more event types - some event type will not be discoverable", zap.Error(err))
|
logger.Error("error when trying to register one or more event types - some event type will not be discoverable", zap.Error(err))
|
||||||
}
|
}
|
||||||
|
|||||||
7
model/drive.go
Normal file
7
model/drive.go
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type Drive struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Icon string `json:"icon"`
|
||||||
|
AuthUrl string `json:"auth_url"`
|
||||||
|
}
|
||||||
@@ -73,4 +73,5 @@ type BaseInfo struct {
|
|||||||
Hash string `json:"i"`
|
Hash string `json:"i"`
|
||||||
Version string `json:"v"`
|
Version string `json:"v"`
|
||||||
Channel string `json:"c,omitempty"`
|
Channel string `json:"c,omitempty"`
|
||||||
|
DriveModel string `json:"m,omitempty"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -23,3 +23,14 @@ type Path struct {
|
|||||||
Write bool `json:"write"`
|
Write bool `json:"write"`
|
||||||
Extensions map[string]interface{} `json:"extensions"`
|
Extensions map[string]interface{} `json:"extensions"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type DeviceInfo struct {
|
||||||
|
LanIpv4 []string `json:"lan_ipv4"`
|
||||||
|
Port int `json:"port"`
|
||||||
|
DeviceName string `json:"device_name"`
|
||||||
|
DeviceModel string `json:"device_model"`
|
||||||
|
DeviceSN string `json:"device_sn"`
|
||||||
|
Initialized bool `json:"initialized"`
|
||||||
|
OS_Version string `json:"os_version"`
|
||||||
|
Hash string `json:"hash"`
|
||||||
|
}
|
||||||
|
|||||||
39
package.json
Normal file
39
package.json
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
{
|
||||||
|
"name": "@icewhale/casaos-openapi",
|
||||||
|
"version": "0.0.1",
|
||||||
|
|
||||||
|
"scripts": {
|
||||||
|
"clean": "rm -rf generate",
|
||||||
|
"build": "rm -rf dist && tsc && yarn clean",
|
||||||
|
"generate:local": "openapi-generator-cli generate -g typescript-axios -i ./api/casaos/openapi.yaml -o ./generate",
|
||||||
|
"generate:npx": "npx @openapitools/openapi-generator-cli generate -g typescript-axios -i ./api/casaos/openapi.yaml -o ./generate",
|
||||||
|
"generate:ts": "npx openapi-typescript-codegen --input ./api/casaos/openapi.yaml --output ./generate",
|
||||||
|
"start": "yarn generate:local && yarn build"
|
||||||
|
},
|
||||||
|
"homepage": "https://github.com/IceWhaleTech/CasaOS#readme",
|
||||||
|
"description": "Casaos Typescript+Axios SDK",
|
||||||
|
"keywords": [
|
||||||
|
"CasaOS",
|
||||||
|
"SDK",
|
||||||
|
"CasaOS Axios"
|
||||||
|
],
|
||||||
|
"main": "dist/index.js",
|
||||||
|
"files": [
|
||||||
|
"LICENSE",
|
||||||
|
"README.md",
|
||||||
|
"dist",
|
||||||
|
"generate"
|
||||||
|
],
|
||||||
|
"dependencies": {
|
||||||
|
"axios": "^1.1.0"
|
||||||
|
},
|
||||||
|
"devDependencies": {
|
||||||
|
"all-contributors-cli": "^6.24.0",
|
||||||
|
"@openapitools/openapi-generator-cli": "2.5.2",
|
||||||
|
"@types/node": "^18.8.3",
|
||||||
|
"openapi-typescript-codegen": "^0.23.0",
|
||||||
|
"typescript": "^4.9.5"
|
||||||
|
},
|
||||||
|
"author": "casaos",
|
||||||
|
"license": "Apache-2.0"
|
||||||
|
}
|
||||||
@@ -10,6 +10,10 @@
|
|||||||
*/
|
*/
|
||||||
package config
|
package config
|
||||||
|
|
||||||
const (
|
import (
|
||||||
USERCONFIGURL = "/etc/casaos/casaos.conf"
|
"path/filepath"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/constants"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
var CasaOSConfigFilePath = filepath.Join(constants.DefaultConfigPath, "casaos.conf")
|
||||||
|
|||||||
@@ -14,80 +14,72 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path"
|
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"runtime"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/constants"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/common"
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/go-ini/ini"
|
"github.com/go-ini/ini"
|
||||||
)
|
)
|
||||||
|
|
||||||
// 系统配置
|
var (
|
||||||
var SysInfo = &model.SysInfoModel{}
|
SysInfo = &model.SysInfoModel{}
|
||||||
|
AppInfo = &model.APPModel{
|
||||||
|
DBPath: constants.DefaultDataPath,
|
||||||
|
LogPath: constants.DefaultLogPath,
|
||||||
|
LogSaveName: common.SERVICENAME,
|
||||||
|
LogFileExt: "log",
|
||||||
|
ShellPath: "/usr/share/casaos/shell",
|
||||||
|
UserDataPath: filepath.Join(constants.DefaultDataPath, "conf"),
|
||||||
|
}
|
||||||
|
CommonInfo = &model.CommonModel{
|
||||||
|
RuntimePath: constants.DefaultRuntimePath,
|
||||||
|
}
|
||||||
|
ServerInfo = &model.ServerModel{}
|
||||||
|
SystemConfigInfo = &model.SystemConfig{}
|
||||||
|
FileSettingInfo = &model.FileSetting{}
|
||||||
|
|
||||||
// 用户相关
|
Cfg *ini.File
|
||||||
var AppInfo = &model.APPModel{}
|
ConfigFilePath string
|
||||||
|
)
|
||||||
var CommonInfo = &model.CommonModel{}
|
|
||||||
|
|
||||||
// var RedisInfo = &model.RedisModel{}
|
|
||||||
|
|
||||||
// server相关
|
|
||||||
var ServerInfo = &model.ServerModel{}
|
|
||||||
|
|
||||||
var SystemConfigInfo = &model.SystemConfig{}
|
|
||||||
|
|
||||||
var FileSettingInfo = &model.FileSetting{}
|
|
||||||
|
|
||||||
var Cfg *ini.File
|
|
||||||
|
|
||||||
// 初始化设置,获取系统的部分信息。
|
// 初始化设置,获取系统的部分信息。
|
||||||
func InitSetup(config string) {
|
func InitSetup(config string, sample string) {
|
||||||
configDir := USERCONFIGURL
|
ConfigFilePath = CasaOSConfigFilePath
|
||||||
if len(config) > 0 {
|
if len(config) > 0 {
|
||||||
configDir = config
|
ConfigFilePath = config
|
||||||
}
|
}
|
||||||
if runtime.GOOS == "darwin" {
|
|
||||||
configDir = "./conf/conf.conf"
|
// create default config file if not exist
|
||||||
|
if _, err := os.Stat(ConfigFilePath); os.IsNotExist(err) {
|
||||||
|
fmt.Println("config file not exist, create it")
|
||||||
|
// create config file
|
||||||
|
file, err := os.Create(ConfigFilePath)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
}
|
}
|
||||||
|
defer file.Close()
|
||||||
|
|
||||||
|
// write default config
|
||||||
|
_, err = file.WriteString(sample)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var err error
|
var err error
|
||||||
|
|
||||||
// 读取文件
|
// 读取文件
|
||||||
Cfg, err = ini.Load(configDir)
|
Cfg, err = ini.Load(ConfigFilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
Cfg, err = ini.Load("/etc/casaos.conf")
|
panic(err)
|
||||||
if err != nil {
|
|
||||||
Cfg, err = ini.Load("/casaOS/server/conf/conf.ini")
|
|
||||||
if err != nil {
|
|
||||||
fmt.Printf("Fail to read file: %v", err)
|
|
||||||
os.Exit(1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
mapTo("app", AppInfo)
|
mapTo("app", AppInfo)
|
||||||
// mapTo("redis", RedisInfo)
|
|
||||||
mapTo("server", ServerInfo)
|
mapTo("server", ServerInfo)
|
||||||
mapTo("system", SystemConfigInfo)
|
mapTo("system", SystemConfigInfo)
|
||||||
mapTo("file", FileSettingInfo)
|
mapTo("file", FileSettingInfo)
|
||||||
mapTo("common", CommonInfo)
|
mapTo("common", CommonInfo)
|
||||||
SystemConfigInfo.ConfigPath = configDir
|
|
||||||
if len(AppInfo.DBPath) == 0 {
|
|
||||||
AppInfo.DBPath = "/var/lib/casaos"
|
|
||||||
}
|
|
||||||
if len(AppInfo.LogPath) == 0 {
|
|
||||||
AppInfo.LogPath = "/var/log/casaos/"
|
|
||||||
}
|
|
||||||
if len(AppInfo.ShellPath) == 0 {
|
|
||||||
AppInfo.ShellPath = "/usr/share/casaos/shell"
|
|
||||||
}
|
|
||||||
if len(AppInfo.UserDataPath) == 0 {
|
|
||||||
AppInfo.UserDataPath = "/var/lib/casaos/conf"
|
|
||||||
}
|
|
||||||
if len(CommonInfo.RuntimePath) == 0 {
|
|
||||||
CommonInfo.RuntimePath = "/var/run/casaos"
|
|
||||||
}
|
|
||||||
Cfg.SaveTo(configDir)
|
|
||||||
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// 映射
|
// 映射
|
||||||
@@ -97,21 +89,3 @@ func mapTo(section string, v interface{}) {
|
|||||||
log.Fatalf("Cfg.MapTo %s err: %v", section, err)
|
log.Fatalf("Cfg.MapTo %s err: %v", section, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// 获取当前执行文件绝对路径(go run)
|
|
||||||
func getCurrentAbPathByCaller() string {
|
|
||||||
var abPath string
|
|
||||||
_, filename, _, ok := runtime.Caller(0)
|
|
||||||
if ok {
|
|
||||||
abPath = path.Dir(filename)
|
|
||||||
}
|
|
||||||
return abPath
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCurrentDirectory() string {
|
|
||||||
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
|
||||||
if err != nil {
|
|
||||||
log.Fatal(err)
|
|
||||||
}
|
|
||||||
return strings.Replace(dir, "\\", "/", -1)
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -431,7 +431,9 @@ func AddFile(ar archiver.Writer, path, commonPath string) error {
|
|||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
if path != commonPath {
|
if path != commonPath {
|
||||||
filename := info.Name()
|
//filename := info.Name()
|
||||||
|
filename := strings.TrimPrefix(path, commonPath)
|
||||||
|
filename = strings.TrimPrefix(filename, string(filepath.Separator))
|
||||||
err = ar.Write(archiver.File{
|
err = ar.Write(archiver.File{
|
||||||
FileInfo: archiver.FileInfo{
|
FileInfo: archiver.FileInfo{
|
||||||
FileInfo: info,
|
FileInfo: info,
|
||||||
|
|||||||
78
pkg/utils/httper/zerotier.go
Normal file
78
pkg/utils/httper/zerotier.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package httper
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ZTGet(url string) ([]byte, error) {
|
||||||
|
port, err := ioutil.ReadFile("/var/lib/zerotier-one/zerotier-one.port")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Build the target URL
|
||||||
|
targetURL := fmt.Sprintf("http://localhost:%s%s", strings.TrimSpace(string(port)), url)
|
||||||
|
|
||||||
|
// Create a new request
|
||||||
|
req, err := http.NewRequest("GET", targetURL, nil)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the X-ZT1-AUTH header
|
||||||
|
authToken, err := ioutil.ReadFile("/var/lib/zerotier-one/authtoken.secret")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("X-ZT1-AUTH", strings.TrimSpace(string(authToken)))
|
||||||
|
|
||||||
|
client := http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
respBody, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return respBody, nil
|
||||||
|
}
|
||||||
|
func ZTPost(url string, body string) ([]byte, error) {
|
||||||
|
port, err := ioutil.ReadFile("/var/lib/zerotier-one/zerotier-one.port")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
// Build the target URL
|
||||||
|
targetURL := fmt.Sprintf("http://localhost:%s%s", strings.TrimSpace(string(port)), url)
|
||||||
|
|
||||||
|
// Create a new request
|
||||||
|
req, err := http.NewRequest("POST", targetURL, strings.NewReader(body))
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the X-ZT1-AUTH header
|
||||||
|
authToken, err := ioutil.ReadFile("/var/lib/zerotier-one/authtoken.secret")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
req.Header.Set("X-ZT1-AUTH", strings.TrimSpace(string(authToken)))
|
||||||
|
|
||||||
|
client := http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
respBody, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return respBody, nil
|
||||||
|
}
|
||||||
@@ -1,6 +1,7 @@
|
|||||||
package ip_helper
|
package ip_helper
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
@@ -56,7 +57,30 @@ func GetDeviceAllIP(port string) []string {
|
|||||||
}
|
}
|
||||||
return address
|
return address
|
||||||
}
|
}
|
||||||
|
func GetDeviceAllIPv4() map[string]string {
|
||||||
|
address := make(map[string]string)
|
||||||
|
addrs, err := net.Interfaces()
|
||||||
|
if err != nil {
|
||||||
|
return address
|
||||||
|
}
|
||||||
|
for _, a := range addrs {
|
||||||
|
if a.Flags&net.FlagLoopback != 0 || a.Flags&net.FlagUp == 0 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
addrs, err := a.Addrs()
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("Error:", err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, addr := range addrs {
|
||||||
|
if ipnet, ok := addr.(*net.IPNet); ok && !ipnet.IP.IsLoopback() && ipnet.IP.To4() != nil {
|
||||||
|
address[a.Name] = ipnet.IP.String()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return address
|
||||||
|
}
|
||||||
func HasLocalIP(ip net.IP) bool {
|
func HasLocalIP(ip net.IP) bool {
|
||||||
if ip.IsLoopback() {
|
if ip.IsLoopback() {
|
||||||
return true
|
return true
|
||||||
|
|||||||
@@ -17,6 +17,7 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
file1 "github.com/IceWhaleTech/CasaOS-Common/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
"github.com/IceWhaleTech/CasaOS/common"
|
"github.com/IceWhaleTech/CasaOS/common"
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
@@ -24,6 +25,7 @@ import (
|
|||||||
"github.com/IceWhaleTech/CasaOS/pkg/samba"
|
"github.com/IceWhaleTech/CasaOS/pkg/samba"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
@@ -31,6 +33,7 @@ import (
|
|||||||
func InitFunction() {
|
func InitFunction() {
|
||||||
go InitNetworkMount()
|
go InitNetworkMount()
|
||||||
go InitInfo()
|
go InitInfo()
|
||||||
|
//go InitZerotier()
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitInfo() {
|
func InitInfo() {
|
||||||
@@ -51,6 +54,12 @@ func InitInfo() {
|
|||||||
}
|
}
|
||||||
mb.Hash = encryption.GetMD5ByStr(mac)
|
mb.Hash = encryption.GetMD5ByStr(mac)
|
||||||
mb.Version = common.VERSION
|
mb.Version = common.VERSION
|
||||||
|
osRelease, _ := file1.ReadOSRelease()
|
||||||
|
|
||||||
|
mb.DriveModel = osRelease["MODEL"]
|
||||||
|
if len(mb.DriveModel) == 0 {
|
||||||
|
mb.DriveModel = "Casa"
|
||||||
|
}
|
||||||
os.Remove(config.AppInfo.DBPath + "/baseinfo.conf")
|
os.Remove(config.AppInfo.DBPath + "/baseinfo.conf")
|
||||||
by, err := json.Marshal(mb)
|
by, err := json.Marshal(mb)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -98,3 +107,6 @@ func InitNetworkMount() {
|
|||||||
logger.Error("mount storage err", zap.Any("err", err))
|
logger.Error("mount storage err", zap.Any("err", err))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func InitZerotier() {
|
||||||
|
v1.CheckNetwork()
|
||||||
|
}
|
||||||
|
|||||||
19
route/v1.go
19
route/v1.go
@@ -7,6 +7,7 @@ import (
|
|||||||
"github.com/IceWhaleTech/CasaOS-Common/external"
|
"github.com/IceWhaleTech/CasaOS-Common/external"
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/middleware"
|
"github.com/IceWhaleTech/CasaOS-Common/middleware"
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
|
"github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/common"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
||||||
|
|
||||||
@@ -35,17 +36,16 @@ func InitV1Router() *gin.Engine {
|
|||||||
r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug
|
r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug
|
||||||
|
|
||||||
r.GET("/v1/sys/version/check", v1.GetSystemCheckVersion)
|
r.GET("/v1/sys/version/check", v1.GetSystemCheckVersion)
|
||||||
|
r.GET("/v1/sys/version/current", func(ctx *gin.Context) {
|
||||||
|
ctx.String(200, common.VERSION)
|
||||||
|
})
|
||||||
r.GET("/ping", func(ctx *gin.Context) {
|
r.GET("/ping", func(ctx *gin.Context) {
|
||||||
ctx.String(200, "pong")
|
ctx.String(200, "pong")
|
||||||
})
|
})
|
||||||
r.GET("/v1/recover/:type", v1.GetRecoverStorage)
|
r.GET("/v1/recover/:type", v1.GetRecoverStorage)
|
||||||
v1Group := r.Group("/v1")
|
v1Group := r.Group("/v1")
|
||||||
|
// r.Any("/v1/test", v1.CheckNetwork)
|
||||||
v1Group.Use(jwt.ExceptLocalhost(
|
v1Group.Use(jwt.ExceptLocalhost(func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) }))
|
||||||
func() (*ecdsa.PublicKey, error) {
|
|
||||||
return external.GetPublicKey(config.CommonInfo.RuntimePath)
|
|
||||||
},
|
|
||||||
))
|
|
||||||
{
|
{
|
||||||
|
|
||||||
v1SysGroup := v1Group.Group("/sys")
|
v1SysGroup := v1Group.Group("/sys")
|
||||||
@@ -79,6 +79,7 @@ func InitV1Router() *gin.Engine {
|
|||||||
// v1SysGroup.PUT("/port", v1.PutCasaOSPort)
|
// v1SysGroup.PUT("/port", v1.PutCasaOSPort)
|
||||||
v1SysGroup.GET("/proxy", v1.GetSystemProxy)
|
v1SysGroup.GET("/proxy", v1.GetSystemProxy)
|
||||||
v1SysGroup.PUT("/state/:state", v1.PutSystemState)
|
v1SysGroup.PUT("/state/:state", v1.PutSystemState)
|
||||||
|
v1SysGroup.GET("/entry", v1.GetSystemEntry)
|
||||||
}
|
}
|
||||||
v1PortGroup := v1Group.Group("/port")
|
v1PortGroup := v1Group.Group("/port")
|
||||||
v1PortGroup.Use()
|
v1PortGroup.Use()
|
||||||
@@ -86,7 +87,6 @@ func InitV1Router() *gin.Engine {
|
|||||||
v1PortGroup.GET("/", v1.GetPort) // app/port
|
v1PortGroup.GET("/", v1.GetPort) // app/port
|
||||||
v1PortGroup.GET("/state/:port", v1.PortCheck) // app/check/:port
|
v1PortGroup.GET("/state/:port", v1.PortCheck) // app/check/:port
|
||||||
}
|
}
|
||||||
|
|
||||||
v1FileGroup := v1Group.Group("/file")
|
v1FileGroup := v1Group.Group("/file")
|
||||||
v1FileGroup.Use()
|
v1FileGroup.Use()
|
||||||
{
|
{
|
||||||
@@ -173,6 +173,11 @@ func InitV1Router() *gin.Engine {
|
|||||||
v1OtherGroup.GET("/search", v1.GetSearchResult)
|
v1OtherGroup.GET("/search", v1.GetSearchResult)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
v1ZerotierGroup := v1Group.Group("/zt")
|
||||||
|
v1ZerotierGroup.Use()
|
||||||
|
{
|
||||||
|
v1ZerotierGroup.Any("/*url", v1.ZerotierProxy)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return r
|
return r
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ import (
|
|||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
"github.com/IceWhaleTech/CasaOS/drivers/dropbox"
|
"github.com/IceWhaleTech/CasaOS/drivers/dropbox"
|
||||||
"github.com/IceWhaleTech/CasaOS/drivers/google_drive"
|
"github.com/IceWhaleTech/CasaOS/drivers/google_drive"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/drivers/onedrive"
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
@@ -51,6 +52,10 @@ func ListStorages(c *gin.Context) {
|
|||||||
if dataMap["type"] == "dropbox" {
|
if dataMap["type"] == "dropbox" {
|
||||||
r.MountPoints[i].Icon = dropbox.ICONURL
|
r.MountPoints[i].Icon = dropbox.ICONURL
|
||||||
}
|
}
|
||||||
|
if dataMap["type"] == "onedrive" {
|
||||||
|
|
||||||
|
r.MountPoints[i].Icon = onedrive.ICONURL
|
||||||
|
}
|
||||||
r.MountPoints[i].Name = dataMap["username"]
|
r.MountPoints[i].Name = dataMap["username"]
|
||||||
}
|
}
|
||||||
list := []httper.MountPoint{}
|
list := []httper.MountPoint{}
|
||||||
|
|||||||
@@ -1,12 +1,34 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/common_err"
|
"github.com/IceWhaleTech/CasaOS-Common/utils/common_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/op"
|
"github.com/IceWhaleTech/CasaOS/drivers/dropbox"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/drivers/google_drive"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/drivers/onedrive"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
func ListDriverInfo(c *gin.Context) {
|
func ListDriverInfo(c *gin.Context) {
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: op.GetDriverInfoMap()})
|
list := []model.Drive{}
|
||||||
|
|
||||||
|
google := google_drive.GetConfig()
|
||||||
|
list = append(list, model.Drive{
|
||||||
|
Name: "Google Drive",
|
||||||
|
Icon: google.Icon,
|
||||||
|
AuthUrl: google.AuthUrl,
|
||||||
|
})
|
||||||
|
dp := dropbox.GetConfig()
|
||||||
|
list = append(list, model.Drive{
|
||||||
|
Name: "Dropbox",
|
||||||
|
Icon: dp.Icon,
|
||||||
|
AuthUrl: dp.AuthUrl,
|
||||||
|
})
|
||||||
|
od := onedrive.GetConfig()
|
||||||
|
list = append(list, model.Drive{
|
||||||
|
Name: "OneDrive",
|
||||||
|
Icon: od.Icon,
|
||||||
|
AuthUrl: od.AuthUrl,
|
||||||
|
})
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -480,6 +480,10 @@ func GetFileUpload(c *gin.Context) {
|
|||||||
path := c.Query("path")
|
path := c.Query("path")
|
||||||
dirPath := ""
|
dirPath := ""
|
||||||
hash := file.GetHashByContent([]byte(fileName))
|
hash := file.GetHashByContent([]byte(fileName))
|
||||||
|
if file.Exists(path + "/" + relative) {
|
||||||
|
c.JSON(http.StatusConflict, model.Result{Success: http.StatusConflict, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
|
tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
|
||||||
if fileName != relative {
|
if fileName != relative {
|
||||||
dirPath = strings.TrimSuffix(relative, fileName)
|
dirPath = strings.TrimSuffix(relative, fileName)
|
||||||
|
|||||||
@@ -8,6 +8,7 @@ import (
|
|||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
"github.com/IceWhaleTech/CasaOS/drivers/dropbox"
|
"github.com/IceWhaleTech/CasaOS/drivers/dropbox"
|
||||||
"github.com/IceWhaleTech/CasaOS/drivers/google_drive"
|
"github.com/IceWhaleTech/CasaOS/drivers/google_drive"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/drivers/onedrive"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
@@ -20,23 +21,17 @@ func GetRecoverStorage(c *gin.Context) {
|
|||||||
currentDate := time.Now().UTC().Format("2006-01-02")
|
currentDate := time.Now().UTC().Format("2006-01-02")
|
||||||
notify := make(map[string]interface{})
|
notify := make(map[string]interface{})
|
||||||
if t == "GoogleDrive" {
|
if t == "GoogleDrive" {
|
||||||
add := google_drive.Addition{}
|
google_drive := google_drive.GetConfig()
|
||||||
add.Code = c.Query("code")
|
google_drive.Code = c.Query("code")
|
||||||
if len(add.Code) == 0 {
|
if len(google_drive.Code) == 0 {
|
||||||
c.String(200, `<p>Code cannot be empty</p><script>window.close()</script>`)
|
c.String(200, `<p>Code cannot be empty</p><script>window.close()</script>`)
|
||||||
notify["status"] = "fail"
|
notify["status"] = "fail"
|
||||||
notify["message"] = "Code cannot be empty"
|
notify["message"] = "Code cannot be empty"
|
||||||
logger.Error("Then code is empty: ", zap.String("code", add.Code), zap.Any("name", "google_drive"))
|
logger.Error("Then code is empty: ", zap.String("code", google_drive.Code), zap.Any("name", "google_drive"))
|
||||||
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
add.RootFolderID = "root"
|
|
||||||
add.ClientID = google_drive.CLIENTID
|
|
||||||
add.ClientSecret = google_drive.CLIENTSECRET
|
|
||||||
|
|
||||||
var google_drive google_drive.GoogleDrive
|
|
||||||
google_drive.Addition = add
|
|
||||||
err := google_drive.Init(c)
|
err := google_drive.Init(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(200, `<p>Initialization failure:`+err.Error()+`</p><script>window.close()</script>`)
|
c.String(200, `<p>Initialization failure:`+err.Error()+`</p><script>window.close()</script>`)
|
||||||
@@ -93,8 +88,8 @@ func GetRecoverStorage(c *gin.Context) {
|
|||||||
//username = fileutil.NameAccumulation(username, "/mnt")
|
//username = fileutil.NameAccumulation(username, "/mnt")
|
||||||
username += "_google_drive_" + strconv.FormatInt(time.Now().Unix(), 10)
|
username += "_google_drive_" + strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
|
|
||||||
dmap["client_id"] = add.ClientID
|
dmap["client_id"] = google_drive.ClientID
|
||||||
dmap["client_secret"] = add.ClientSecret
|
dmap["client_secret"] = google_drive.ClientSecret
|
||||||
dmap["scope"] = "drive"
|
dmap["scope"] = "drive"
|
||||||
dmap["mount_point"] = "/mnt/" + username
|
dmap["mount_point"] = "/mnt/" + username
|
||||||
dmap["token"] = `{"access_token":"` + google_drive.AccessToken + `","token_type":"Bearer","refresh_token":"` + google_drive.RefreshToken + `","expiry":"` + currentDate + `T` + currentTime.Add(time.Hour*1).Add(time.Minute*50).Format("15:04:05") + `Z"}`
|
dmap["token"] = `{"access_token":"` + google_drive.AccessToken + `","token_type":"Bearer","refresh_token":"` + google_drive.RefreshToken + `","expiry":"` + currentDate + `T` + currentTime.Add(time.Hour*1).Add(time.Minute*50).Format("15:04:05") + `Z"}`
|
||||||
@@ -106,21 +101,17 @@ func GetRecoverStorage(c *gin.Context) {
|
|||||||
notify["driver"] = "GoogleDrive"
|
notify["driver"] = "GoogleDrive"
|
||||||
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
} else if t == "Dropbox" {
|
} else if t == "Dropbox" {
|
||||||
add := dropbox.Addition{}
|
dropbox := dropbox.GetConfig()
|
||||||
add.Code = c.Query("code")
|
dropbox.Code = c.Query("code")
|
||||||
if len(add.Code) == 0 {
|
if len(dropbox.Code) == 0 {
|
||||||
c.String(200, `<p>Code cannot be empty</p><script>window.close()</script>`)
|
c.String(200, `<p>Code cannot be empty</p><script>window.close()</script>`)
|
||||||
notify["status"] = "fail"
|
notify["status"] = "fail"
|
||||||
notify["message"] = "Code cannot be empty"
|
notify["message"] = "Code cannot be empty"
|
||||||
logger.Error("Then code is empty error: ", zap.String("code", add.Code), zap.Any("name", "dropbox"))
|
logger.Error("Then code is empty error: ", zap.String("code", dropbox.Code), zap.Any("name", "dropbox"))
|
||||||
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
add.RootFolderID = ""
|
|
||||||
add.AppKey = dropbox.APPKEY
|
|
||||||
add.AppSecret = dropbox.APPSECRET
|
|
||||||
var dropbox dropbox.Dropbox
|
|
||||||
dropbox.Addition = add
|
|
||||||
err := dropbox.Init(c)
|
err := dropbox.Init(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.String(200, `<p>Initialization failure:`+err.Error()+`</p><script>window.close()</script>`)
|
c.String(200, `<p>Initialization failure:`+err.Error()+`</p><script>window.close()</script>`)
|
||||||
@@ -176,8 +167,8 @@ func GetRecoverStorage(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
username += "_dropbox_" + strconv.FormatInt(time.Now().Unix(), 10)
|
username += "_dropbox_" + strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
|
|
||||||
dmap["client_id"] = add.AppKey
|
dmap["client_id"] = dropbox.AppKey
|
||||||
dmap["client_secret"] = add.AppSecret
|
dmap["client_secret"] = dropbox.AppSecret
|
||||||
dmap["token"] = `{"access_token":"` + dropbox.AccessToken + `","token_type":"bearer","refresh_token":"` + dropbox.Addition.RefreshToken + `","expiry":"` + currentDate + `T` + currentTime.Add(time.Hour*3).Add(time.Minute*50).Format("15:04:05") + `.780385354Z"}`
|
dmap["token"] = `{"access_token":"` + dropbox.AccessToken + `","token_type":"bearer","refresh_token":"` + dropbox.Addition.RefreshToken + `","expiry":"` + currentDate + `T` + currentTime.Add(time.Hour*3).Add(time.Minute*50).Format("15:04:05") + `.780385354Z"}`
|
||||||
dmap["mount_point"] = "/mnt/" + username
|
dmap["mount_point"] = "/mnt/" + username
|
||||||
// data.SetValue(username, "type", "dropbox")
|
// data.SetValue(username, "type", "dropbox")
|
||||||
@@ -199,6 +190,98 @@ func GetRecoverStorage(c *gin.Context) {
|
|||||||
notify["message"] = "Success"
|
notify["message"] = "Success"
|
||||||
notify["driver"] = "Dropbox"
|
notify["driver"] = "Dropbox"
|
||||||
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
|
} else if t == "Onedrive" {
|
||||||
|
onedrive := onedrive.GetConfig()
|
||||||
|
onedrive.Code = c.Query("code")
|
||||||
|
if len(onedrive.Code) == 0 {
|
||||||
|
c.String(200, `<p>Code cannot be empty</p><script>window.close()</script>`)
|
||||||
|
notify["status"] = "fail"
|
||||||
|
notify["message"] = "Code cannot be empty"
|
||||||
|
logger.Error("Then code is empty error: ", zap.String("code", onedrive.Code), zap.Any("name", "onedrive"))
|
||||||
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
err := onedrive.Init(c)
|
||||||
|
if err != nil {
|
||||||
|
c.String(200, `<p>Initialization failure:`+err.Error()+`</p><script>window.close()</script>`)
|
||||||
|
notify["status"] = "fail"
|
||||||
|
notify["message"] = "Initialization failure"
|
||||||
|
logger.Error("Then init error: ", zap.Error(err), zap.Any("name", "onedrive"))
|
||||||
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
username, driveId, driveType, err := onedrive.GetInfo(c)
|
||||||
|
if err != nil {
|
||||||
|
c.String(200, `<p>Failed to get user information:`+err.Error()+`</p><script>window.close()</script>`)
|
||||||
|
notify["status"] = "fail"
|
||||||
|
notify["message"] = "Failed to get user information"
|
||||||
|
logger.Error("Then get user information: ", zap.Error(err), zap.Any("name", "onedrive"))
|
||||||
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
dmap := make(map[string]string)
|
||||||
|
dmap["username"] = username
|
||||||
|
|
||||||
|
configs, err := service.MyService.Storage().GetConfig()
|
||||||
|
if err != nil {
|
||||||
|
c.String(200, `<p>Failed to get rclone config:`+err.Error()+`</p><script>window.close()</script>`)
|
||||||
|
notify["status"] = "fail"
|
||||||
|
notify["message"] = "Failed to get rclone config"
|
||||||
|
logger.Error("Then get config error: ", zap.Error(err), zap.Any("name", "onedrive"))
|
||||||
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
for _, v := range configs.Remotes {
|
||||||
|
cf, err := service.MyService.Storage().GetConfigByName(v)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("then get config by name error: ", zap.Error(err), zap.Any("name", v))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
if cf["type"] == "onedrive" && cf["username"] == dmap["username"] {
|
||||||
|
c.String(200, `<p>The same configuration has been added</p><script>window.close()</script>`)
|
||||||
|
err := service.MyService.Storage().CheckAndMountByName(v)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("check and mount by name error: ", zap.Error(err), zap.Any("name", cf["username"]))
|
||||||
|
}
|
||||||
|
|
||||||
|
notify["status"] = "warn"
|
||||||
|
notify["message"] = "The same configuration has been added"
|
||||||
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if len(username) > 0 {
|
||||||
|
a := strings.Split(username, "@")
|
||||||
|
username = a[0]
|
||||||
|
}
|
||||||
|
username += "_onedrive_" + strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
|
|
||||||
|
dmap["client_id"] = onedrive.ClientID
|
||||||
|
dmap["client_secret"] = onedrive.ClientSecret
|
||||||
|
dmap["token"] = `{"access_token":"` + onedrive.AccessToken + `","token_type":"bearer","refresh_token":"` + onedrive.RefreshToken + `","expiry":"` + currentDate + `T` + currentTime.Add(time.Hour*3).Add(time.Minute*50).Format("15:04:05") + `.780385354Z"}`
|
||||||
|
dmap["mount_point"] = "/mnt/" + username
|
||||||
|
dmap["drive_id"] = driveId
|
||||||
|
dmap["drive_type"] = driveType
|
||||||
|
// data.SetValue(username, "type", "dropbox")
|
||||||
|
// data.SetValue(username, "client_id", add.AppKey)
|
||||||
|
// data.SetValue(username, "client_secret", add.AppSecret)
|
||||||
|
// data.SetValue(username, "mount_point", "/mnt/"+username)
|
||||||
|
|
||||||
|
// data.SetValue(username, "token", `{"access_token":"`+dropbox.AccessToken+`","token_type":"bearer","refresh_token":"`+dropbox.Addition.RefreshToken+`","expiry":"`+currentDate+`T`+currentTime.Add(time.Hour*3).Format("15:04:05")+`.780385354Z"}`)
|
||||||
|
// e = data.Save()
|
||||||
|
// if e != nil {
|
||||||
|
// c.String(200, `<p>保存配置失败:`+e.Error()+`</p>`)
|
||||||
|
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
service.MyService.Storage().CreateConfig(dmap, username, "onedrive")
|
||||||
|
service.MyService.Storage().MountStorage("/mnt/"+username, username+":")
|
||||||
|
|
||||||
|
notify["status"] = "success"
|
||||||
|
notify["message"] = "Success"
|
||||||
|
notify["driver"] = "Onedrive"
|
||||||
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
}
|
}
|
||||||
|
|
||||||
c.String(200, `<p>Just close the page</p><script>window.close()</script>`)
|
c.String(200, `<p>Just close the page</p><script>window.close()</script>`)
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package v1
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bytes"
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -24,6 +25,7 @@ import (
|
|||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/types"
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary check version
|
// @Summary check version
|
||||||
@@ -371,3 +373,13 @@ func PortCheck(c *gin.Context) {
|
|||||||
t := c.DefaultQuery("type", "tcp")
|
t := c.DefaultQuery("type", "tcp")
|
||||||
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port.IsPortAvailable(p, t)})
|
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port.IsPortAvailable(p, t)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSystemEntry(c *gin.Context) {
|
||||||
|
entry := service.MyService.System().GetSystemEntry()
|
||||||
|
str := json.RawMessage(entry)
|
||||||
|
if !gjson.ValidBytes(str) {
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: entry, Data: json.RawMessage("[]")})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: str})
|
||||||
|
}
|
||||||
|
|||||||
313
route/v1/zerotier.go
Normal file
313
route/v1/zerotier.go
Normal file
@@ -0,0 +1,313 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"io/ioutil"
|
||||||
|
"math/rand"
|
||||||
|
"net"
|
||||||
|
"net/http"
|
||||||
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/common"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ZerotierProxy(c *gin.Context) {
|
||||||
|
// Read the port number from the file
|
||||||
|
w := c.Writer
|
||||||
|
r := c.Request
|
||||||
|
port, err := ioutil.ReadFile("/var/lib/zerotier-one/zerotier-one.port")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the request path and remove "/zt"
|
||||||
|
path := strings.TrimPrefix(r.URL.Path, "/v1/zt")
|
||||||
|
fmt.Println(path)
|
||||||
|
|
||||||
|
// Build the target URL
|
||||||
|
targetURL := fmt.Sprintf("http://localhost:%s%s", strings.TrimSpace(string(port)), path)
|
||||||
|
|
||||||
|
// Create a new request
|
||||||
|
req, err := http.NewRequest(r.Method, targetURL, r.Body)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Add the X-ZT1-AUTH header
|
||||||
|
authToken, err := ioutil.ReadFile("/var/lib/zerotier-one/authtoken.secret")
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
req.Header.Set("X-ZT1-AUTH", strings.TrimSpace(string(authToken)))
|
||||||
|
|
||||||
|
copyHeaders(req.Header, r.Header)
|
||||||
|
|
||||||
|
client := http.Client{}
|
||||||
|
resp, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
|
||||||
|
copyHeaders(w.Header(), resp.Header)
|
||||||
|
|
||||||
|
respBody, err := ioutil.ReadAll(resp.Body)
|
||||||
|
if err != nil {
|
||||||
|
http.Error(w, err.Error(), http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// Return the response to the client
|
||||||
|
w.WriteHeader(resp.StatusCode)
|
||||||
|
w.Write(respBody)
|
||||||
|
}
|
||||||
|
|
||||||
|
func copyHeaders(destination, source http.Header) {
|
||||||
|
for key, values := range source {
|
||||||
|
for _, value := range values {
|
||||||
|
destination.Add(key, value)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func CheckNetwork() {
|
||||||
|
logger.Info("start check network")
|
||||||
|
respBody, err := httper.ZTGet("/controller/network")
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("get network error", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
networkId := ""
|
||||||
|
address := ""
|
||||||
|
networkNames := gjson.ParseBytes(respBody).Array()
|
||||||
|
routers := ""
|
||||||
|
for _, v := range networkNames {
|
||||||
|
res, err := httper.ZTGet("/controller/network/" + v.Str)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("get network error", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
name := gjson.GetBytes(res, "name").Str
|
||||||
|
if name == common.RANW_NAME {
|
||||||
|
networkId = gjson.GetBytes(res, "id").Str
|
||||||
|
routers = gjson.GetBytes(res, "routes.0.target").Str
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ip, s, e, c := getZTIP(routers)
|
||||||
|
logger.Info("ip", zap.Any("ip", ip))
|
||||||
|
if len(networkId) == 0 {
|
||||||
|
if len(address) == 0 {
|
||||||
|
address = GetAddress()
|
||||||
|
}
|
||||||
|
networkId = CreateNet(address, s, e, c)
|
||||||
|
}
|
||||||
|
res, err := httper.ZTGet("/network")
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("get network error", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
joined := false
|
||||||
|
networks := gjson.GetBytes(res, "#.id").Array()
|
||||||
|
for _, v := range networks {
|
||||||
|
if v.Str == networkId {
|
||||||
|
joined = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
logger.Info("joined", zap.Any("joined", joined))
|
||||||
|
if !joined {
|
||||||
|
JoinAndUpdateNet(address, networkId, ip)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func GetAddress() string {
|
||||||
|
nodeRes, err := httper.ZTGet("/status")
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("get status error", zap.Error(err))
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return gjson.GetBytes(nodeRes, "address").String()
|
||||||
|
}
|
||||||
|
func JoinAndUpdateNet(address, networkId, ip string) {
|
||||||
|
logger.Info("start join network", zap.Any("ip", ip))
|
||||||
|
_, err := httper.ZTPost("/network/"+networkId, "")
|
||||||
|
if err != nil {
|
||||||
|
logger.Error(" get network error", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(address) == 0 {
|
||||||
|
address = GetAddress()
|
||||||
|
}
|
||||||
|
b := `{
|
||||||
|
"authorized": true,
|
||||||
|
"activeBridge": true,
|
||||||
|
"ipAssignments": [
|
||||||
|
"` + ip + `"
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
_, err = httper.ZTPost("/controller/network/"+networkId+"/member/"+address, b)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("join network error", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func CreateNet(address, s, e, c string) string {
|
||||||
|
body := `{
|
||||||
|
"name": "` + common.RANW_NAME + `",
|
||||||
|
"private": false,
|
||||||
|
"v4AssignMode": {
|
||||||
|
"zt": true
|
||||||
|
},
|
||||||
|
"ipAssignmentPools": [
|
||||||
|
{
|
||||||
|
"ipRangeStart": "` + s + `",
|
||||||
|
"ipRangeEnd": "` + e + `"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"target": "` + c + `"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"etherType": 2048,
|
||||||
|
"not": true,
|
||||||
|
"or": false,
|
||||||
|
"type": "MATCH_ETHERTYPE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"etherType": 2054,
|
||||||
|
"not": true,
|
||||||
|
"or": false,
|
||||||
|
"type": "MATCH_ETHERTYPE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"etherType": 34525,
|
||||||
|
"not": true,
|
||||||
|
"or": false,
|
||||||
|
"type": "MATCH_ETHERTYPE"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ACTION_DROP"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "ACTION_ACCEPT"
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"v6AssignMode": {
|
||||||
|
"rfc4193": true
|
||||||
|
}
|
||||||
|
}`
|
||||||
|
createRes, err := httper.ZTPost("/controller/network/"+address+"______", body)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("post network error", zap.Error(err))
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return gjson.GetBytes(createRes, "id").Str
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetZTIPs() []gjson.Result {
|
||||||
|
res, err := httper.ZTGet("/network")
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("get network error", zap.Error(err))
|
||||||
|
return []gjson.Result{}
|
||||||
|
}
|
||||||
|
a := gjson.GetBytes(res, "#.routes.0.target")
|
||||||
|
return a.Array()
|
||||||
|
}
|
||||||
|
|
||||||
|
func getZTIP(routes string) (ip, start, end, cidr string) {
|
||||||
|
excluded := GetZTIPs()
|
||||||
|
cidrs := []string{
|
||||||
|
"10.147.11.0/24",
|
||||||
|
"10.147.12.0/24",
|
||||||
|
"10.147.13.0/24",
|
||||||
|
"10.147.14.0/24",
|
||||||
|
"10.147.15.0/24",
|
||||||
|
"10.147.16.0/24",
|
||||||
|
"10.147.17.0/24",
|
||||||
|
"10.147.18.0/24",
|
||||||
|
"10.147.19.0/24",
|
||||||
|
"10.147.20.0/24",
|
||||||
|
"10.240.0.0/16",
|
||||||
|
"10.241.0.0/16",
|
||||||
|
"10.242.0.0/16",
|
||||||
|
"10.243.0.0/16",
|
||||||
|
"10.244.0.0/16",
|
||||||
|
"10.245.0.0/16",
|
||||||
|
"10.246.0.0/16",
|
||||||
|
"10.247.0.0/16",
|
||||||
|
"10.248.0.0/16",
|
||||||
|
"10.249.0.0/16",
|
||||||
|
"172.21.0.0/16",
|
||||||
|
"172.22.0.0/16",
|
||||||
|
"172.23.0.0/16",
|
||||||
|
"172.24.0.0/16",
|
||||||
|
"172.25.0.0/16",
|
||||||
|
"172.26.0.0/16",
|
||||||
|
"172.27.0.0/16",
|
||||||
|
"172.28.0.0/16",
|
||||||
|
"172.29.0.0/16",
|
||||||
|
"172.30.0.0/16",
|
||||||
|
}
|
||||||
|
filteredCidrs := make([]string, 0)
|
||||||
|
if len(routes) > 0 {
|
||||||
|
filteredCidrs = append(filteredCidrs, routes)
|
||||||
|
} else {
|
||||||
|
for _, cidr := range cidrs {
|
||||||
|
isExcluded := false
|
||||||
|
for _, excludedIP := range excluded {
|
||||||
|
if cidr == excludedIP.Str {
|
||||||
|
isExcluded = true
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if !isExcluded {
|
||||||
|
filteredCidrs = append(filteredCidrs, cidr)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
rnd := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||||
|
ip = ""
|
||||||
|
if len(filteredCidrs) > 0 {
|
||||||
|
randomIndex := rnd.Intn(len(filteredCidrs))
|
||||||
|
selectedCIDR := filteredCidrs[randomIndex]
|
||||||
|
_, ipNet, err := net.ParseCIDR(selectedCIDR)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("ParseCIDR error", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
cidr = selectedCIDR
|
||||||
|
startIP := ipNet.IP
|
||||||
|
endIP := make(net.IP, len(startIP))
|
||||||
|
copy(endIP, startIP)
|
||||||
|
|
||||||
|
for i := range startIP {
|
||||||
|
endIP[i] |= ^ipNet.Mask[i]
|
||||||
|
}
|
||||||
|
startIP[3] = 1
|
||||||
|
start = startIP.String()
|
||||||
|
endIP[3] = 254
|
||||||
|
end = endIP.String()
|
||||||
|
ipt := ipNet
|
||||||
|
ipt.IP[3] = 1
|
||||||
|
ip = ipt.IP.String()
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
logger.Error("No available CIDR found")
|
||||||
|
}
|
||||||
|
return
|
||||||
|
}
|
||||||
41
route/v2.go
41
route/v2.go
@@ -30,7 +30,6 @@ var (
|
|||||||
V2APIPath string
|
V2APIPath string
|
||||||
V2DocPath string
|
V2DocPath string
|
||||||
V3FilePath string
|
V3FilePath string
|
||||||
V4DirPath string
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
@@ -49,7 +48,6 @@ func init() {
|
|||||||
V2APIPath = strings.TrimRight(u.Path, "/")
|
V2APIPath = strings.TrimRight(u.Path, "/")
|
||||||
V2DocPath = "/doc" + V2APIPath
|
V2DocPath = "/doc" + V2APIPath
|
||||||
V3FilePath = "/v3/file"
|
V3FilePath = "/v3/file"
|
||||||
V4DirPath = "/v4/dir"
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitV2Router() http.Handler {
|
func InitV2Router() http.Handler {
|
||||||
@@ -74,12 +72,9 @@ func InitV2Router() http.Handler {
|
|||||||
Skipper: func(c echo.Context) bool {
|
Skipper: func(c echo.Context) bool {
|
||||||
return c.RealIP() == "::1" || c.RealIP() == "127.0.0.1"
|
return c.RealIP() == "::1" || c.RealIP() == "127.0.0.1"
|
||||||
//return true
|
//return true
|
||||||
|
|
||||||
},
|
},
|
||||||
ParseTokenFunc: func(token string, c echo.Context) (interface{}, error) {
|
ParseTokenFunc: func(token string, c echo.Context) (interface{}, error) {
|
||||||
// claims, code := jwt.Validate(token) // TODO - needs JWT validation
|
|
||||||
// if code != common_err.SUCCESS {
|
|
||||||
// return nil, echo.ErrUnauthorized
|
|
||||||
// }
|
|
||||||
valid, claims, err := jwt.Validate(token, func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) })
|
valid, claims, err := jwt.Validate(token, func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) })
|
||||||
if err != nil || !valid {
|
if err != nil || !valid {
|
||||||
return nil, echo.ErrUnauthorized
|
return nil, echo.ErrUnauthorized
|
||||||
@@ -90,7 +85,10 @@ func InitV2Router() http.Handler {
|
|||||||
},
|
},
|
||||||
TokenLookupFuncs: []echo_middleware.ValuesExtractor{
|
TokenLookupFuncs: []echo_middleware.ValuesExtractor{
|
||||||
func(c echo.Context) ([]string, error) {
|
func(c echo.Context) ([]string, error) {
|
||||||
|
if len(c.Request().Header.Get(echo.HeaderAuthorization)) > 0 {
|
||||||
return []string{c.Request().Header.Get(echo.HeaderAuthorization)}, nil
|
return []string{c.Request().Header.Get(echo.HeaderAuthorization)}, nil
|
||||||
|
}
|
||||||
|
return []string{c.QueryParam("token")}, nil
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
}))
|
}))
|
||||||
@@ -145,15 +143,46 @@ func InitV2DocRouter(docHTML string, docYAML string) http.Handler {
|
|||||||
|
|
||||||
func InitFile() http.Handler {
|
func InitFile() http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
token := r.URL.Query().Get("token")
|
||||||
|
if len(token) == 0 {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
w.Write([]byte(`{"message": "token not found"}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
valid, _, errs := jwt.Validate(token, func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) })
|
||||||
|
if errs != nil || !valid {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
w.Write([]byte(`{"message": "validation failure"}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
filePath := r.URL.Query().Get("path")
|
filePath := r.URL.Query().Get("path")
|
||||||
fileName := path.Base(filePath)
|
fileName := path.Base(filePath)
|
||||||
w.Header().Add("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(fileName))
|
w.Header().Add("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(fileName))
|
||||||
http.ServeFile(w, r, filePath)
|
http.ServeFile(w, r, filePath)
|
||||||
|
//http.ServeFile(w, r, filePath)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
func InitDir() http.Handler {
|
func InitDir() http.Handler {
|
||||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
token := r.URL.Query().Get("token")
|
||||||
|
if len(token) == 0 {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
w.Write([]byte(`{"message": "token not found"}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
valid, _, errs := jwt.Validate(token, func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) })
|
||||||
|
if errs != nil || !valid {
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
w.WriteHeader(http.StatusUnauthorized)
|
||||||
|
w.Write([]byte(`{"message": "validation failure"}`))
|
||||||
|
return
|
||||||
|
}
|
||||||
t := r.URL.Query().Get("format")
|
t := r.URL.Query().Get("format")
|
||||||
files := r.URL.Query().Get("files")
|
files := r.URL.Query().Get("files")
|
||||||
|
|
||||||
|
|||||||
@@ -2,10 +2,15 @@ package v2
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/url"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/codegen"
|
"github.com/IceWhaleTech/CasaOS/codegen"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/labstack/echo/v4"
|
"github.com/labstack/echo/v4"
|
||||||
|
"github.com/mholt/archiver/v3"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (s *CasaOS) GetHealthServices(ctx echo.Context) error {
|
func (s *CasaOS) GetHealthServices(ctx echo.Context) error {
|
||||||
@@ -41,3 +46,55 @@ func (s *CasaOS) GetHealthPorts(ctx echo.Context) error {
|
|||||||
},
|
},
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
func (c *CasaOS) GetHealthlogs(ctx echo.Context) error {
|
||||||
|
var name, currentPath, commonDir, extension string
|
||||||
|
var err error
|
||||||
|
var ar archiver.Writer
|
||||||
|
fileList, err := os.ReadDir("/var/log/casaos")
|
||||||
|
if err != nil {
|
||||||
|
message := err.Error()
|
||||||
|
return ctx.JSON(http.StatusInternalServerError, codegen.ResponseInternalServerError{
|
||||||
|
Message: &message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
extension, ar, err = file.GetCompressionAlgorithm("zip")
|
||||||
|
if err != nil {
|
||||||
|
ctx.Response().Header().Set("Content-Type", "application/json")
|
||||||
|
message := err.Error()
|
||||||
|
return ctx.JSON(http.StatusNotFound, codegen.ResponseInternalServerError{
|
||||||
|
Message: &message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
err = ar.Create(ctx.Response().Writer)
|
||||||
|
if err != nil {
|
||||||
|
ctx.Response().Header().Set("Content-Type", "application/json")
|
||||||
|
message := err.Error()
|
||||||
|
return ctx.JSON(http.StatusNotFound, codegen.ResponseInternalServerError{
|
||||||
|
Message: &message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
defer ar.Close()
|
||||||
|
|
||||||
|
commonDir = "/var/log/casaos"
|
||||||
|
|
||||||
|
currentPath = filepath.Base(commonDir)
|
||||||
|
|
||||||
|
name = currentPath
|
||||||
|
name += extension
|
||||||
|
ctx.Response().Header().Add("Content-Type", "application/octet-stream")
|
||||||
|
ctx.Response().Header().Add("Content-Transfer-Encoding", "binary")
|
||||||
|
ctx.Response().Header().Add("Cache-Control", "no-cache")
|
||||||
|
ctx.Response().Header().Add("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name))
|
||||||
|
|
||||||
|
for _, fname := range fileList {
|
||||||
|
err := file.AddFile(ar, filepath.Join("/var/log/casaos", fname.Name()), commonDir)
|
||||||
|
if err != nil {
|
||||||
|
message := err.Error()
|
||||||
|
return ctx.JSON(http.StatusInternalServerError, codegen.ResponseInternalServerError{
|
||||||
|
Message: &message,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
74
route/v2/zerotier.go
Normal file
74
route/v2/zerotier.go
Normal file
@@ -0,0 +1,74 @@
|
|||||||
|
package v2
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/codegen"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/common"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
|
"github.com/labstack/echo/v4"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (s *CasaOS) SetZerotierNetworkStatus(ctx echo.Context, networkId string) error {
|
||||||
|
ip := `,"via":"10.147.19.0"`
|
||||||
|
m := make(map[string]string)
|
||||||
|
ctx.Bind(&m)
|
||||||
|
status := m["status"]
|
||||||
|
if status == "online" {
|
||||||
|
ip = ``
|
||||||
|
}
|
||||||
|
body := `{
|
||||||
|
"routes": [
|
||||||
|
{
|
||||||
|
"target": "10.147.20.0/24"` + ip + `
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}`
|
||||||
|
res, err := httper.ZTPost("/controller/network/"+networkId, body)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return ctx.JSON(http.StatusInternalServerError, codegen.BaseResponse{Message: utils.Ptr(err.Error())})
|
||||||
|
}
|
||||||
|
info := codegen.GetZTInfoOK{}
|
||||||
|
via := gjson.GetBytes(res, "routes.0.via").Str
|
||||||
|
info.Id = utils.Ptr(gjson.GetBytes(res, "id").Str)
|
||||||
|
info.Name = utils.Ptr(gjson.GetBytes(res, "name").Str)
|
||||||
|
if len(via) == 0 {
|
||||||
|
info.Status = utils.Ptr("online")
|
||||||
|
} else {
|
||||||
|
info.Status = utils.Ptr("offline")
|
||||||
|
}
|
||||||
|
return ctx.JSON(http.StatusOK, info)
|
||||||
|
}
|
||||||
|
func (s *CasaOS) GetZerotierInfo(ctx echo.Context) error {
|
||||||
|
info := codegen.GetZTInfoOK{}
|
||||||
|
respBody, err := httper.ZTGet("/controller/network")
|
||||||
|
if err != nil {
|
||||||
|
return ctx.JSON(http.StatusInternalServerError, codegen.BaseResponse{Message: utils.Ptr(err.Error())})
|
||||||
|
}
|
||||||
|
|
||||||
|
networkNames := gjson.ParseBytes(respBody).Array()
|
||||||
|
for _, v := range networkNames {
|
||||||
|
res, err := httper.ZTGet("/controller/network/" + v.Str)
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
return ctx.JSON(http.StatusInternalServerError, codegen.BaseResponse{Message: utils.Ptr(err.Error())})
|
||||||
|
}
|
||||||
|
name := gjson.GetBytes(res, "name").Str
|
||||||
|
if name == common.RANW_NAME {
|
||||||
|
via := gjson.GetBytes(res, "routes.0.via").Str
|
||||||
|
info.Id = utils.Ptr(gjson.GetBytes(res, "id").Str)
|
||||||
|
info.Name = &name
|
||||||
|
if len(via) == 0 {
|
||||||
|
info.Status = utils.Ptr("online")
|
||||||
|
} else {
|
||||||
|
info.Status = utils.Ptr("offline")
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ctx.JSON(http.StatusOK, info)
|
||||||
|
}
|
||||||
@@ -102,7 +102,9 @@ func FileOperate(k string) {
|
|||||||
os.RemoveAll(temp.To + "/" + lastPath)
|
os.RemoveAll(temp.To + "/" + lastPath)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
err := os.Rename(v.From, temp.To+"/"+lastPath)
|
err := file.CopyDir(v.From, temp.To, temp.Style)
|
||||||
|
if err == nil {
|
||||||
|
err = os.RemoveAll(v.From)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("file move error", zap.Any("err", err))
|
logger.Error("file move error", zap.Any("err", err))
|
||||||
err = file.MoveFile(v.From, temp.To+"/"+lastPath)
|
err = file.MoveFile(v.From, temp.To+"/"+lastPath)
|
||||||
@@ -112,6 +114,8 @@ func FileOperate(k string) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} else if temp.Type == "copy" {
|
} else if temp.Type == "copy" {
|
||||||
err := file.CopyDir(v.From, temp.To, temp.Style)
|
err := file.CopyDir(v.From, temp.To, temp.Style)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/json"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -15,10 +16,14 @@ import (
|
|||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/file"
|
"github.com/IceWhaleTech/CasaOS-Common/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/common"
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"github.com/shirou/gopsutil/v3/cpu"
|
"github.com/shirou/gopsutil/v3/cpu"
|
||||||
@@ -49,6 +54,7 @@ type SystemService interface {
|
|||||||
GetDiskInfo() *disk.UsageStat
|
GetDiskInfo() *disk.UsageStat
|
||||||
GetSysInfo() host.InfoStat
|
GetSysInfo() host.InfoStat
|
||||||
GetDeviceTree() string
|
GetDeviceTree() string
|
||||||
|
GetDeviceInfo() model.DeviceInfo
|
||||||
CreateFile(path string) (int, error)
|
CreateFile(path string) (int, error)
|
||||||
RenameFile(oldF, newF string) (int, error)
|
RenameFile(oldF, newF string) (int, error)
|
||||||
MkdirAll(path string) (int, error)
|
MkdirAll(path string) (int, error)
|
||||||
@@ -57,9 +63,117 @@ type SystemService interface {
|
|||||||
GetMacAddress() (string, error)
|
GetMacAddress() (string, error)
|
||||||
SystemReboot() error
|
SystemReboot() error
|
||||||
SystemShutdown() error
|
SystemShutdown() error
|
||||||
|
GetSystemEntry() string
|
||||||
|
GenreateSystemEntry()
|
||||||
}
|
}
|
||||||
type systemService struct{}
|
type systemService struct{}
|
||||||
|
|
||||||
|
func (c *systemService) GetDeviceInfo() model.DeviceInfo {
|
||||||
|
m := model.DeviceInfo{}
|
||||||
|
m.OS_Version = common.VERSION
|
||||||
|
err, portStr := MyService.Gateway().GetPort()
|
||||||
|
if err != nil {
|
||||||
|
m.Port = 80
|
||||||
|
} else {
|
||||||
|
port := gjson.Get(portStr, "data")
|
||||||
|
if len(port.Raw) == 0 {
|
||||||
|
m.Port = 80
|
||||||
|
} else {
|
||||||
|
p, err := strconv.Atoi(port.Raw)
|
||||||
|
if err != nil {
|
||||||
|
m.Port = 80
|
||||||
|
} else {
|
||||||
|
m.Port = p
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
allIpv4 := ip_helper.GetDeviceAllIPv4()
|
||||||
|
ip := []string{}
|
||||||
|
nets := MyService.System().GetNet(true)
|
||||||
|
for _, n := range nets {
|
||||||
|
if v, ok := allIpv4[n]; ok {
|
||||||
|
{
|
||||||
|
ip = append(ip, v)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
m.LanIpv4 = ip
|
||||||
|
h, err := host.Info() /* */
|
||||||
|
if err == nil {
|
||||||
|
m.DeviceName = h.Hostname
|
||||||
|
}
|
||||||
|
mb := model.BaseInfo{}
|
||||||
|
|
||||||
|
err = json.Unmarshal(file.ReadFullFile(config.AppInfo.DBPath+"/baseinfo.conf"), &mb)
|
||||||
|
if err == nil {
|
||||||
|
m.Hash = mb.Hash
|
||||||
|
}
|
||||||
|
|
||||||
|
osRelease, _ := file.ReadOSRelease()
|
||||||
|
m.DeviceModel = osRelease["MODEL"]
|
||||||
|
m.DeviceSN = osRelease["SN"]
|
||||||
|
res := httper.Get("http://127.0.0.1:"+strconv.Itoa(m.Port)+"/v1/users/status", nil)
|
||||||
|
init := gjson.Get(res, "data.initialized")
|
||||||
|
m.Initialized, _ = strconv.ParseBool(init.Raw)
|
||||||
|
|
||||||
|
return m
|
||||||
|
}
|
||||||
|
func (c *systemService) GenreateSystemEntry() {
|
||||||
|
modelsPath := "/var/lib/casaos/www/modules"
|
||||||
|
entryFileName := "entry.json"
|
||||||
|
entryFilePath := filepath.Join(config.AppInfo.DBPath, "db", entryFileName)
|
||||||
|
file.IsNotExistCreateFile(entryFilePath)
|
||||||
|
|
||||||
|
dir, err := os.ReadDir(modelsPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("read dir error", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
json := "["
|
||||||
|
for _, v := range dir {
|
||||||
|
data, err := os.ReadFile(filepath.Join(modelsPath, v.Name(), entryFileName))
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("read entry file error", zap.Error(err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
json += string(data) + ","
|
||||||
|
}
|
||||||
|
json = strings.TrimRight(json, ",")
|
||||||
|
json += "]"
|
||||||
|
err = os.WriteFile(entryFilePath, []byte(json), 0666)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("write entry file error", zap.Error(err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
func (c *systemService) GetSystemEntry() string {
|
||||||
|
|
||||||
|
modelsPath := "/var/lib/casaos/www/modules"
|
||||||
|
entryFileName := "entry.json"
|
||||||
|
dir, err := os.ReadDir(modelsPath)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("read dir error", zap.Error(err))
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
json := "["
|
||||||
|
for _, v := range dir {
|
||||||
|
data, err := os.ReadFile(filepath.Join(modelsPath, v.Name(), entryFileName))
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("read entry file error", zap.Error(err))
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
json += string(data) + ","
|
||||||
|
}
|
||||||
|
json = strings.TrimRight(json, ",")
|
||||||
|
json += "]"
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("write entry file error", zap.Error(err))
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
return json
|
||||||
|
}
|
||||||
func (c *systemService) GetMacAddress() (string, error) {
|
func (c *systemService) GetMacAddress() (string, error) {
|
||||||
interfaces, err := net.Interfaces()
|
interfaces, err := net.Interfaces()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -359,6 +473,7 @@ func GetCPUThermalZone() string {
|
|||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Cache.SetDefault(keyName, path)
|
Cache.SetDefault(keyName, path)
|
||||||
return path
|
return path
|
||||||
}
|
}
|
||||||
@@ -369,8 +484,11 @@ func (s *systemService) GetCPUTemperature() int {
|
|||||||
if len(path) > 0 {
|
if len(path) > 0 {
|
||||||
outPut = string(file.ReadFullFile(path + "/temp"))
|
outPut = string(file.ReadFullFile(path + "/temp"))
|
||||||
} else {
|
} else {
|
||||||
|
outPut = string(file.ReadFullFile("/sys/class/hwmon/hwmon0/temp1_input"))
|
||||||
|
if len(outPut) == 0 {
|
||||||
outPut = "0"
|
outPut = "0"
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
celsius, _ := strconv.Atoi(strings.TrimSpace(outPut))
|
celsius, _ := strconv.Atoi(strings.TrimSpace(outPut))
|
||||||
|
|
||||||
|
|||||||
25
tsconfig.json
Normal file
25
tsconfig.json
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
{
|
||||||
|
"compilerOptions": {
|
||||||
|
"declaration": true,
|
||||||
|
"lib": [
|
||||||
|
"es2017",
|
||||||
|
"DOM"
|
||||||
|
],
|
||||||
|
"module": "commonjs",
|
||||||
|
"target": "es6",
|
||||||
|
"skipLibCheck": true,
|
||||||
|
"sourceMap": false,
|
||||||
|
"strict": true,
|
||||||
|
"useUnknownInCatchVariables": false,
|
||||||
|
"resolveJsonModule": true,
|
||||||
|
"esModuleInterop": true,
|
||||||
|
"outDir": "dist",
|
||||||
|
"types": [
|
||||||
|
"node"
|
||||||
|
],
|
||||||
|
},
|
||||||
|
"exclude": [
|
||||||
|
"node_modules"
|
||||||
|
],
|
||||||
|
"main": "generate/index"
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user