Compare commits

..

66 Commits

Author SHA1 Message Date
LinkLeong
eedfdde311 add filter 2023-08-31 07:26:44 +01:00
LinkLeong
38c7b5a569 update name 2023-08-24 11:57:32 +01:00
LinkLeong
8c0b219621 update path 2023-08-24 11:21:44 +01:00
LinkLeong
23fc677f30 Merge branch 'main' of github.com:IceWhaleTech/CasaOS 2023-08-24 09:23:45 +01:00
LinkLeong
a06508783c update path 2023-08-24 09:23:40 +01:00
Tiger Wang
37fee157dd add message-bus-codegen CLI tool for generating a markdown of all event types (#1346) 2023-08-23 18:21:12 +08:00
LinkLeong
3f1c7098bd add v3 file path 2023-08-23 08:29:41 +01:00
LinkLeong
b11d046c52 add route 2023-08-23 04:35:43 +01:00
LinkLeong
d6a9ba65ed add onedrive icon 2023-08-22 05:01:40 +01:00
link
5f1df76dbf Community (#1341) 2023-08-18 15:46:29 +08:00
Tiger Wang
0cf353c56e create default config if it does not already exist (#1304) 2023-07-31 16:53:03 +08:00
LinkLeong
5dc6297047 Merge branch 'main' of github.com:IceWhaleTech/CasaOS 2023-07-25 03:29:00 +01:00
LinkLeong
f26ae2793c Update zerotier 2023-07-25 03:28:52 +01:00
CorrectRoadH
d7641e1b93 chore: fix the readme error (#1270)
Signed-off-by: CorrectRoadH <a778917369@gmail.com>
2023-07-21 20:44:11 +08:00
CorrectRoadH
37c496fd6a chore:add zhanghenxing to contributor (#1269)
same to the title
2023-07-21 20:43:07 +08:00
CorrectRoadH
cb15c06f7e chore: add Contributor (#1268)
😆add me to the contributor list🤫
My Code in https://github.com/IceWhaleTech/CasaOS-AppManagement
My Document in https://github.com/IceWhaleTech/CasaOS-AppStore/pull/187
2023-07-21 20:38:04 +08:00
LinkLeong
89a0ea34b0 Add get version function 2023-07-20 04:12:46 +01:00
LinkLeong
d8dd815baa Update ip 2023-07-19 07:46:23 +01:00
LinkLeong
a77b5d1954 Update ip 2023-07-18 08:54:01 +01:00
LinkLeong
d0fb2f06f5 Supplementary log 2023-07-18 08:13:11 +01:00
raller1028
dd8032a8be Update push_test_server.yml (#1243)
Signed-off-by: raller1028 <57336867+raller1028@users.noreply.github.com>
2023-07-12 15:06:55 +08:00
raller1028
760882e147 Update push_test_server.yml (#1233)
Signed-off-by: raller1028 <57336867+raller1028@users.noreply.github.com>
2023-07-03 17:10:45 +08:00
LinkLeong
dfeed76a66 Update permission issues 2023-07-03 10:08:05 +01:00
Tiger Wang
28d724731a remove submit application template 2023-06-27 08:18:15 -04:00
Tiger Wang
4549d8778b remove feedback template 2023-06-27 08:15:52 -04:00
Tiger Wang
05cadaabf3 update bug_report.md (#1216)
Signed-off-by: Tiger Wang <tigerwang@outlook.com>
2023-06-26 17:36:34 -04:00
link
1a0c15208c Update demo.yml (#1213)
Signed-off-by: link <a624669980@163.com>
2023-06-25 17:09:31 +08:00
link
4f5b4b0887 Update demo.yml (#1212)
Signed-off-by: link <a624669980@163.com>
2023-06-25 17:07:17 +08:00
link
cbfe44be61 Update demo.yml (#1211)
Signed-off-by: link <a624669980@163.com>
2023-06-25 17:05:27 +08:00
link
e1bbb998df Update demo.yml (#1210)
Signed-off-by: link <a624669980@163.com>
2023-06-25 16:58:29 +08:00
link
f48cddf924 Up json (#1186) 2023-06-14 11:32:04 +08:00
raller1028
23ce3487e1 Update demo.yml (#1174)
Add demo reset error handle

Signed-off-by: raller1028 <57336867+raller1028@users.noreply.github.com>
2023-06-07 16:09:01 +08:00
link
6246421dae Up json (#1173)
Signed-off-by: link <a624669980@163.com>
2023-06-07 15:23:29 +08:00
link
f867453573 Update entry json output (#1172) 2023-06-07 15:21:22 +08:00
link
78e7a8b411 Add zt dynamic ip (#1168) 2023-06-05 16:49:32 +08:00
link
1aa8fb600b Remove 9527 (#1162) 2023-06-02 18:51:25 +08:00
link
7ecfea71ab Update json (#1160) 2023-06-01 17:09:34 +08:00
link
d911d80254 Socket update (#1159) 2023-06-01 10:22:04 +08:00
link
9bfe37305c Socket update (#1154) 2023-05-31 18:02:46 +08:00
link
94dd2e00c7 Socket update (#1153) 2023-05-31 16:10:14 +08:00
link
c5d2cebe92 Socket update (#1151) 2023-05-30 18:57:15 +08:00
link
955e8dea07 Update socket address (#1147) 2023-05-29 17:17:39 +08:00
link
4c7b3a749b Zt update (#1146) 2023-05-29 15:38:39 +08:00
link
e86a61596b Update zt (#1139) 2023-05-26 18:37:16 +08:00
link
c9617e583f Add zertier (#1137)
Signed-off-by: link <a624669980@163.com>
2023-05-26 17:45:18 +08:00
link
dda15b0821 Add zertier (#1124)
Signed-off-by: link <a624669980@163.com>
2023-05-25 12:14:32 +08:00
link
50816c68b0 Update demo.yml (#1121)
Signed-off-by: link <a624669980@163.com>
2023-05-24 19:12:18 +08:00
李旭海
c5de0319fb Update publish_npm.yaml (#1120)
Signed-off-by: 李旭海 <lxh_shine@hotmail.com>
Signed-off-by: zhanghengxin <812718649@qq.com>
Co-authored-by: zhanghengxin <812718649@qq.com>
2023-05-24 13:49:03 +08:00
link
78b7c6ce09 Add zertier (#1116) 2023-05-23 16:39:25 +08:00
link
b420a2d930 Add logs function (#1108) 2023-05-22 17:28:30 +08:00
zhanghengxin
c67ee1731c Introducing new features.Incorporating automatic publishin… (#1107)
Introducing new features.Incorporating automatic publishing for the
openAPI npm package.
2023-05-22 16:45:06 +08:00
raller1028
eaca399ef9 Add zerotier route (#1098) 2023-05-22 16:44:39 +08:00
LinkLeong
e0e9f97764 Update ip address 2023-05-22 04:32:47 +01:00
link
2fefee87fa Fixed compression error (#1097) 2023-05-19 16:50:48 +08:00
link
280ad4fcf9 Add merge json (#1079) 2023-05-15 11:01:21 +08:00
Tiger Wang
538639b623 fix (*service).Ports() missing ports from IPv6 (#1069) 2023-05-09 17:02:59 -04:00
老竭力
39535d6a38 Update README.md (#1067)
Signed-off-by: 老竭力 <jerrykuku@qq.com>
2023-05-09 18:13:29 +08:00
老竭力
4d977d7a62 Update demo.yml (#1049)
Signed-off-by: 老竭力 <jerrykuku@qq.com>
2023-05-06 11:35:44 +08:00
link
08c500c434 Add local jwt (#1047) 2023-05-05 10:37:23 +08:00
link
705bf1facb Update jwt (#1025) 2023-04-26 16:00:43 +08:00
Tiger Wang
aae1802191 bump version from 0.4.3 to 0.4.4
Signed-off-by: Tiger Wang <tigerwang@outlook.com>
2023-04-24 16:11:16 -04:00
Tiger Wang
8e1b9b82c1 add /v2/casaos/health/ports to get ports in use (#1023)
Signed-off-by: Tiger Wang <tigerwang@outlook.com>
2023-04-24 16:10:15 -04:00
link
af440eac55 Update samba (#1021) 2023-04-24 11:24:22 +08:00
link
34b4e154a1 fix reboot auto mount (#1007) 2023-04-12 13:53:27 +08:00
Lauren
79db93ec02 Update README.md
Update the project introduction

Signed-off-by: Lauren <Lauren-ED209@users.noreply.github.com>
2023-03-29 17:57:17 +08:00
Tiger Wang
f8ec3b20cd upgrade dependencies (#978)
Signed-off-by: Tiger Wang <tigerwang@outlook.com>
2023-03-25 23:37:00 -04:00
57 changed files with 1945 additions and 324 deletions

View File

@@ -8,39 +8,57 @@ assignees: ''
---
**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**
Steps to reproduce the behavior:
> Steps to reproduce the behavior:
1. Go to '...'
2. Click on '....'
3. Scroll down to '....'
4. See error
**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**
If applicable, add screenshots to help explain your problem.
> If applicable, add screenshots to help explain your problem.
**Desktop (please complete the following information):**
```
- OS: [e.g. iOS]
- Browser [e.g. chrome, safari]
- Version [e.g. 22]
```
**System Time**
> Run `timedatectl` and share the output
```
(timedatectl output here)
```
**Logs**
run following command to collect corresponding logs:
> Run following command to collect corresponding logs:
```bash
sudo journalctl -xef -u casaos-gateway
sudo journalctl -xef -u casaos-user-service
sudo journalctl -xef -u casaos-local-storage
sudo journalctl -xef -u casaos-app-management
sudo journalctl -xef -u casaos.service
```
**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.

View File

@@ -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.

View File

@@ -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

View File

@@ -33,9 +33,10 @@ jobs:
- name: Get old instance and snapshot name, create new instance name
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_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 "NEW_INSTANCE_NAME=CasaOS-Demo-$(date +%s)" >> $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]' | 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
- name: Create instances from snapshot
run: |
@@ -75,5 +76,9 @@ jobs:
run: |
aws lightsail delete-instance \
--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
View 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}}

View File

@@ -3,6 +3,8 @@ on:
push:
branches:
- main
workflow_dispatch:
permissions:
contents: write
jobs:
@@ -19,7 +21,7 @@ jobs:
- name: git global
run: sudo git config --global --add safe.directory '*'
- name: set version
run: sudo git tag v99.99.99-alpha
run: sudo git tag v00.00.00-alpha
- name: Fetch all tags
run: sudo git fetch --force --tags
@@ -44,10 +46,16 @@ jobs:
with:
# either 'goreleaser' (default) or 'goreleaser-pro'
distribution: goreleaser
version: latest
version: 1.14.1
args: release --rm-dist --snapshot
env:
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
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

View File

@@ -42,6 +42,12 @@ jobs:
args: release --rm-dist
env:
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
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}

View File

@@ -113,24 +113,22 @@ builds:
goarm:
- "7"
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
builds:
- casaos-amd64
- casaos-arm64
- casaos-arm-7
replacements:
arm: arm-7
files:
- 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
builds:
- casaos-migration-tool-amd64
- casaos-migration-tool-arm64
- casaos-migration-tool-arm-7
replacements:
arm: arm-7
files:
- build/sysroot/etc/**/*
checksum:

View File

@@ -19,6 +19,12 @@ builds:
ldflags:
- -X main.commit={{.Commit}}
- -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
- -w
- -extldflags "-static"
@@ -40,6 +46,12 @@ builds:
ldflags:
- -X main.commit={{.Commit}}
- -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
- -w
- -extldflags "-static"
@@ -61,6 +73,12 @@ builds:
ldflags:
- -X main.commit={{.Commit}}
- -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
- -w
- -extldflags "-static"
@@ -143,24 +161,22 @@ builds:
goarm:
- "7"
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
builds:
- casaos-amd64
- casaos-arm64
- casaos-arm-7
replacements:
arm: arm-7
files:
- 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
builds:
- casaos-migration-tool-amd64
- casaos-migration-tool-arm64
- casaos-migration-tool-arm-7
replacements:
arm: arm-7
files:
- build/sysroot/etc/**/*
checksum:

View File

@@ -1,6 +1,4 @@
# CasaOS - Your Home Cloud OS
# CasaOS - Your Personal Cloud
<!-- Readme i18n links -->
<!-- > English | [中文](#) | [Français](#) -->
@@ -12,7 +10,7 @@
<img alt="CasaOS" src="https://raw.githubusercontent.com/IceWhaleTech/logo/main/casaos/casaos_banner_twilight_blue_800x300.png">
</picture>
<br/>
<i>Connect with the community developing HOME CLOUD, creating self-sovereign, and defining the future of the distributed cloud.</i>
<i>Connect with the community, establish autonomy, reduce the cost of SaaS, and MAXIMIZE the potential for a personalized copilot.</i>
<br/>
<br/>
<!-- CasaOS Badges -->
@@ -65,18 +63,16 @@
</kbd>
</p>
## Why do we need Home Cloud?
## Why do you need Personal Cloud?
Think about it seriously. Is control of our data, smart devices and digital assets now only in the hands of some big company?
In 2020, the team noticed three important trends:
- The cost of computing power and storage was decreasing fast.
- A part of cloud computing was moving towards edge computing.
- The issue of consumer data asset ownership and attribution had been ignored.
- Is your photo album saved in their cloud service?
- Do your thermostats, monitors, lamps need to be used through their cloud services?
- Do your personal documents, memos, contacts, passwords, etc. reside in their cloud storage services?
- Are you just going to have to accept their decisions when they decide to change prices, review content or even discontinue services?
Based on these trends, the team proposed a thought experiment internally: what if personal clouds were available under $100 in next five years? This personal cloud would provide a low-cost data collaboration solution as a personal data center, storing and managing data for creators and small organizations. A distributed collaborative computing network can be formed by personal servers located around the world. It could also control and connect all smart devices, providing cross-ecosystem local intelligent services.
It sounds ridiculous, doesn't it? We are losing control of our own data!
Our ideal home cloud is one where you can manage all your data, devices and data assets very easily. In your own home, you have absolute control.
Furthermore, the personal cloud could combine personal data to train personalized AI assistants. The idea is that this technology would be an effective way to solve the issue of consumer data asset ownership and , as well as provide a more affordable and efficient computing solution for individuals and small organizations.
> If you think what we are doing is valuable. Please **give us a star ⭐** and **fork it 🤞**!
@@ -169,6 +165,10 @@ CasaOS is a community-driven open source project and the people involved are Cas
- See <https://wiki.casaos.io/en/contribute> for ways of contribution to CasaOS
- See <https://wiki.casaos.io/en/contribute/development> if you want to be involved in code contribution specificially
## 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>
## Credits
Many thanks to everyone who has helped CasaOS so far!
@@ -199,6 +199,8 @@ Everyone's contribution is greatly appreciated. ([Emoji Key](https://allcontribu
</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/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>
</table>

View File

@@ -47,6 +47,35 @@ paths:
$ref: "#/components/responses/GetHealthServicesOK"
"500":
$ref: "#/components/responses/ResponseInternalServerError"
/health/ports:
get:
tags:
- Health methods
summary: Get port in use
operationId: getHealthPorts
responses:
"200":
$ref: "#/components/responses/GetHealthPortsOK"
"500":
$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:
get:
tags:
@@ -60,6 +89,52 @@ paths:
$ref: "#/components/responses/ResponseOK"
"500":
$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:
securitySchemes:
access_token:
@@ -93,6 +168,24 @@ components:
data:
$ref: "#/components/schemas/HealthServices"
GetHealthPortsOK:
description: OK
content:
application/json:
schema:
allOf:
- $ref: "#/components/schemas/BaseResponse"
- properties:
data:
$ref: "#/components/schemas/HealthPorts"
GetZTInfoOK:
description: OK
content:
application/json:
schema:
$ref: "#/components/schemas/ZTInfo"
schemas:
BaseResponse:
properties:
@@ -114,3 +207,29 @@ components:
items:
type: string
example: "casaos.service"
HealthPorts:
properties:
tcp:
type: array
items:
type: integer
example: 80
x-go-name: TCP
udp:
type: array
items:
type: integer
example: 53
x-go-name: UDP
ZTInfo:
properties:
id:
type: string
example: "1234567890"
name:
type: string
example: "CasaOS"
status:
type: string
example: "online"

View File

@@ -1,7 +1,6 @@
[Unit]
After=casaos-message-bus.service
After=rclone.service
ConditionFileNotEmpty=/etc/casaos/casaos.conf
Description=CasaOS Main Service
[Service]

View 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)
}

View File

@@ -77,7 +77,7 @@ func init() {
}
}
config.InitSetup(configFlag)
config.InitSetup(configFlag, "")
if len(dbFlag) == 0 {
dbFlag = config.AppInfo.DBPath + "/db"

View File

@@ -8,10 +8,12 @@ import (
"compress/gzip"
"encoding/base64"
"fmt"
"net/http"
"net/url"
"path"
"strings"
"github.com/deepmap/oapi-codegen/pkg/runtime"
"github.com/getkin/kin-openapi/openapi3"
"github.com/labstack/echo/v4"
)
@@ -20,18 +22,45 @@ const (
Access_tokenScopes = "access_token.Scopes"
)
// Defines values for SetZerotierNetworkStatusJSONBodyStatus.
const (
Offline SetZerotierNetworkStatusJSONBodyStatus = "offline"
Online SetZerotierNetworkStatusJSONBodyStatus = "online"
)
// BaseResponse defines model for BaseResponse.
type BaseResponse struct {
// Message message returned by server side if there is any
Message *string `json:"message,omitempty"`
}
// HealthPorts defines model for HealthPorts.
type HealthPorts struct {
TCP *[]int `json:"tcp,omitempty"`
UDP *[]int `json:"udp,omitempty"`
}
// HealthServices defines model for HealthServices.
type HealthServices struct {
NotRunning *[]string `json:"not_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.
type GetHealthPortsOK struct {
Data *HealthPorts `json:"data,omitempty"`
// Message message returned by server side if there is any
Message *string `json:"message,omitempty"`
}
// GetHealthServicesOK defines model for GetHealthServicesOK.
type GetHealthServicesOK struct {
Data *HealthServices `json:"data,omitempty"`
@@ -40,20 +69,46 @@ type GetHealthServicesOK struct {
Message *string `json:"message,omitempty"`
}
// GetZTInfoOK defines model for GetZTInfoOK.
type GetZTInfoOK = ZTInfo
// ResponseInternalServerError defines model for ResponseInternalServerError.
type ResponseInternalServerError = BaseResponse
// ResponseOK defines model for ResponseOK.
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.
type ServerInterface interface {
// Test file methods
// (GET /file/test)
GetFileTest(ctx echo.Context) error
// Get log
// (GET /health/logs)
GetHealthlogs(ctx echo.Context) error
// Get port in use
// (GET /health/ports)
GetHealthPorts(ctx echo.Context) error
// Get service status
// (GET /health/services)
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.
@@ -72,6 +127,28 @@ func (w *ServerInterfaceWrapper) GetFileTest(ctx echo.Context) error {
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.
func (w *ServerInterfaceWrapper) GetHealthPorts(ctx echo.Context) error {
var err error
ctx.Set(Access_tokenScopes, []string{""})
// Invoke the callback with all the unmarshalled arguments
err = w.Handler.GetHealthPorts(ctx)
return err
}
// GetHealthServices converts echo context to params.
func (w *ServerInterfaceWrapper) GetHealthServices(ctx echo.Context) error {
var err error
@@ -83,6 +160,35 @@ func (w *ServerInterfaceWrapper) GetHealthServices(ctx echo.Context) error {
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
// are present on both echo.Echo and echo.Group, since we want to allow using
// either of them for path registration
@@ -112,29 +218,39 @@ func RegisterHandlersWithBaseURL(router EchoRouter, si ServerInterface, baseURL
}
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/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
var swaggerSpec = []string{
"H4sIAAAAAAAC/7xW70/jRhD9V1bTfoDKxBGoUmXpPnC9wiFUpSpIrUSi3GY9sfewd92ZcSBF/t+rXZtL",
"SCiC649PiffHe2/e7szsAxhfN96hE4bsAQi58Y4xfpyjfERdSXmFtLIGeXIZho13gk7CX900lTVarHfp",
"Z/YujLEpsdZxtqomS8huHuBbwiVk8E26YUv7dZy+14y/DrTQJQ/QkG+QxPYici0R7CWIpyqh67pZ13UJ",
"5MiGbBPkQQaTS+gSeKS6cILkdBV2If1E5OlNwb0+pH0lj9yqJ1c9+5a4Nxr9T7QEV7pkAIuOP9mR7Z5H",
"jcy6iBNPgYYJRSgtOczVYq24j49tjsoulZRIqCwr7daQAN7ruqkQMoAECHU+cdUaMqEWE5B1E2ZYyLqi",
"F75zzHvSnJc5tc6FDdkDWME6jm94jGbtecQ9BOyxfBnQRHodvl+Dd1RowTu9fj1uDIfRtGRlfRWs7yPQ",
"xiDzXPwtxiO2wdgSdY4ECThdB4zTVkpP9s94GzZcurGXuO6dsm7p909o2o7HJ6axRlrC+IFTp5RS/QT7",
"lgyqGnOr303hoCFcIvGR8ZWno3hBMFO5ptvDKSgmwyjvplCKNJylKem7UWGlbBctIw13d2R8nV4Y/K3U",
"FV6jKdPKFz6ttXVpb97wM19o55DmAX7ubFHK/IfxuLkfNa6YwteKrQLQf6hW7mykmC+qFl8WbOtC6SpI",
"+FGznlz1ov5/Rb2adOcWTF2vSp3+cqEa8iubI6vassGq0g59y6pGKX3OaulJ5Xa5REInig06TdbzKKCc",
"eVKWucWQ47nKLZuW2XrHiWoq1IxqZdlKKAXq5tzKx3ahCBvPVjytZwePbvRO7IffyzxUntRnb5268S2p",
"D5aNp3yzO+8HRkWR3ro/TheL9wv8/XA0jeliJebuJmBIYIXEfZKsjkO6+gadbixkcDIaj04ggUZLGXM0",
"XdoKU0GOhblA2U+0a2RRYdmjZyOIkBRT9iKHLPTWMxtiYonFb6vtHo/Hf1fUv6xLtzpFl8D3b9nyXOeL",
"9aita03r5/QH23TBkN3A2fbwLOxLy1iXU94qzM/aco6ihnqqWLS0rPxSoTal+jRU0u8+qQHmWct2OsDX",
"GPfco+bfdzCEOgQyhLplYc+/beJWN4jvpad94GbWzcKCQMZxvqUKMkhXx0P2Q1gwwO+6fnA9+TA53LSP",
"Hfbw4np5w5MTD0T3R6KLc/Jt0/MN637euyt7gc66vwIAAP//o5zNVnEKAAA=",
"H4sIAAAAAAAC/8xX72/bNhD9VwhuH5pBsbxk3ToB/dAfaxoUW4Ilw4bGhktLZ4mNRKp3pyRuoP99oCjb",
"sq386pqhn2xRp7v3Hnnk47WMbVFaA4ZJRtcSgUprCJqHA+C3oHLOji0yHb1zY7E1DIbdX1WWuY4Va2vC",
"j2SNG6M4g0I1b/P8aCajs2v5PcJMRvK7cFUq9HEUvlQEf7Y1ZR1cyxJtCcjaI0gUN8luS9GBKOu6Htd1",
"HcgEKEZdOmwykkfvZB2s6JwAXugYvnFGC5R3knp/emhm9oFkbqvvE8obay7oHRoGNCp3SAF/Q7T41TCs",
"y7iNZFFb+OLCV++A+4p63IXFqVIHbbJmlte+iDbXQAFEKm1erCdqXwgErtBAIqZzQZ4f6QSEngnOAEFo",
"EsrMZSDhShVlDjKSMpAIKjky+VxGjBUEkuele0OM2qQeeLdZtnBxXLofzVA0z8vkz4bLZNowpNAo3Y4o",
"ROWgXO2mdteowo2dvjp2EVVyQ8Kn+w9M+Nfr4y6BZW9scTCWJ1gZ4xj3lpaxImVpQD6F3JJpA0cdyPvk",
"200Vw6Wa3z+vY9N22hYLnazX+HFv/6enP//y7NdhX16vUTf+lSJ1dNIXS6y42mBgTa5ND+IGIkFcoeb5",
"iVvdHp2KYyCasD2Hpou0W7sZqARQLtDIFxVnFvXnpuFWuVWp30HLXrfc15tgVA2H+3GpY64QmgcYGSGE",
"8C/IVhiDKCDR6vlIPikRZoC0G9vc4m7TgxCJROH5zkgKwpiAn49kxlxSFIaoLgep5qyaVgTYbg+D2Bbh",
"YQx/ZyqHU4izMLepDQulTeint/2ZTJUxgBOXfmJ0mvHk2XBYXg1Kk47kl4LNXaJHRMuXuikxmeYV3A5Y",
"F6lQuYPgl5AH9f8j8mjCjVUwMh6VeHF8KEq0FzoBEoWmGPJcGbAViQI4swmJmUWR6NkMEAwLisEo1JYG",
"Lssbi0ITVeC20UQkmuKKSFtDgShzUATiQpNmt9uKswPNb6upQCgtabY4Hz9ZqOGV2KbvYe4Ii+Kj1Uac",
"2QrFa02xxWT1deIHBmkanptPL6bTl1P4Z2cwatpFc6eTHWEZyAtA8k1yseea2ZZgVKllJPcHw8G+DGSp",
"OGt6NJzpHEIGas6+FHi70U6BWLiwhWYD2aTEpmUPExk5d/FGO07EzfnSMYd7w+FN5+YyLuwcxnUgnz7k",
"kz5z0exHVVEonPfhd7KplGR0Jt90h8fuuzBrTg63MqkjyRZff8A0Uf2Mb7AUNmbgXWIEVaxbi5nFQrGM",
"5FQbh7z3YO7zWV9ZrwNgkdu0o5Ln2q9TufAItwvlrcSXrI2t28XjMHY8hDaiIrgnc+qYi97GcWlbTyD8",
"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

View File

@@ -2,6 +2,7 @@ package common
const (
SERVICENAME = "casaos"
VERSION = "0.4.2"
VERSION = "0.4.4.1"
BODY = " "
RANW_NAME = "IceWhale-RemoteAccess"
)

View File

@@ -1,23 +1,12 @@
package common
import (
"fmt"
"github.com/IceWhaleTech/CasaOS/codegen/message_bus"
)
var (
// devtype -> action -> event
EventTypes map[string]map[string]message_bus.EventType
PropertyNameLookupMaps = map[string]map[string]string{
"system": {
fmt.Sprintf("%s:%s", SERVICENAME, "utilization"): "ID_BUS",
},
}
ActionPastTense = map[string]string{
"add": "added",
"remove": "removed",
}
)
// devtype -> action -> event
var EventTypes = []message_bus.EventType{
{Name: "casaos:system:utilization", SourceID: SERVICENAME, PropertyTypeList: []message_bus.PropertyType{}},
{Name: "casaos:file:recover", SourceID: SERVICENAME, PropertyTypeList: []message_bus.PropertyType{}},
{Name: "casaos:file:operate", SourceID: SERVICENAME, PropertyTypeList: []message_bus.PropertyType{}},
}

View File

@@ -3,6 +3,7 @@ package drivers
import (
_ "github.com/IceWhaleTech/CasaOS/drivers/dropbox"
_ "github.com/IceWhaleTech/CasaOS/drivers/google_drive"
_ "github.com/IceWhaleTech/CasaOS/drivers/onedrive"
)
// All do nothing,just for import

View File

@@ -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 {
return nil
}
func (d *Dropbox) GetInfo(ctx context.Context) (string, string, string, error) {
return "", "", "", nil
}
var _ driver.Driver = (*Dropbox)(nil)

View File

@@ -2,12 +2,9 @@ package dropbox
import (
"github.com/IceWhaleTech/CasaOS/internal/driver"
"github.com/IceWhaleTech/CasaOS/internal/op"
)
const ICONURL = "./img/driver/Dropbox.svg"
const APPKEY = "tciqajyazzdygt9"
const APPSECRET = "e7gtmv441cwdf0n"
type Addition struct {
driver.RootID
@@ -15,7 +12,7 @@ type Addition struct {
AppKey string `json:"app_key" type:"string" default:"tciqajyazzdygt9" 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"`
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"`
Code string `json:"code" type:"string" help:"code from auth_url" omit:"true"`
}
@@ -25,9 +22,3 @@ var config = driver.Config{
OnlyProxy: true,
DefaultRoot: "root",
}
func init() {
op.RegisterDriver(func() driver.Driver {
return &Dropbox{}
})
}

View File

@@ -10,6 +10,11 @@ import (
"go.uber.org/zap"
)
var (
app_key = "private build"
app_secret = "private build"
)
func (d *Dropbox) getRefreshToken() error {
url := "https://api.dropbox.com/oauth2/token"
var resp base.TokenResp
@@ -100,3 +105,12 @@ func (d *Dropbox) getFiles(path string) ([]File, error) {
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
}

View File

@@ -80,6 +80,9 @@ func (d *GoogleDrive) GetUserInfo(ctx context.Context) (string, error) {
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 {
data := base.Json{
"name": dirName,

View File

@@ -2,22 +2,19 @@ package google_drive
import (
"github.com/IceWhaleTech/CasaOS/internal/driver"
"github.com/IceWhaleTech/CasaOS/internal/op"
)
const ICONURL = "./img/driver/GoogleDrive.svg"
const CLIENTID = "921743327851-urr4f7jjfp4ts639evqb3i4m4qb4u4cc.apps.googleusercontent.com"
const CLIENTSECRET = "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"
type Addition struct {
driver.RootID
RefreshToken string `json:"refresh_token" required:"true" 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"`
ClientID string `json:"client_id" required:"true" default:"921743327851-urr4f7jjfp4ts639evqb3i4m4qb4u4cc.apps.googleusercontent.com" omit:"true"`
ClientSecret string `json:"client_secret" required:"true" default:"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" omit:"true"`
ClientID string `json:"client_id" required:"true" default:"" 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"`
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"`
Code string `json:"code" type:"string" help:"code from auth_url" omit:"true"`
}
@@ -27,9 +24,3 @@ var config = driver.Config{
OnlyProxy: true,
DefaultRoot: "root",
}
func init() {
op.RegisterDriver(func() driver.Driver {
return &GoogleDrive{}
})
}

View File

@@ -16,6 +16,11 @@ import (
"go.uber.org/zap"
)
var (
client_id = "private build"
client_secret = "private build"
)
// do others that not defined in Driver interface
func (d *GoogleDrive) getRefreshToken() error {
@@ -150,3 +155,13 @@ func (d *GoogleDrive) chunkUpload(ctx context.Context, stream model.FileStreamer
}
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
View 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
View 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
View 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
}

27
go.mod
View File

@@ -4,7 +4,7 @@ go 1.20
require (
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
github.com/IceWhaleTech/CasaOS-Common v0.4.2-alpha3
github.com/IceWhaleTech/CasaOS-Common v0.4.7-alpha4
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
github.com/deckarep/golang-set/v2 v2.3.0
github.com/deepmap/oapi-codegen v1.12.4
@@ -33,15 +33,18 @@ require (
github.com/patrickmn/go-cache v2.1.0+incompatible
github.com/pkg/errors v0.9.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/shirou/gopsutil/v3 v3.23.2
github.com/sirupsen/logrus v1.9.0
github.com/stretchr/testify v1.8.2
github.com/tidwall/gjson v1.14.4
go.uber.org/goleak v1.2.1
go.uber.org/zap v1.24.0
golang.org/x/crypto v0.7.0
golang.org/x/crypto v0.8.0
golang.org/x/oauth2 v0.6.0
golang.org/x/sync v0.1.0
golang.org/x/sys v0.7.0
gorm.io/gorm v1.24.6
gotest.tools v2.2.0+incompatible
)
@@ -53,6 +56,7 @@ require (
github.com/bytedance/sonic v1.8.5 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
@@ -66,8 +70,8 @@ require (
github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.11.2 // indirect
github.com/goccy/go-json v0.10.1 // indirect
github.com/go-playground/validator/v10 v10.12.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
@@ -83,16 +87,16 @@ require (
github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.16.3 // indirect
github.com/klauspost/compress v1.16.5 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect
github.com/kr/pretty v0.3.1 // indirect
github.com/labstack/gommon v0.4.0 // indirect
github.com/leodido/go-urn v1.2.2 // indirect
github.com/leodido/go-urn v1.2.3 // indirect
github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de // indirect
github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect
github.com/mattn/go-isatty v0.0.17 // indirect
github.com/mattn/go-isatty v0.0.18 // indirect
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
@@ -100,6 +104,7 @@ require (
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
github.com/perimeterx/marshmallow v1.1.4 // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/tidwall/match v1.1.1 // indirect
@@ -114,12 +119,12 @@ require (
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.10.0 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 // indirect
golang.org/x/image v0.6.0 // indirect
golang.org/x/net v0.8.0 // indirect
golang.org/x/sys v0.6.0 // indirect
golang.org/x/text v0.8.0 // indirect
golang.org/x/net v0.9.0 // indirect
golang.org/x/text v0.9.0 // indirect
golang.org/x/time v0.3.0 // indirect
google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.30.0 // indirect

49
go.sum
View File

@@ -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/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ=
github.com/IceWhaleTech/CasaOS-Common v0.4.2-alpha3 h1:WJUYo+hJpLmza7mQngoJVeUJOfnrZevNrX5wzTuOJo0=
github.com/IceWhaleTech/CasaOS-Common v0.4.2-alpha3/go.mod h1:xcemiRsXcs1zrmQxYMyExDjZ7UHYwkJqYE71IDIV0xA=
github.com/IceWhaleTech/CasaOS-Common v0.4.7-alpha4 h1:bsVQ+kdVkmPsqX6lxxETaShiMb9I8OgiR4xrEQ/vyss=
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/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
@@ -92,15 +92,15 @@ github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
github.com/go-playground/validator/v10 v10.12.0 h1:E4gtWgxWxp8YSxExrQFv5BpCahla0PVF2oTTEYaWQGI=
github.com/go-playground/validator/v10 v10.12.0/go.mod h1:hCAPuzYvKdP33pxWa+2+6AIKXEKqjIUyqsNCtbsSJrA=
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.1 h1:lEs5Ob+oOG/Ze199njvzHbhn6p9T+h64F5hRj69iTTo=
github.com/goccy/go-json v0.10.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@@ -169,8 +169,8 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY=
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI=
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
@@ -191,8 +191,8 @@ github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4=
github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ=
github.com/leodido/go-urn v1.2.3 h1:6BE2vPT0lqoz3fmOesHZiaiFh7889ssCo2GMvLCfiuA=
github.com/leodido/go-urn v1.2.3/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de h1:V53FWzU6KAZVi1tPp5UIsMoUWJ2/PNwYIDXnu7QuBCE=
github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
@@ -207,8 +207,8 @@ github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxec
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.18 h1:DOKFKCQ7FNG2L1rbrmstDN4QVRdS89Nkh85u68Uwp98=
github.com/mattn/go-isatty v0.0.18/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
github.com/mileusna/useragent v1.2.1 h1:p3RJWhi3LfuI6BHdddojREyK3p6qX67vIfOVMnUIVr0=
@@ -254,7 +254,8 @@ github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTE
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
github.com/shirou/gopsutil/v3 v3.23.2 h1:PAWSuiAszn7IhPMBtXsbSCafej7PqUOvY6YywlQUExU=
@@ -310,8 +311,8 @@ go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
@@ -322,8 +323,10 @@ golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8U
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
golang.org/x/crypto v0.8.0 h1:pd9TJtTueMTVQXzk8E2XESSMQDj/U7OUu0PqJqPXQjQ=
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17 h1:3MTrJm4PyNL9NBqvYDSj3DHl46qQakyfqfWo4jgfaEM=
golang.org/x/exp v0.0.0-20220303212507-bbda1eaf7a17/go.mod h1:lgLbSvA5ygNOMpwM/9anMpWVlVJ7Z+cHWq/eFuinpGE=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
golang.org/x/image v0.6.0 h1:bR8b5okrPI3g/gyZakLZHeWxAR8Dn5CyxXv1hLH5g/4=
golang.org/x/image v0.6.0/go.mod h1:MXLdDR43H7cDJq5GEGXEVeeNhPgi+YYEQ2pC1byI1x0=
@@ -344,8 +347,8 @@ golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
golang.org/x/net v0.9.0 h1:aWJ/m6xSmxWBx+V0XRHTlrYrPG56jKsLdTFmsSsCzOM=
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
@@ -378,20 +381,22 @@ golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.7.0 h1:3jlCCIQZPdOYu1h8BkNvLz8Kgwtae2cagcG/VamtZRU=
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
golang.org/x/term v0.7.0 h1:BEvjmm5fURWqcfbSKTdpkDXYBrUS1c0m8agp14W48vQ=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.9.0 h1:2sjJmO8cDvYveuX97RDLsxlyUxLl+GHoLxBiRdHllBE=
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=

View File

@@ -34,14 +34,16 @@ type Reader interface {
// 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 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(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 {
// GetRoot get root directory of user
GetUserInfo(ctx context.Context) (string, error)
GetInfo(ctx context.Context) (string, string, string, error)
}
type Getter interface {
GetRoot(ctx context.Context) (model.Obj, error)
}

27
main.go
View File

@@ -18,7 +18,6 @@ import (
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/pkg/cache"
"github.com/IceWhaleTech/CasaOS/pkg/config"
@@ -48,6 +47,9 @@ var (
//go:embed api/casaos/openapi.yaml
_docYAML string
//go:embed build/sysroot/etc/casaos/casaos.conf.sample
_confSample string
configFlag = flag.String("c", "", "config address")
dbFlag = flag.String("db", "", "db path")
versionFlag = flag.Bool("v", false, "version")
@@ -63,7 +65,7 @@ func init() {
println("git commit:", commit)
println("build date:", date)
config.InitSetup(*configFlag)
config.InitSetup(*configFlag, _confSample)
logger.LogInit(config.AppInfo.LogPath, config.AppInfo.LogSaveName, config.AppInfo.LogFileExt)
if len(*dbFlag) == 0 {
@@ -81,9 +83,10 @@ func init() {
route.InitFunction()
//service.MyService.System().GenreateSystemEntry()
///
// service.MountLists = make(map[string]*mountlib.MountPoint)
// configfile.Install()
//service.MountLists = make(map[string]*mountlib.MountPoint)
//configfile.Install()
}
// @title casaOS API
@@ -101,20 +104,17 @@ func main() {
if *versionFlag {
return
}
v1Router := route.InitV1Router()
v2Router := route.InitV2Router()
v2DocRouter := route.InitV2DocRouter(_docHTML, _docYAML)
v3file := route.InitFile()
v4dir := route.InitDir()
v3File := route.InitFile()
mux := &util_http.HandlerMultiplexer{
HandlerMap: map[string]http.Handler{
"v1": v1Router,
"v2": v2Router,
"v3": v3File,
"doc": v2DocRouter,
"v3": v3file,
"v4": v4dir,
},
}
@@ -143,6 +143,8 @@ func main() {
"/v1/cloud",
"/v1/recover",
"/v1/other",
"/v1/zt",
"/v1/test",
route.V2APIPath,
route.V2DocPath,
route.V3FilePath,
@@ -158,13 +160,10 @@ func main() {
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
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 {
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
View File

@@ -0,0 +1,7 @@
package model
type Drive struct {
Name string `json:"name"`
Icon string `json:"icon"`
AuthUrl string `json:"auth_url"`
}

View File

@@ -70,7 +70,8 @@ type FileSetting struct {
DownloadDir string `json:"download_dir"`
}
type BaseInfo struct {
Hash string `json:"i"`
Version string `json:"v"`
Channel string `json:"c,omitempty"`
Hash string `json:"i"`
Version string `json:"v"`
Channel string `json:"c,omitempty"`
DriveModel string `json:"m,omitempty"`
}

View File

@@ -23,3 +23,14 @@ type Path struct {
Write bool `json:"write"`
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
View 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"
}

View File

@@ -10,6 +10,10 @@
*/
package config
const (
USERCONFIGURL = "/etc/casaos/casaos.conf"
import (
"path/filepath"
"github.com/IceWhaleTech/CasaOS-Common/utils/constants"
)
var CasaOSConfigFilePath = filepath.Join(constants.DefaultConfigPath, "casaos.conf")

View File

@@ -14,80 +14,72 @@ import (
"fmt"
"log"
"os"
"path"
"path/filepath"
"runtime"
"strings"
"github.com/IceWhaleTech/CasaOS-Common/utils/constants"
"github.com/IceWhaleTech/CasaOS/common"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/go-ini/ini"
)
// 系统配置
var SysInfo = &model.SysInfoModel{}
var (
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{}
// 用户相关
var AppInfo = &model.APPModel{}
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
Cfg *ini.File
ConfigFilePath string
)
// 初始化设置,获取系统的部分信息。
func InitSetup(config string) {
configDir := USERCONFIGURL
func InitSetup(config string, sample string) {
ConfigFilePath = CasaOSConfigFilePath
if len(config) > 0 {
configDir = config
ConfigFilePath = config
}
if runtime.GOOS == "darwin" {
configDir = "./conf/conf.conf"
}
var err error
// 读取文件
Cfg, err = ini.Load(configDir)
if err != nil {
Cfg, err = ini.Load("/etc/casaos.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 {
Cfg, err = ini.Load("/casaOS/server/conf/conf.ini")
if err != nil {
fmt.Printf("Fail to read file: %v", err)
os.Exit(1)
}
panic(err)
}
defer file.Close()
// write default config
_, err = file.WriteString(sample)
if err != nil {
panic(err)
}
}
var err error
// 读取文件
Cfg, err = ini.Load(ConfigFilePath)
if err != nil {
panic(err)
}
mapTo("app", AppInfo)
// mapTo("redis", RedisInfo)
mapTo("server", ServerInfo)
mapTo("system", SystemConfigInfo)
mapTo("file", FileSettingInfo)
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)
}
}
// 获取当前执行文件绝对路径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)
}

View File

@@ -431,7 +431,9 @@ func AddFile(ar archiver.Writer, path, commonPath string) error {
defer file.Close()
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{
FileInfo: archiver.FileInfo{
FileInfo: info,

View 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
}

View File

@@ -1,6 +1,7 @@
package ip_helper
import (
"fmt"
"net"
"strings"
@@ -56,7 +57,30 @@ func GetDeviceAllIP(port string) []string {
}
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 {
if ip.IsLoopback() {
return true

View File

@@ -17,6 +17,7 @@ import (
"strings"
"time"
file1 "github.com/IceWhaleTech/CasaOS-Common/utils/file"
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
"github.com/IceWhaleTech/CasaOS/common"
"github.com/IceWhaleTech/CasaOS/model"
@@ -24,6 +25,7 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/samba"
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
"github.com/IceWhaleTech/CasaOS/service"
"go.uber.org/zap"
)
@@ -31,6 +33,7 @@ import (
func InitFunction() {
go InitNetworkMount()
go InitInfo()
go InitZerotier()
}
func InitInfo() {
@@ -51,6 +54,12 @@ func InitInfo() {
}
mb.Hash = encryption.GetMD5ByStr(mac)
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")
by, err := json.Marshal(mb)
if err != nil {
@@ -92,6 +101,12 @@ func InitNetworkMount() {
}
connection.Directories = strings.Join(directories, ",")
service.MyService.Connections().UpdateConnection(&connection)
service.MyService.Storage().CheckAndMountAll()
}
err := service.MyService.Storage().CheckAndMountAll()
if err != nil {
logger.Error("mount storage err", zap.Any("err", err))
}
}
func InitZerotier() {
v1.CheckNetwork()
}

View File

@@ -1,10 +1,13 @@
package route
import (
"crypto/ecdsa"
"os"
"github.com/IceWhaleTech/CasaOS-Common/external"
"github.com/IceWhaleTech/CasaOS-Common/middleware"
"github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
"github.com/IceWhaleTech/CasaOS/common"
"github.com/IceWhaleTech/CasaOS/pkg/config"
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
@@ -33,13 +36,16 @@ func InitV1Router() *gin.Engine {
r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug
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) {
ctx.String(200, "pong")
})
r.GET("/v1/recover/:type", v1.GetRecoverStorage)
v1Group := r.Group("/v1")
v1Group.Use(jwt.ExceptLocalhost())
// r.Any("/v1/test", v1.CheckNetwork)
v1Group.Use(jwt.ExceptLocalhost(func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) }))
{
v1SysGroup := v1Group.Group("/sys")
@@ -73,6 +79,7 @@ func InitV1Router() *gin.Engine {
// v1SysGroup.PUT("/port", v1.PutCasaOSPort)
v1SysGroup.GET("/proxy", v1.GetSystemProxy)
v1SysGroup.PUT("/state/:state", v1.PutSystemState)
v1SysGroup.GET("/entry", v1.GetSystemEntry)
}
v1PortGroup := v1Group.Group("/port")
v1PortGroup.Use()
@@ -80,7 +87,6 @@ func InitV1Router() *gin.Engine {
v1PortGroup.GET("/", v1.GetPort) // app/port
v1PortGroup.GET("/state/:port", v1.PortCheck) // app/check/:port
}
v1FileGroup := v1Group.Group("/file")
v1FileGroup.Use()
{
@@ -167,6 +173,11 @@ func InitV1Router() *gin.Engine {
v1OtherGroup.GET("/search", v1.GetSearchResult)
}
v1ZerotierGroup := v1Group.Group("/zt")
v1ZerotierGroup.Use()
{
v1ZerotierGroup.Any("/*url", v1.ZerotierProxy)
}
}
return r

View File

@@ -6,6 +6,7 @@ import (
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
"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/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
@@ -51,6 +52,10 @@ func ListStorages(c *gin.Context) {
if dataMap["type"] == "dropbox" {
r.MountPoints[i].Icon = dropbox.ICONURL
}
if dataMap["type"] == "onedrive" {
r.MountPoints[i].Icon = onedrive.ICONURL
}
r.MountPoints[i].Name = dataMap["username"]
}
list := []httper.MountPoint{}

View File

@@ -1,12 +1,34 @@
package v1
import (
"github.com/IceWhaleTech/CasaOS-Common/model"
"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"
)
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})
}

View File

@@ -480,6 +480,10 @@ func GetFileUpload(c *gin.Context) {
path := c.Query("path")
dirPath := ""
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)) + "/"
if fileName != relative {
dirPath = strings.TrimSuffix(relative, fileName)

View File

@@ -8,6 +8,7 @@ import (
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
"github.com/IceWhaleTech/CasaOS/drivers/dropbox"
"github.com/IceWhaleTech/CasaOS/drivers/google_drive"
"github.com/IceWhaleTech/CasaOS/drivers/onedrive"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
"go.uber.org/zap"
@@ -20,23 +21,17 @@ func GetRecoverStorage(c *gin.Context) {
currentDate := time.Now().UTC().Format("2006-01-02")
notify := make(map[string]interface{})
if t == "GoogleDrive" {
add := google_drive.Addition{}
add.Code = c.Query("code")
if len(add.Code) == 0 {
google_drive := google_drive.GetConfig()
google_drive.Code = c.Query("code")
if len(google_drive.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: ", 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)
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)
if err != nil {
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 += "_google_drive_" + strconv.FormatInt(time.Now().Unix(), 10)
dmap["client_id"] = add.ClientID
dmap["client_secret"] = add.ClientSecret
dmap["client_id"] = google_drive.ClientID
dmap["client_secret"] = google_drive.ClientSecret
dmap["scope"] = "drive"
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"}`
@@ -106,21 +101,17 @@ func GetRecoverStorage(c *gin.Context) {
notify["driver"] = "GoogleDrive"
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
} else if t == "Dropbox" {
add := dropbox.Addition{}
add.Code = c.Query("code")
if len(add.Code) == 0 {
dropbox := dropbox.GetConfig()
dropbox.Code = c.Query("code")
if len(dropbox.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", 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)
return
}
add.RootFolderID = ""
add.AppKey = dropbox.APPKEY
add.AppSecret = dropbox.APPSECRET
var dropbox dropbox.Dropbox
dropbox.Addition = add
err := dropbox.Init(c)
if err != nil {
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)
dmap["client_id"] = add.AppKey
dmap["client_secret"] = add.AppSecret
dmap["client_id"] = dropbox.AppKey
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["mount_point"] = "/mnt/" + username
// data.SetValue(username, "type", "dropbox")
@@ -199,6 +190,98 @@ func GetRecoverStorage(c *gin.Context) {
notify["message"] = "Success"
notify["driver"] = "Dropbox"
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>`)

View File

@@ -16,7 +16,6 @@ import (
"net/http"
"os"
"path/filepath"
"regexp"
"strings"
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
@@ -27,7 +26,6 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/samba"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/gin-gonic/gin"
@@ -139,22 +137,22 @@ func PostSambaConnectionsCreate(c *gin.Context) {
return
}
if ok, _ := regexp.MatchString(`^[\w@#*.]{4,30}$`, connection.Password); !ok {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CHARACTER_LIMIT, Message: common_err.GetMsg(common_err.CHARACTER_LIMIT)})
return
}
if ok, _ := regexp.MatchString(`^[\w@#*.]{4,30}$`, connection.Username); !ok {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
if !ip_helper.IsIPv4(connection.Host) && !ip_helper.IsIPv6(connection.Host) {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
if ok, _ := regexp.MatchString("^[0-9]{1,6}$", connection.Port); !ok {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
// if ok, _ := regexp.MatchString(`^[\w@#*.]{4,30}$`, connection.Password); !ok {
// c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CHARACTER_LIMIT, Message: common_err.GetMsg(common_err.CHARACTER_LIMIT)})
// return
// }
// if ok, _ := regexp.MatchString(`^[\w@#*.]{4,30}$`, connection.Username); !ok {
// c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return
// }
// if !ip_helper.IsIPv4(connection.Host) && !ip_helper.IsIPv6(connection.Host) {
// c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return
// }
// if ok, _ := regexp.MatchString("^[0-9]{1,6}$", connection.Port); !ok {
// c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return
// }
connection.Host = strings.Split(connection.Host, "/")[0]
// check is exists

View File

@@ -2,6 +2,7 @@ package v1
import (
"bytes"
"encoding/json"
"fmt"
"io"
"io/ioutil"
@@ -24,6 +25,7 @@ import (
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin"
"github.com/tidwall/gjson"
)
// @Summary check version
@@ -371,3 +373,13 @@ func PortCheck(c *gin.Context) {
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)})
}
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
View 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
}

View File

@@ -1,6 +1,7 @@
package route
import (
"crypto/ecdsa"
"log"
"net/http"
"net/url"
@@ -10,9 +11,10 @@ import (
"strings"
"github.com/IceWhaleTech/CasaOS/codegen"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS-Common/utils/common_err"
"github.com/IceWhaleTech/CasaOS-Common/external"
"github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
v2Route "github.com/IceWhaleTech/CasaOS/route/v2"
"github.com/deepmap/oapi-codegen/pkg/middleware"
@@ -28,7 +30,6 @@ var (
V2APIPath string
V2DocPath string
V3FilePath string
V4DirPath string
)
func init() {
@@ -47,7 +48,6 @@ func init() {
V2APIPath = strings.TrimRight(u.Path, "/")
V2DocPath = "/doc" + V2APIPath
V3FilePath = "/v3/file"
V4DirPath = "/v4/dir"
}
func InitV2Router() http.Handler {
@@ -72,20 +72,23 @@ func InitV2Router() http.Handler {
Skipper: func(c echo.Context) bool {
return c.RealIP() == "::1" || c.RealIP() == "127.0.0.1"
//return true
},
ParseTokenFunc: func(token string, c echo.Context) (interface{}, error) {
claims, code := jwt.Validate(token)
if code != common_err.SUCCESS {
valid, claims, err := jwt.Validate(token, func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) })
if err != nil || !valid {
return nil, echo.ErrUnauthorized
}
c.Request().Header.Set("user_id", strconv.Itoa(claims.ID))
return claims, nil
},
TokenLookupFuncs: []echo_middleware.ValuesExtractor{
func(c echo.Context) ([]string, error) {
return []string{c.Request().Header.Get(echo.HeaderAuthorization)}, nil
if len(c.Request().Header.Get(echo.HeaderAuthorization)) > 0 {
return []string{c.Request().Header.Get(echo.HeaderAuthorization)}, nil
}
return []string{c.QueryParam("token")}, nil
},
},
}))
@@ -137,17 +140,49 @@ func InitV2DocRouter(docHTML string, docYAML string) http.Handler {
}
})
}
func InitFile() http.Handler {
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")
fileName := path.Base(filePath)
w.Header().Add("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(fileName))
http.ServeFile(w, r, filePath)
//http.ServeFile(w, r, filePath)
})
}
func InitDir() http.Handler {
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")
files := r.URL.Query().Get("files")
@@ -174,7 +209,7 @@ func InitDir() http.Handler {
// handles only single files not folders and multiple files
// if len(list) == 1 {
//filePath := list[0]
// filePath := list[0]
// info, err := os.Stat(filePath)
// if err != nil {

View File

@@ -2,10 +2,15 @@ package v2
import (
"net/http"
"net/url"
"os"
"path/filepath"
"github.com/IceWhaleTech/CasaOS/codegen"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/labstack/echo/v4"
"github.com/mholt/archiver/v3"
)
func (s *CasaOS) GetHealthServices(ctx echo.Context) error {
@@ -24,3 +29,72 @@ func (s *CasaOS) GetHealthServices(ctx echo.Context) error {
},
})
}
func (s *CasaOS) GetHealthPorts(ctx echo.Context) error {
tcpPorts, udpPorts, err := service.MyService.Health().Ports()
if err != nil {
message := err.Error()
return ctx.JSON(http.StatusInternalServerError, codegen.ResponseInternalServerError{
Message: &message,
})
}
return ctx.JSON(http.StatusOK, codegen.GetHealthPortsOK{
Data: &codegen.HealthPorts{
TCP: &tcpPorts,
UDP: &udpPorts,
},
})
}
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
View 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)
}

View File

@@ -11,11 +11,12 @@
package service
import (
"github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"fmt"
"github.com/IceWhaleTech/CasaOS/service/model"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/moby/sys/mount"
"golang.org/x/sys/unix"
"gorm.io/gorm"
)
@@ -26,7 +27,7 @@ type ConnectionsService interface {
CreateConnection(connection *model2.ConnectionsDBModel)
DeleteConnection(id string)
UpdateConnection(connection *model2.ConnectionsDBModel)
MountSmaba(username, host, directory, port, mountPoint, password string) string
MountSmaba(username, host, directory, port, mountPoint, password string) error
UnmountSmaba(mountPoint string) error
}
@@ -56,9 +57,17 @@ func (s *connectionsStruct) DeleteConnection(id string) {
s.db.Where("id= ?", id).Delete(&model.ConnectionsDBModel{})
}
func (s *connectionsStruct) MountSmaba(username, host, directory, port, mountPoint, password string) string {
str := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;MountCIFS " + username + " " + host + " " + directory + " " + port + " " + mountPoint + " " + password)
return str
func (s *connectionsStruct) MountSmaba(username, host, directory, port, mountPoint, password string) error {
err := unix.Mount(
fmt.Sprintf("//%s/%s", host, directory),
mountPoint,
"cifs",
unix.MS_NOATIME|unix.MS_NODEV|unix.MS_NOSUID,
fmt.Sprintf("username=%s,password=%s", username, password),
)
return err
//str := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;MountCIFS " + username + " " + host + " " + directory + " " + port + " " + mountPoint + " " + password)
//return str
}
func (s *connectionsStruct) UnmountSmaba(mountPoint string) error {
return mount.Unmount(mountPoint)

View File

@@ -1,11 +1,13 @@
package service
import (
"github.com/IceWhaleTech/CasaOS-Common/utils/port"
"github.com/IceWhaleTech/CasaOS-Common/utils/systemctl"
)
type HealthService interface {
Services() (map[bool]*[]string, error)
Ports() ([]int, []int, error)
}
type service struct{}
@@ -34,6 +36,10 @@ func (s *service) Services() (map[bool]*[]string, error) {
return result, nil
}
func (s *service) Ports() ([]int, []int, error) {
return port.ListPortsInUse()
}
func NewHealthService() HealthService {
return &service{}
}

18
service/health_test.go Normal file
View File

@@ -0,0 +1,18 @@
package service_test
import (
"testing"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/stretchr/testify/assert"
)
func TestPorts(t *testing.T) {
service := service.NewHealthService()
tcpPorts, udpPorts, err := service.Ports()
assert.NoError(t, err)
assert.NotEmpty(t, tcpPorts)
assert.NotEmpty(t, udpPorts)
}

View File

@@ -1,6 +1,7 @@
package service
import (
"encoding/json"
"errors"
"fmt"
"io/ioutil"
@@ -15,10 +16,14 @@ import (
"github.com/IceWhaleTech/CasaOS-Common/utils/file"
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
"github.com/IceWhaleTech/CasaOS/common"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"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"
"github.com/shirou/gopsutil/v3/cpu"
@@ -49,6 +54,7 @@ type SystemService interface {
GetDiskInfo() *disk.UsageStat
GetSysInfo() host.InfoStat
GetDeviceTree() string
GetDeviceInfo() model.DeviceInfo
CreateFile(path string) (int, error)
RenameFile(oldF, newF string) (int, error)
MkdirAll(path string) (int, error)
@@ -57,9 +63,117 @@ type SystemService interface {
GetMacAddress() (string, error)
SystemReboot() error
SystemShutdown() error
GetSystemEntry() string
GenreateSystemEntry()
}
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) {
interfaces, err := net.Interfaces()
if err != nil {

25
tsconfig.json Normal file
View 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"
}