mirror of
https://github.com/IceWhaleTech/CasaOS.git
synced 2025-12-23 13:04:42 +00:00
Compare commits
167 Commits
v0.3.3-alp
...
v0.4.0-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
062d95c1eb | ||
|
|
75643287a5 | ||
|
|
6bda9406fb | ||
|
|
be9a010d17 | ||
|
|
3875827b7a | ||
|
|
5338d4662e | ||
|
|
3b9c4b62c5 | ||
|
|
536eac788d | ||
|
|
fc371bf068 | ||
|
|
299b20a087 | ||
|
|
eb31bf5586 | ||
|
|
04d4eacc60 | ||
|
|
60608c5dc7 | ||
|
|
b582e8f53e | ||
|
|
5690ccc1b5 | ||
|
|
13c2967889 | ||
|
|
8a37f9c879 | ||
|
|
96e9284235 | ||
|
|
06f83d3d68 | ||
|
|
438b8a1dd2 | ||
|
|
29e701cb7c | ||
|
|
43cc7596d2 | ||
|
|
11f800d138 | ||
|
|
a58a9e5477 | ||
|
|
5f015e9038 | ||
|
|
3922296d9b | ||
|
|
908a16ace4 | ||
|
|
f7a3863720 | ||
|
|
e94c2ff5c5 | ||
|
|
89487eb5db | ||
|
|
0fb5cab480 | ||
|
|
f210f29ae5 | ||
|
|
7bd5c6a2b4 | ||
|
|
230f1585a3 | ||
|
|
ca967ec59c | ||
|
|
c0b3260a6c | ||
|
|
9ed82cd55e | ||
|
|
381fb85b1d | ||
|
|
2beb1c0d82 | ||
|
|
772c3e0bc0 | ||
|
|
bcda992322 | ||
|
|
8cec47e4db | ||
|
|
87de9cec0a | ||
|
|
6d47d4ff18 | ||
|
|
4bb81e4669 | ||
|
|
c05d837350 | ||
|
|
8908c39969 | ||
|
|
df0f015944 | ||
|
|
46a37f0510 | ||
|
|
6ea3cdb364 | ||
|
|
be80d0cd95 | ||
|
|
296e88d099 | ||
|
|
b61a3db611 | ||
|
|
0f3d3e82f5 | ||
|
|
dd66f73157 | ||
|
|
cbbb907d6a | ||
|
|
ff6cdb6fda | ||
|
|
2eac040875 | ||
|
|
b41d855f73 | ||
|
|
182bc25343 | ||
|
|
12d5e5db03 | ||
|
|
455d226dcd | ||
|
|
f0448cd1b9 | ||
|
|
aff18fa091 | ||
|
|
80c347ac01 | ||
|
|
8113f51cf7 | ||
|
|
4f491fa22f | ||
|
|
3935489d8b | ||
|
|
d14381e6a2 | ||
|
|
42ebd5f325 | ||
|
|
a51bf70b79 | ||
|
|
3787c7bf99 | ||
|
|
ec7f6573ad | ||
|
|
50d68f3f76 | ||
|
|
d9c6a5c875 | ||
|
|
4bace9b16a | ||
|
|
84dfa7f5bf | ||
|
|
582f85c3ba | ||
|
|
7f4562629a | ||
|
|
4776b76b16 | ||
|
|
466350dd21 | ||
|
|
fb39529e8f | ||
|
|
4434ba522b | ||
|
|
aac8fe85ba | ||
|
|
9f938f65b1 | ||
|
|
314dbdab57 | ||
|
|
4ccae3f67f | ||
|
|
9f2e8dae6f | ||
|
|
727aca564b | ||
|
|
70ba4d5e3d | ||
|
|
8d088afcc5 | ||
|
|
34f35bbf20 | ||
|
|
b6f413b9e9 | ||
|
|
091be6d12e | ||
|
|
aefa68d8f8 | ||
|
|
9aed323d8d | ||
|
|
eba607fc53 | ||
|
|
d064f20a04 | ||
|
|
079e431d33 | ||
|
|
cee34ec1c2 | ||
|
|
848ee63386 | ||
|
|
c12c6cc940 | ||
|
|
f31fb22039 | ||
|
|
a5133bdbfa | ||
|
|
1902b2d4f2 | ||
|
|
fc5e351f0b | ||
|
|
7f642a7a4c | ||
|
|
c36a046a15 | ||
|
|
8b2c9486da | ||
|
|
ce5ecfcf84 | ||
|
|
bd1a2f5751 | ||
|
|
d2e0695d73 | ||
|
|
8cd18c3218 | ||
|
|
cc0ba82c92 | ||
|
|
ddca242d23 | ||
|
|
eaa07ba95a | ||
|
|
39a4c29680 | ||
|
|
af6900b1c7 | ||
|
|
9ec43a7691 | ||
|
|
bd85cda9fa | ||
|
|
94eaba6ecb | ||
|
|
e207c9c75f | ||
|
|
81d3293991 | ||
|
|
364fbf01f5 | ||
|
|
87e66aae8a | ||
|
|
3a60db3729 | ||
|
|
d3f78b52fa | ||
|
|
7d67a66d6b | ||
|
|
cb9e1b9dd9 | ||
|
|
dc8282acbb | ||
|
|
cf6103a2b5 | ||
|
|
6f98995e7d | ||
|
|
5cc41fa040 | ||
|
|
cb289f5b8a | ||
|
|
1377d55407 | ||
|
|
06eca38022 | ||
|
|
c47c1e548c | ||
|
|
552ec4849d | ||
|
|
7386a9dce3 | ||
|
|
b2b1daf5ab | ||
|
|
bbc0181e23 | ||
|
|
c23bd3f3a3 | ||
|
|
8a1839c02e | ||
|
|
164bf66190 | ||
|
|
a4c2a4b992 | ||
|
|
e7e82e6ca3 | ||
|
|
574295470e | ||
|
|
b1061f19ad | ||
|
|
bdd9eaca9f | ||
|
|
ec4c672924 | ||
|
|
5d4717de4d | ||
|
|
e2de783152 | ||
|
|
09f68f4034 | ||
|
|
cec83fc048 | ||
|
|
33e1d8a806 | ||
|
|
2a8dafae28 | ||
|
|
a426b56306 | ||
|
|
6202d38bdb | ||
|
|
4626ceb048 | ||
|
|
1e7333118c | ||
|
|
9758436a1e | ||
|
|
ed67e977b7 | ||
|
|
b0b1b5e262 | ||
|
|
2796c37bf6 | ||
|
|
d48e24f652 | ||
|
|
3a8cf593d9 | ||
|
|
0ffa2f901a |
197
.all-contributorsrc
Normal file
197
.all-contributorsrc
Normal file
@@ -0,0 +1,197 @@
|
|||||||
|
{
|
||||||
|
"files": [
|
||||||
|
"README.md"
|
||||||
|
],
|
||||||
|
"imageSize": 100,
|
||||||
|
"badgeTemplate": "<a href=\"#credits\"><img alt=\"All Contributors\" src=\"https://img.shields.io/static/v1?label=All%20Contributors&message=<%= contributors.length %>&color=162453&style=flat-square&logo=Handshake&logoColor=fff\" /></a>",
|
||||||
|
"commit": false,
|
||||||
|
"contributors": [
|
||||||
|
{
|
||||||
|
"login": "jerrykuku",
|
||||||
|
"name": "老竭力",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/9485680?v=4",
|
||||||
|
"profile": "https://github.com/jerrykuku",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"doc",
|
||||||
|
"ideas",
|
||||||
|
"infra",
|
||||||
|
"maintenance",
|
||||||
|
"platform",
|
||||||
|
"question",
|
||||||
|
"review"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "LinkLeong",
|
||||||
|
"name": "link",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/13556972?v=4",
|
||||||
|
"profile": "https://github.com/LinkLeong",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"doc",
|
||||||
|
"ideas",
|
||||||
|
"infra",
|
||||||
|
"maintenance",
|
||||||
|
"question",
|
||||||
|
"review"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "tigerinus",
|
||||||
|
"name": "Tiger Wang (王豫)",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/7172560?v=4",
|
||||||
|
"profile": "https://github.com/tigerinus",
|
||||||
|
"contributions": [
|
||||||
|
"code",
|
||||||
|
"doc",
|
||||||
|
"ideas",
|
||||||
|
"infra",
|
||||||
|
"maintenance",
|
||||||
|
"mentoring",
|
||||||
|
"security",
|
||||||
|
"question",
|
||||||
|
"review"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Lauren-ED209",
|
||||||
|
"name": "Lauren",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/8243355?v=4",
|
||||||
|
"profile": "https://github.com/Lauren-ED209",
|
||||||
|
"contributions": [
|
||||||
|
"ideas",
|
||||||
|
"fundingFinding",
|
||||||
|
"projectManagement",
|
||||||
|
"question",
|
||||||
|
"test"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "JohnGuan",
|
||||||
|
"name": "John Guan",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/3358477?v=4",
|
||||||
|
"profile": "https://JohnGuan.Cn",
|
||||||
|
"contributions": [
|
||||||
|
"blog",
|
||||||
|
"content",
|
||||||
|
"doc",
|
||||||
|
"ideas",
|
||||||
|
"eventOrganizing",
|
||||||
|
"mentoring",
|
||||||
|
"question",
|
||||||
|
"review"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "dtaivpp",
|
||||||
|
"name": "David Tippett",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/17506770?v=4",
|
||||||
|
"profile": "https://blog.tippybits.com",
|
||||||
|
"contributions": [
|
||||||
|
"doc",
|
||||||
|
"ideas",
|
||||||
|
"question"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "zarevskaya",
|
||||||
|
"name": "Skaya",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/60230221?v=4",
|
||||||
|
"profile": "https://github.com/zarevskaya",
|
||||||
|
"contributions": [
|
||||||
|
"mentoring",
|
||||||
|
"question",
|
||||||
|
"tutorial",
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "AuthorShin",
|
||||||
|
"name": "AuthorShin",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/4959043?v=4",
|
||||||
|
"profile": "https://github.com/AuthorShin",
|
||||||
|
"contributions": [
|
||||||
|
"test",
|
||||||
|
"bug",
|
||||||
|
"question",
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "baptiste313",
|
||||||
|
"name": "baptiste313",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/93325157?v=4",
|
||||||
|
"profile": "https://github.com/baptiste313",
|
||||||
|
"contributions": [
|
||||||
|
"translation"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "DrMxrcy",
|
||||||
|
"name": "DrMxrcy",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/58747968?v=4",
|
||||||
|
"profile": "https://github.com/DrMxrcy",
|
||||||
|
"contributions": [
|
||||||
|
"test",
|
||||||
|
"ideas",
|
||||||
|
"question"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Joooost",
|
||||||
|
"name": "Joooost",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/12090673?v=4",
|
||||||
|
"profile": "https://github.com/Joooost",
|
||||||
|
"contributions": [
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "sio",
|
||||||
|
"name": "Vitaly Potyarkin",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/334908?v=4",
|
||||||
|
"profile": "https://potyarkin.ml",
|
||||||
|
"contributions": [
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "bearfrieze",
|
||||||
|
"name": "Bjørn Friese",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1023813?v=4",
|
||||||
|
"profile": "https://github.com/bearfrieze",
|
||||||
|
"contributions": [
|
||||||
|
"ideas"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "Protektor-Desura",
|
||||||
|
"name": "Protektor",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/1195496?v=4",
|
||||||
|
"profile": "https://github.com/Protektor-Desura",
|
||||||
|
"contributions": [
|
||||||
|
"bug",
|
||||||
|
"ideas",
|
||||||
|
"question"
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"login": "llwaini",
|
||||||
|
"name": "llwaini",
|
||||||
|
"avatar_url": "https://avatars.githubusercontent.com/u/59589857?v=4",
|
||||||
|
"profile": "https://github.com/llwaini",
|
||||||
|
"contributions": [
|
||||||
|
"projectManagement",
|
||||||
|
"test",
|
||||||
|
"tutorial"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
],
|
||||||
|
"contributorsPerLine": 7,
|
||||||
|
"projectName": "CasaOS",
|
||||||
|
"projectOwner": "IceWhaleTech",
|
||||||
|
"repoType": "github",
|
||||||
|
"repoHost": "https://github.com",
|
||||||
|
"skipCi": true
|
||||||
|
}
|
||||||
26
.github/ISSUE_TEMPLATE/alpha_bug_report.yml
vendored
Normal file
26
.github/ISSUE_TEMPLATE/alpha_bug_report.yml
vendored
Normal file
@@ -0,0 +1,26 @@
|
|||||||
|
name: "[Alpha Only] Bug Report"
|
||||||
|
description: CasaOS Alpha Testing specific bug report form.
|
||||||
|
title: "[Alpha][Bug] "
|
||||||
|
labels: ["alpha", "bug"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
Thanks for taking the time to fill out this bug report!
|
||||||
|
> If you haven't joined CasaOS Alpha Team yet.
|
||||||
|
> Please join first on [Discord](https://discord.gg/knqAbbBbeX) to be updated on the Alpha test plan and test scope.
|
||||||
|
- type: textarea
|
||||||
|
id: what-happened
|
||||||
|
attributes:
|
||||||
|
label: What happened?
|
||||||
|
description: Also tell us, what did you expect to happen?
|
||||||
|
placeholder: Tell us what you see!
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
- type: textarea
|
||||||
|
id: screenshots
|
||||||
|
attributes:
|
||||||
|
label: Screenshots
|
||||||
|
description: If applicable, add screenshots to help explain your problem.
|
||||||
|
placeholder: Screenshots would be very helpful!
|
||||||
|
|
||||||
53
.github/ISSUE_TEMPLATE/app_request.yml
vendored
Normal file
53
.github/ISSUE_TEMPLATE/app_request.yml
vendored
Normal file
@@ -0,0 +1,53 @@
|
|||||||
|
name: "App Request"
|
||||||
|
description: "Request to add an app to the app store."
|
||||||
|
title: "[App Request] AppName"
|
||||||
|
labels: ["App Request"]
|
||||||
|
body:
|
||||||
|
- type: markdown
|
||||||
|
attributes:
|
||||||
|
value: |
|
||||||
|
### ❤ Thanks for taking the time to fill out this app request!
|
||||||
|
> Before proceeding, please make sure that this app is not in App Store and no one has [requested](https://github.com/IceWhaleTech/CasaOS/labels/App%20Request) the same app before.
|
||||||
|
> If you have already requested the app, please ask your friends to help add a 👍 to this issue. Then be patient and wait for the developers to work on it.
|
||||||
|
> If you have any questions, please ask them on [Discord](https://discord.gg/knqAbbBbeX) or [Github Discussions](https://github.com/IceWhaleTech/CasaOS/discussions).
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: app-info
|
||||||
|
attributes:
|
||||||
|
label: "App Information"
|
||||||
|
description: "The formal information of this app, as detailed as possible."
|
||||||
|
value: |
|
||||||
|
- Name: <!-- eg. Nextcloud -->
|
||||||
|
- Short Description: <!-- eg. Personal cloud and file sharing solution -->
|
||||||
|
- Official Website: <!-- If available. eg. https://nextcloud.com -->
|
||||||
|
- GitHub Repository: <!-- If available. eg. https://github.com/nextcloud/server -->
|
||||||
|
- Docker Image: <!-- If available. eg. nextcloud/server:latest, ghcr.io/nextcloud/server:latest -->
|
||||||
|
validations:
|
||||||
|
required: true
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: why
|
||||||
|
attributes:
|
||||||
|
label: "Why do you want this app?"
|
||||||
|
description: "Detailed notes can help developers and others understand the importance of this app."
|
||||||
|
placeholder: |
|
||||||
|
As a [what role], it helps me solve [what problem], and especially [what function] is great!
|
||||||
|
or
|
||||||
|
It solves [what problem] and especially [what feature] works well, which is hard to do with other app.
|
||||||
|
or
|
||||||
|
This is the app that [some device/service] must use and will not work without it.
|
||||||
|
or
|
||||||
|
others
|
||||||
|
|
||||||
|
- type: textarea
|
||||||
|
id: additional-info
|
||||||
|
attributes:
|
||||||
|
label: "Additional information?"
|
||||||
|
description: "Anything else you want to share with the developers and others?"
|
||||||
|
placeholder: |
|
||||||
|
Example:
|
||||||
|
- Noteworthy matters.
|
||||||
|
- Recommended Docker image.
|
||||||
|
- Validated Docker deployment instructions.
|
||||||
|
- Notable Docker setup details.
|
||||||
|
- Recommended config files, user data, accessible directory settings.
|
||||||
18
.github/ISSUE_TEMPLATE/bug_report.md
vendored
18
.github/ISSUE_TEMPLATE/bug_report.md
vendored
@@ -1,8 +1,8 @@
|
|||||||
---
|
---
|
||||||
name: Bug report
|
name: Bug report
|
||||||
about: Create a report to help us improve
|
about: Create a report to help us improve
|
||||||
title: ''
|
title: '[Bug] '
|
||||||
labels: ''
|
labels: 'bug'
|
||||||
assignees: ''
|
assignees: ''
|
||||||
|
|
||||||
---
|
---
|
||||||
@@ -28,5 +28,19 @@ If applicable, add screenshots to help explain your problem.
|
|||||||
- Browser [e.g. chrome, safari]
|
- Browser [e.g. chrome, safari]
|
||||||
- Version [e.g. 22]
|
- Version [e.g. 22]
|
||||||
|
|
||||||
|
**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.service
|
||||||
|
```
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
**Additional context**
|
**Additional context**
|
||||||
Add any other context about the problem here.
|
Add any other context about the problem here.
|
||||||
|
|||||||
8
.github/ISSUE_TEMPLATE/config.yml
vendored
8
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +1,11 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
- name: Questions, Ideas, Discussions
|
- name: Feature/Enhancement Ideas
|
||||||
|
url: https://github.com/IceWhaleTech/CasaOS/discussions/164
|
||||||
|
about: Have an idea for a new feature/enhancement?
|
||||||
|
- name: Questions, Discussions
|
||||||
url: https://github.com/IceWhaleTech/CasaOS/discussions
|
url: https://github.com/IceWhaleTech/CasaOS/discussions
|
||||||
about: Ask questions, propose ideas, or discuss anything related to CasaOS
|
about: Ask questions, propose ideas, or discuss anything related to CasaOS
|
||||||
|
- name: Discord
|
||||||
|
url: https://discord.gg/knqAbbBbeX
|
||||||
|
about: Get help or share great ideas on Discord!
|
||||||
23
.github/ISSUE_TEMPLATE/feedback.yml
vendored
Normal file
23
.github/ISSUE_TEMPLATE/feedback.yml
vendored
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
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.
|
||||||
|
|
||||||
33
.github/workflows/add_issues_to_projects.yml
vendored
Normal file
33
.github/workflows/add_issues_to_projects.yml
vendored
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
name: Add Issues To Projects
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
add-issues:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Generate token
|
||||||
|
id: generate_token
|
||||||
|
uses: tibdex/github-app-token@36464acb844fc53b9b8b2401da68844f6b05ebb0
|
||||||
|
with:
|
||||||
|
app_id: ${{ secrets.ALPHA_BOT_ID }}
|
||||||
|
private_key: ${{ secrets.ALPHA_BOT_PEM }}
|
||||||
|
|
||||||
|
- name: Add Alpha Bug Issue To project
|
||||||
|
uses: actions/add-to-project@v0.3.0
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate_token.outputs.token }}
|
||||||
|
project-url: https://github.com/orgs/IceWhaleTech/projects/5
|
||||||
|
labeled: alpha, bug
|
||||||
|
label-operator: AND
|
||||||
|
|
||||||
|
- name: Add App Request Issue To project
|
||||||
|
uses: actions/add-to-project@v0.3.0
|
||||||
|
with:
|
||||||
|
github-token: ${{ steps.generate_token.outputs.token }}
|
||||||
|
project-url: https://github.com/orgs/IceWhaleTech/projects/8
|
||||||
|
labeled: "App Request"
|
||||||
|
label-operator: AND
|
||||||
2
.github/workflows/demo.yml
vendored
2
.github/workflows/demo.yml
vendored
@@ -33,7 +33,7 @@ jobs:
|
|||||||
|
|
||||||
- name: Get old instance and snapshot name, create new instance name
|
- name: Get old instance and snapshot name, create new instance name
|
||||||
run: |
|
run: |
|
||||||
echo "OLD_INSTANCE_SNAPSHOT_NAME=$(aws lightsail get-instance-snapshots | grep '"name": "CasaOS-Demo-Snapshot-1652856810' | sed 's/ //g' | sed 's/"//g' | sed 's/,//g' | sed 's/name://g')" >> $GITHUB_ENV
|
echo "OLD_INSTANCE_SNAPSHOT_NAME=$(aws lightsail get-instance-snapshots | grep '"name": "casaos-0.3.6-1666150291' | 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 "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 "NEW_INSTANCE_NAME=CasaOS-Demo-$(date +%s)" >> $GITHUB_ENV
|
||||||
|
|
||||||
|
|||||||
27
.github/workflows/move_alpha_bug_to_project.yml
vendored
Normal file
27
.github/workflows/move_alpha_bug_to_project.yml
vendored
Normal file
@@ -0,0 +1,27 @@
|
|||||||
|
# This is a basic workflow to help you get started with Actions
|
||||||
|
|
||||||
|
name: Move alpha bug to project
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
track_issue:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Generate token
|
||||||
|
id: generate_token
|
||||||
|
uses: tibdex/github-app-token@36464acb844fc53b9b8b2401da68844f6b05ebb0
|
||||||
|
with:
|
||||||
|
app_id: ${{ secrets.ALPHA_BOT_ID }}
|
||||||
|
private_key: ${{ secrets.ALPHA_BOT_PEM }}
|
||||||
|
|
||||||
|
- name: Add Issue To GitHub Projects Beta
|
||||||
|
uses: actions/add-to-project@v0.1.0
|
||||||
|
with:
|
||||||
|
project-url: https://github.com/orgs/IceWhaleTech/projects/5
|
||||||
|
github-token: ${{ steps.generate_token.outputs.token }}
|
||||||
|
labeled: alpha, bug
|
||||||
|
label-operator: AND
|
||||||
48
.github/workflows/push_events_to_discord.yml
vendored
Normal file
48
.github/workflows/push_events_to_discord.yml
vendored
Normal file
@@ -0,0 +1,48 @@
|
|||||||
|
name: Push Events to Discord
|
||||||
|
|
||||||
|
on:
|
||||||
|
issues:
|
||||||
|
types:
|
||||||
|
- opened
|
||||||
|
issue_comment:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
|
discussion:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
|
- transferred
|
||||||
|
- answered
|
||||||
|
discussion_comment:
|
||||||
|
types:
|
||||||
|
- created
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
push-events:
|
||||||
|
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
|
||||||
|
steps:
|
||||||
|
|
||||||
|
- name: General Discussions & Comments
|
||||||
|
if: ${{ ( github.event_name == 'discussion' || github.event_name == 'discussion_comment' ) && github.event.discussion.category.name == 'General' }}
|
||||||
|
uses: joseph-montanez/forward-event-action@v3.0.0
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.Discord_CasaOS_General_Webhook }}
|
||||||
|
|
||||||
|
- name: App Request Issues & Comments
|
||||||
|
if: ${{ ( github.event_name == 'issues' || github.event_name == 'issue_comment' ) && contains(github.event.issue.labels.*.name, 'App Request') }}
|
||||||
|
uses: joseph-montanez/forward-event-action@v3.0.0
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.Discord_CasaOS_App_Request_Webhook }}
|
||||||
|
|
||||||
|
- name: Bug Issues & Comments
|
||||||
|
if: ${{ ( github.event_name == 'issues' || github.event_name == 'issue_comment' ) && contains(github.event.issue.labels.*.name, 'bug') && !contains(github.event.issue.labels.*.name, 'alpha') }}
|
||||||
|
uses: joseph-montanez/forward-event-action@v3.0.0
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.Discord_CasaOS_Bug_Webhook }}
|
||||||
|
|
||||||
|
- name: Alpha Issues & Comments
|
||||||
|
if: ${{ ( github.event_name == 'issues' || github.event_name == 'issue_comment' ) && contains(github.event.issue.labels.*.name, 'alpha') }}
|
||||||
|
uses: joseph-montanez/forward-event-action@v3.0.0
|
||||||
|
with:
|
||||||
|
webhook: ${{ secrets.Discord_CasaOS_Alpha_Webhook }}
|
||||||
71
.github/workflows/release.yml
vendored
Normal file
71
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,71 @@
|
|||||||
|
name: goreleaser
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- v*.*.*
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Install dependencies for cross-compiling
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt-get --no-install-recommends --yes install \
|
||||||
|
libc6-dev-amd64-cross \
|
||||||
|
gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
|
||||||
|
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
-
|
||||||
|
name: Fetch all tags
|
||||||
|
run: git fetch --force --tags
|
||||||
|
|
||||||
|
- name: Get version
|
||||||
|
id: get_version
|
||||||
|
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
|
||||||
|
-
|
||||||
|
name: Set up Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.19
|
||||||
|
-
|
||||||
|
name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v2
|
||||||
|
with:
|
||||||
|
# either 'goreleaser' (default) or 'goreleaser-pro'
|
||||||
|
distribution: goreleaser
|
||||||
|
version: latest
|
||||||
|
args: release --rm-dist
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
|
||||||
|
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
||||||
|
|
||||||
|
- name: Upload to oss
|
||||||
|
id: upload_to_oss
|
||||||
|
uses: tvrcgo/upload-to-oss@master
|
||||||
|
with:
|
||||||
|
key-id: ${{ secrets.OSS_KEY_ID }}
|
||||||
|
key-secret: ${{ secrets.OSS_KEY_SECRET }}
|
||||||
|
region: oss-cn-shanghai
|
||||||
|
bucket: casaos
|
||||||
|
assets: |
|
||||||
|
dist/checksums.txt:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/checksums.txt
|
||||||
|
dist/linux-arm-7-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm-7-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
dist/linux-arm64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
dist/linux-amd64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-amd64-casaos-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
dist/linux-arm-7-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm-7-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
dist/linux-arm64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
dist/linux-amd64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-amd64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -28,12 +28,15 @@ gen
|
|||||||
/sql/
|
/sql/
|
||||||
/out/
|
/out/
|
||||||
/db/
|
/db/
|
||||||
/docs/
|
|
||||||
/web/
|
|
||||||
/conf/conf.ini
|
/conf/conf.ini
|
||||||
/conf/conf.conf
|
/conf/conf.conf
|
||||||
/conf/conf.json
|
/conf/conf.json
|
||||||
__debug_bin
|
__debug_bin
|
||||||
main
|
main
|
||||||
CasaOS
|
|
||||||
github.com
|
github.com
|
||||||
|
.all-contributorsrc
|
||||||
|
dist
|
||||||
|
CasaOS
|
||||||
|
|
||||||
|
# System Files
|
||||||
|
.DS_Store
|
||||||
|
|||||||
167
.goreleaser.debug.yaml
Normal file
167
.goreleaser.debug.yaml
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||||
|
# Make sure to check the documentation at https://goreleaser.com
|
||||||
|
project_name: casaos
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
# You may remove this if you don't use go modules.
|
||||||
|
- go mod tidy
|
||||||
|
builds:
|
||||||
|
- id: casaos-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-migration-tool-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- id: casaos-migration-tool-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
- id: casaos-migration-tool-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
archives:
|
||||||
|
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .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 }}"
|
||||||
|
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:
|
||||||
|
name_template: "checksums.txt"
|
||||||
|
snapshot:
|
||||||
|
name_template: "{{ incpatch .Version }}"
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- "^docs:"
|
||||||
|
- "^test:"
|
||||||
|
# release:
|
||||||
|
# github:
|
||||||
|
# owner: IceWhaleTech
|
||||||
|
# name: CasaOS
|
||||||
|
# draft: true
|
||||||
|
# prerelease: auto
|
||||||
|
# mode: replace
|
||||||
|
# name_template: "v{{ .Version }}"
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: IceWhaleTech
|
||||||
|
name: CasaOS
|
||||||
|
draft: true
|
||||||
|
prerelease: auto
|
||||||
|
mode: replace
|
||||||
|
name_template: "v{{ .Version }}"
|
||||||
167
.goreleaser.yaml
Normal file
167
.goreleaser.yaml
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||||
|
# Make sure to check the documentation at https://goreleaser.com
|
||||||
|
project_name: casaos
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
# You may remove this if you don't use go modules.
|
||||||
|
- go mod tidy
|
||||||
|
builds:
|
||||||
|
- id: casaos-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-migration-tool-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- id: casaos-migration-tool-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
- id: casaos-migration-tool-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
- osusergo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
archives:
|
||||||
|
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .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 }}"
|
||||||
|
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:
|
||||||
|
name_template: "checksums.txt"
|
||||||
|
snapshot:
|
||||||
|
name_template: "{{ incpatch .Version }}"
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- "^docs:"
|
||||||
|
- "^test:"
|
||||||
|
# release:
|
||||||
|
# github:
|
||||||
|
# owner: IceWhaleTech
|
||||||
|
# name: CasaOS
|
||||||
|
# draft: true
|
||||||
|
# prerelease: auto
|
||||||
|
# mode: replace
|
||||||
|
# name_template: "v{{ .Version }}"
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: IceWhaleTech
|
||||||
|
name: CasaOS
|
||||||
|
draft: true
|
||||||
|
prerelease: auto
|
||||||
|
mode: replace
|
||||||
|
name_template: "v{{ .Version }}"
|
||||||
120
CHANGELOG.md
120
CHANGELOG.md
@@ -16,9 +16,127 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
|
## [0.4.0 - alpha]
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- [Developer] Included `casaos-cli` command tool for debugging
|
||||||
|
- [Developer] Added message bus for events and actions - Use `casaos-cli message-bus` to manage.
|
||||||
|
- [Disk] Disk notification in Dashboard
|
||||||
|
- [System] Restart/shutdown directly from CasaOS Dashboard
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- [General] CasaOS new logo!
|
||||||
|
- [App] Redesign of Featured App
|
||||||
|
- [App] Now you can choose to delete userdata along with app uninstallation
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- [System] Fixed a shell injection issue for better security
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
## [0.3.3-pre] - 2022-07-01(UTC)
|
- [System] Re-instate default zone0 for CPU Temp ([#694](https://github.com/IceWhaleTech/CasaOS/issues/694))
|
||||||
|
- [Disk] Fixed storage name with extra `-1` after rebooting ([#698](https://github.com/IceWhaleTech/CasaOS/issues/698))
|
||||||
|
- [Disk] Fixed disk check so it does not impact disk going into idle ([#704](https://github.com/IceWhaleTech/CasaOS/issues/704))
|
||||||
|
|
||||||
|
## [0.3.8] 2022-11-21
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- [System] Add system announcement
|
||||||
|
- [App] Allow to turn off the display of "Existing Docker Apps" in the settings.
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- [System] Improve the feedback function, you can submit feedback in the bottom right corner of WebUI.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- [System] Fix CPU Temp for other platforms ([#661](https://github.com/IceWhaleTech/CasaOS/issues/661))
|
||||||
|
|
||||||
|
## [0.3.7.1] 2022-11-04
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fix memory leak issue ([#658](https://github.com/IceWhaleTech/CasaOS/issues/658)[#646](https://github.com/IceWhaleTech/CasaOS/issues/646))
|
||||||
|
- Solve the problem of local application import failure ([#490](https://github.com/IceWhaleTech/CasaOS/issues/490))
|
||||||
|
|
||||||
|
## [0.3.7] 2022-10-28
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- [Storage] Disk merge (Beta), you can merge multiple disks into a single storage space (currently you need to enable this feature from the command line)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- [Files] Changed the cache file storage location, now the file upload size is not limited by the system disk capacity.
|
||||||
|
- [Scripts] Updated installation and upgrade scripts to support more Debian-based Linux distributions.
|
||||||
|
- [Engineering] Refactored Local Storage into a standalone service as part of CasaOS modularization.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- [Apps] App list update mechanism improved, now you can see the latest apps in App Store immediately.
|
||||||
|
- [Storage] Fixed a lot of known issues
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- [Storage] Disk merge (Beta), you can merge multiple disks into a single storage space (currently you need to enable this feature from the command line)
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- [Files] Changed the cache file storage location, now the file upload size is not limited by the system disk capacity.
|
||||||
|
- [Scripts] Updated installation and upgrade scripts to support more Debian-based Linux distributions.
|
||||||
|
- [Engineering] Refactored Local Storage into a standalone service as part of CasaOS modularization.
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- [Apps] App list update mechanism improved, now you can see the latest apps in App Store immediately.
|
||||||
|
- [Storage] Fixed a lot of known issues
|
||||||
|
|
||||||
|
|
||||||
|
## [0.3.6] - 2022-09-06
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- [System] Added power and temperature info to performance widget (Intel)
|
||||||
|
- [Apps] Custom links can be added to Apps section
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- [Apps] Fixed the problem of not being able to modify some App settings ([#510](https://github.com/IceWhaleTech/CasaOS/issues/510))
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- [System] Architecture optimization. Improved performance.
|
||||||
|
|
||||||
|
## [0.3.5] - 2022-08-23
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- [File] Mount the shared samba
|
||||||
|
- [File] File sharing via Samba
|
||||||
|
- [System] You can share casaos on Twitter, facebook, reddit
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- [Disk] Support for mounting existing data disks
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- [App] fixed uninstalling imported docker container apps results in wiping ALL your config data from them ([#360](https://github.com/IceWhaleTech/CasaOS/issues/360))
|
||||||
|
|
||||||
|
## [0.3.4] - 2022-07-29(UTC)
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- SSH adds port-side options and prompts for connection status. ([#286](https://github.com/IceWhaleTech/CasaOS/issues/286))
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- Normalize all routes
|
||||||
|
- Application names now support spaces ([#211](https://github.com/IceWhaleTech/CasaOS/issues/211))
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
- Removed casaos connect
|
||||||
|
|
||||||
|
### Security
|
||||||
|
|
||||||
|
- Adjustment of authentication method
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- Fixed storage format and remove password error issues ([#344](https://github.com/IceWhaleTech/CasaOS/issues/344) [#357](https://github.com/IceWhaleTech/CasaOS/issues/357))
|
||||||
|
|
||||||
|
## [0.3.3] - 2022-07-08(UTC)
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|||||||
230
README.md
230
README.md
@@ -1,72 +1,151 @@
|
|||||||
# CasaOS - A simple, easy-to-use, elegant open-source Home Cloud system.
|
# CasaOS - Your Home Cloud OS
|
||||||
|
|
||||||

|
|
||||||
|
|
||||||
[](https://github.com/IceWhaleTech/CasaOS)
|
<!-- Readme i18n links -->
|
||||||
[](https://github.com/IceWhaleTech/CasaOS/pulls)
|
<!-- > English | [中文](#) | [Français](#) -->
|
||||||
[](https://github.com/IceWhaleTech/CasaOS/issues)
|
|
||||||
[](https://github.com/IceWhaleTech/CasaOS/stargazers)
|
|
||||||
[](https://discord.gg/knqAbbBbeX)
|
|
||||||
|
|
||||||
CasaOS is an open-source Home Cloud system based on the Docker ecosystem and designed for home scenarios. It is committed to building the world's most simple, easy-to-use, and elegant Home Cloud system.
|
<p align="center">
|
||||||
|
<!-- CasaOS Banner -->
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="https://raw.githubusercontent.com/IceWhaleTech/logo/main/casaos/casaos_banner_dark_night_800px.png">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="https://raw.githubusercontent.com/IceWhaleTech/logo/main/casaos/casaos_banner_twilight_blue_800px.png">
|
||||||
|
<img alt="CasaOS" src="https://raw.githubusercontent.com/IceWhaleTech/logo/main/casaos/casaos_banner_twilight_blue_800px.png">
|
||||||
|
</picture>
|
||||||
|
<br/>
|
||||||
|
<i>Connect with the community developing HOME CLOUD, creating self-sovereign, and defining the future of the distributed cloud.</i>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<!-- CasaOS Badges -->
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS" target="_blank">
|
||||||
|
<img alt="CasaOS Version" src="https://img.shields.io/github/v/release/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=CasaOS" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS/blob/main/LICENSE" target="_blank">
|
||||||
|
<img alt="CasaOS License" src="https://img.shields.io/github/license/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=License" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS/pulls" target="_blank">
|
||||||
|
<img alt="CasaOS Pull Requests" src="https://img.shields.io/github/issues-pr/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=PRs" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS/issues" target="_blank">
|
||||||
|
<img alt="CasaOS Issues" src="https://img.shields.io/github/issues/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=Issues" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS/stargazers" target="_blank">
|
||||||
|
<img alt="CasaOS Stargazers" src="https://img.shields.io/github/stars/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=Stars" />
|
||||||
|
</a>
|
||||||
|
<!-- <a href="https://github.com/IceWhaleTech/CasaOS/releases" target="_blank">
|
||||||
|
<img alt="CasaOS Downloads" src="https://img.shields.io/github/downloads/IceWhaleTech/CasaOS/total?color=162453&style=flat-square" />
|
||||||
|
</a> -->
|
||||||
|
<br/>
|
||||||
|
<!-- CasaOS Community -->
|
||||||
|
<a href="https://discord.gg/knqAbbBbeX" target="_blank">
|
||||||
|
<img alt="IceWhale Discord" src="https://img.shields.io/discord/884667213326463016?color=162453&style=flat-square&label=Discord&logo=discord&logoColor=fff" />
|
||||||
|
</a>
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS/discussions" target="_blank">
|
||||||
|
<img alt="CasaOS GitHub Discussions" src="https://img.shields.io/github/discussions/IceWhaleTech/CasaOS?color=162453&style=flat-square&label=Discussions&logo=github" />
|
||||||
|
</a>
|
||||||
|
<!-- ALL-CONTRIBUTORS-BADGE:START - Do not remove or modify this section -->
|
||||||
|
<a href="#credits"><img alt="All Contributors" src="https://img.shields.io/static/v1?label=All%20Contributors&message=15&color=162453&style=flat-square&logo=Handshake&logoColor=fff" /></a>
|
||||||
|
<!-- ALL-CONTRIBUTORS-BADGE:END -->
|
||||||
|
<br/>
|
||||||
|
<!-- CasaOS Links -->
|
||||||
|
<a href="https://www.casaos.io" target="_blank">Website</a> |
|
||||||
|
<a href="http://demo.casaos.io" target="_blank">Demo</a> |
|
||||||
|
<a href="https://github.com/IceWhaleTech/CasaOS" target="_blank">GitHub</a>
|
||||||
|
<br/>
|
||||||
|
<br/>
|
||||||
|
<!-- CasaOS Snapshots -->
|
||||||
|
<kbd>
|
||||||
|
<picture>
|
||||||
|
<source media="(prefers-color-scheme: dark)" srcset="snapshot-dark.jpg">
|
||||||
|
<source media="(prefers-color-scheme: light)" srcset="snapshot-light.jpg">
|
||||||
|
<img alt="CasaOS Snapshot" src="snapshot-light.jpg">
|
||||||
|
</picture>
|
||||||
|
</kbd>
|
||||||
|
</p>
|
||||||
|
|
||||||
IceWhale team believes that through community-driven collaborative innovation and open communication with global developers, we can reshape the digital home experience like never before.
|
## Why do we need Home Cloud?
|
||||||
|
|
||||||

|
Think about it seriously. Is control of our data, smart devices and digital assets now only in the hands of some big company?
|
||||||

|
|
||||||
|
- 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?
|
||||||
|
|
||||||
|
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.
|
||||||
|
|
||||||
|
> If you think what we are doing is valuable. Please **give us a star ⭐** and **fork it 🤞**!
|
||||||
|
|
||||||
|
## Features
|
||||||
|
|
||||||
|
- Friendly UI designed for home scenarios
|
||||||
|
- No code, no forms, intuitive, design for humanity
|
||||||
|
- Multiple hardware and base system support
|
||||||
|
- ZimaBoard, NUC, RPi, old computers, whatever is available.
|
||||||
|
- Selected apps in the app store, one-click installation
|
||||||
|
- Nextcloud, HomeAssiant, AdGuard, Jellyfin, *arr and more!
|
||||||
|
- Easily install numerous Docker apps
|
||||||
|
- Over 100,000 apps from the Docker ecosystem can be easily installed
|
||||||
|
- Elegant drive and file management
|
||||||
|
- What you see is what you get. No technical background required.
|
||||||
|
- Well-designed system/app widgets
|
||||||
|
- What you care about, at a glance. Resource usage, app status, and more!
|
||||||
|
|
||||||
## Getting Started
|
## Getting Started
|
||||||
|
|
||||||
> ⚠️ Note:
|
CasaOS fully supports ZimaBoard, Intel NUC, and Raspberry Pi. Also, more computers and development boards and fully compatible with Ubuntu, Debian, Raspberry Pi OS, and CentOS with one-liner installation.
|
||||||
>
|
|
||||||
> CasaOS is still in the early development stage and may vary significantly with the final release. Feel free to test run and share your feedback in the [Discord server](https://discord.gg/knqAbbBbeX)!
|
### Hardware Compatibility
|
||||||
|
|
||||||
|
- amd64 / x86-64
|
||||||
|
- arm64
|
||||||
|
- armv7
|
||||||
|
|
||||||
|
### System Compatibility
|
||||||
|
|
||||||
|
Official Support
|
||||||
|
- Debian 11 (✅ Tested, Recommended)
|
||||||
|
- Ubuntu Server 20.04 (✅ Tested)
|
||||||
|
- Raspberry Pi OS (✅ Tested)
|
||||||
|
|
||||||
|
Community Support
|
||||||
|
- Elementary 6.1 (✅ Tested)
|
||||||
|
- Armbian 22.04 (✅ Tested)
|
||||||
|
- Alpine (🚧 Not Fully Tested Yet)
|
||||||
|
- OpenWrt (🚧 Not Fully Tested Yet)
|
||||||
|
- ArchLinux (🚧 Not Fully Tested Yet)
|
||||||
|
|
||||||
### Quick Setup CasaOS
|
### Quick Setup CasaOS
|
||||||
|
|
||||||
Fresh install a system from the list below and run the this command:
|
Freshly install a system from the list above and run this command:
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
wget -qO- https://get.icewhale.io/casaos.sh | bash
|
wget -qO- https://get.casaos.io | sudo bash
|
||||||
```
|
```
|
||||||
|
|
||||||
or
|
or
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -fsSL https://get.icewhale.io/casaos.sh | bash
|
curl -fsSL https://get.casaos.io | sudo bash
|
||||||
```
|
```
|
||||||
|
|
||||||
### Uninstall CasaOS
|
### Uninstall CasaOS
|
||||||
|
|
||||||
|
|
||||||
|
v0.3.3 or newer
|
||||||
|
|
||||||
```sh
|
```sh
|
||||||
curl -fsSL https://get.icewhale.io/casaos-uninstall.sh | bash
|
casaos-uninstall
|
||||||
```
|
```
|
||||||
|
|
||||||
### System Compatibility
|
Before v0.3.3
|
||||||
|
|
||||||
- Ubuntu Server 20.04 amd64 (✅ Recommend, Tested)
|
```sh
|
||||||
- Armbian 22.02 armhf/arm64/amd64 (✅ Recommend, Tested)
|
curl -fsSL https://get.icewhale.io/casaos-uninstall.sh | sudo bash
|
||||||
- Elementary OS 6.1 Jólnir amd64 (✅ Recommend, Tested)
|
```
|
||||||
- Deepin 20.4 amd64 (⚠️ Not Fully Tested Yet)
|
|
||||||
- Raspberry Pi Lite OS aarch64/arm64 (⚠️ Not Fully Tested Yet)
|
|
||||||
- Debian 11 amd64 (⚠️ Not Fully Tested Yet)
|
|
||||||
- OpenWrt 21.02 amd64 (⚠️ Not Fully Tested Yet)
|
|
||||||
- OpenWrt 21.02 aarch64/arm64 (⚠️ Not Fully Tested Yet)
|
|
||||||
|
|
||||||
|
## Community
|
||||||
## Key Features
|
|
||||||
|
|
||||||
- UI designed for home scenarios - simple, elegant, and easy-to-use
|
|
||||||
- Quick Docker app installation with only three steps, plus automatic management
|
|
||||||
- App Store for Home Cloud 🚧
|
|
||||||
- Home data/digital asset management 🚧
|
|
||||||
- Smart home manager 🚧
|
|
||||||
|
|
||||||
🚧 is under development.
|
|
||||||
|
|
||||||
We are actively moving forward with development, and you are more than welcome to share any idea with us!
|
|
||||||
|
|
||||||
|
|
||||||
## Community
|
|
||||||
|
|
||||||
The word Casa comes from the Spanish word for "home". Project CasaOS originated as a pre-installed system for crowdfunded product [ZimaBoard](https://www.zimaboard.com) on Kickstarter.
|
The word Casa comes from the Spanish word for "home". Project CasaOS originated as a pre-installed system for crowdfunded product [ZimaBoard](https://www.zimaboard.com) on Kickstarter.
|
||||||
|
|
||||||
@@ -74,16 +153,67 @@ After looking at many systems and software on the market, the team found no serv
|
|||||||
|
|
||||||
So, we set out to build this open source project to develop CasaOS with our own hands, everyone in the community, and you.
|
So, we set out to build this open source project to develop CasaOS with our own hands, everyone in the community, and you.
|
||||||
|
|
||||||
> A warm welcome for you to share and discuss your great ideas in the [Discord server](https://discord.gg/knqAbbBbeX)!
|
We believes that through community-driven collaborative innovation and open communication with global developers, we can reshape the digital home experience like never before.
|
||||||
|
|
||||||
|
**A warm welcome for you to get help or share great ideas in the [Discord](https://discord.gg/knqAbbBbeX)!**
|
||||||
|
|
||||||
[](https://discord.gg/knqAbbBbeX)
|
[](https://discord.gg/knqAbbBbeX)
|
||||||
|
|
||||||
|
## Contributing
|
||||||
|
|
||||||
|
CasaOS is a community-driven open source project and the people involved are CasaOS users. That means CasaOS will always need contributions from community members just like you!
|
||||||
|
|
||||||
## Maintainers
|
- See <https://wiki.casaos.io/en/contribute> for ways of contribution to CasaOS
|
||||||
- Jerry Liu
|
- See <https://wiki.casaos.io/en/contribute/development> if you want to be involved in code contribution specificially
|
||||||
- Link Liang
|
|
||||||
- Ober Zhang
|
## Credits
|
||||||
- Zyaire Ann
|
|
||||||
- John Guan
|
Many thanks to everyone who has helped CasaOS so far!
|
||||||
- Right here, waiting for YOU!
|
|
||||||
|
Everyone's contribution is greatly appreciated. ([Emoji Key](https://allcontributors.org/docs/en/emoji-key))
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:START - Do not remove or modify this section -->
|
||||||
|
<!-- prettier-ignore-start -->
|
||||||
|
<!-- markdownlint-disable -->
|
||||||
|
<table>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://github.com/jerrykuku"><img src="https://avatars.githubusercontent.com/u/9485680?v=4?s=100" width="100px;" alt=""/><br /><sub><b>老竭力</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=jerrykuku" title="Code">💻</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=jerrykuku" title="Documentation">📖</a> <a href="#ideas-jerrykuku" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-jerrykuku" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-jerrykuku" title="Maintenance">🚧</a> <a href="#platform-jerrykuku" title="Packaging/porting to new platform">📦</a> <a href="#question-jerrykuku" title="Answering Questions">💬</a> <a href="https://github.com/IceWhaleTech/CasaOS/pulls?q=is%3Apr+reviewed-by%3Ajerrykuku" title="Reviewed Pull Requests">👀</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/LinkLeong"><img src="https://avatars.githubusercontent.com/u/13556972?v=4?s=100" width="100px;" alt=""/><br /><sub><b>link</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=LinkLeong" title="Code">💻</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=LinkLeong" title="Documentation">📖</a> <a href="#ideas-LinkLeong" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-LinkLeong" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-LinkLeong" title="Maintenance">🚧</a> <a href="#question-LinkLeong" title="Answering Questions">💬</a> <a href="https://github.com/IceWhaleTech/CasaOS/pulls?q=is%3Apr+reviewed-by%3ALinkLeong" title="Reviewed Pull Requests">👀</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/tigerinus"><img src="https://avatars.githubusercontent.com/u/7172560?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Tiger Wang (王豫)</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=tigerinus" title="Code">💻</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=tigerinus" title="Documentation">📖</a> <a href="#ideas-tigerinus" title="Ideas, Planning, & Feedback">🤔</a> <a href="#infra-tigerinus" title="Infrastructure (Hosting, Build-Tools, etc)">🚇</a> <a href="#maintenance-tigerinus" title="Maintenance">🚧</a> <a href="#mentoring-tigerinus" title="Mentoring">🧑🏫</a> <a href="#security-tigerinus" title="Security">🛡️</a> <a href="#question-tigerinus" title="Answering Questions">💬</a> <a href="https://github.com/IceWhaleTech/CasaOS/pulls?q=is%3Apr+reviewed-by%3Atigerinus" title="Reviewed Pull Requests">👀</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/Lauren-ED209"><img src="https://avatars.githubusercontent.com/u/8243355?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Lauren</b></sub></a><br /><a href="#ideas-Lauren-ED209" title="Ideas, Planning, & Feedback">🤔</a> <a href="#fundingFinding-Lauren-ED209" title="Funding Finding">🔍</a> <a href="#projectManagement-Lauren-ED209" title="Project Management">📆</a> <a href="#question-Lauren-ED209" title="Answering Questions">💬</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=Lauren-ED209" title="Tests">⚠️</a></td>
|
||||||
|
<td align="center"><a href="https://JohnGuan.Cn"><img src="https://avatars.githubusercontent.com/u/3358477?v=4?s=100" width="100px;" alt=""/><br /><sub><b>John Guan</b></sub></a><br /><a href="#blog-JohnGuan" title="Blogposts">📝</a> <a href="#content-JohnGuan" title="Content">🖋</a> <a href="https://github.com/IceWhaleTech/CasaOS/commits?author=JohnGuan" title="Documentation">📖</a> <a href="#ideas-JohnGuan" title="Ideas, Planning, & Feedback">🤔</a> <a href="#eventOrganizing-JohnGuan" title="Event Organizing">📋</a> <a href="#mentoring-JohnGuan" title="Mentoring">🧑🏫</a> <a href="#question-JohnGuan" title="Answering Questions">💬</a> <a href="https://github.com/IceWhaleTech/CasaOS/pulls?q=is%3Apr+reviewed-by%3AJohnGuan" title="Reviewed Pull Requests">👀</a></td>
|
||||||
|
<td align="center"><a href="https://blog.tippybits.com"><img src="https://avatars.githubusercontent.com/u/17506770?v=4?s=100" width="100px;" alt=""/><br /><sub><b>David Tippett</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=dtaivpp" title="Documentation">📖</a> <a href="#ideas-dtaivpp" title="Ideas, Planning, & Feedback">🤔</a> <a href="#question-dtaivpp" title="Answering Questions">💬</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/zarevskaya"><img src="https://avatars.githubusercontent.com/u/60230221?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Skaya</b></sub></a><br /><a href="#mentoring-zarevskaya" title="Mentoring">🧑🏫</a> <a href="#question-zarevskaya" title="Answering Questions">💬</a> <a href="#tutorial-zarevskaya" title="Tutorials">✅</a> <a href="#translation-zarevskaya" title="Translation">🌍</a></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td align="center"><a href="https://github.com/AuthorShin"><img src="https://avatars.githubusercontent.com/u/4959043?v=4?s=100" width="100px;" alt=""/><br /><sub><b>AuthorShin</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=AuthorShin" title="Tests">⚠️</a> <a href="https://github.com/IceWhaleTech/CasaOS/issues?q=author%3AAuthorShin" title="Bug reports">🐛</a> <a href="#question-AuthorShin" title="Answering Questions">💬</a> <a href="#ideas-AuthorShin" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/baptiste313"><img src="https://avatars.githubusercontent.com/u/93325157?v=4?s=100" width="100px;" alt=""/><br /><sub><b>baptiste313</b></sub></a><br /><a href="#translation-baptiste313" title="Translation">🌍</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/DrMxrcy"><img src="https://avatars.githubusercontent.com/u/58747968?v=4?s=100" width="100px;" alt=""/><br /><sub><b>DrMxrcy</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/commits?author=DrMxrcy" title="Tests">⚠️</a> <a href="#ideas-DrMxrcy" title="Ideas, Planning, & Feedback">🤔</a> <a href="#question-DrMxrcy" title="Answering Questions">💬</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/Joooost"><img src="https://avatars.githubusercontent.com/u/12090673?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Joooost</b></sub></a><br /><a href="#ideas-Joooost" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
<td align="center"><a href="https://potyarkin.ml"><img src="https://avatars.githubusercontent.com/u/334908?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Vitaly Potyarkin</b></sub></a><br /><a href="#ideas-sio" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/bearfrieze"><img src="https://avatars.githubusercontent.com/u/1023813?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Bjørn Friese</b></sub></a><br /><a href="#ideas-bearfrieze" title="Ideas, Planning, & Feedback">🤔</a></td>
|
||||||
|
<td align="center"><a href="https://github.com/Protektor-Desura"><img src="https://avatars.githubusercontent.com/u/1195496?v=4?s=100" width="100px;" alt=""/><br /><sub><b>Protektor</b></sub></a><br /><a href="https://github.com/IceWhaleTech/CasaOS/issues?q=author%3AProtektor-Desura" title="Bug reports">🐛</a> <a href="#ideas-Protektor-Desura" title="Ideas, Planning, & Feedback">🤔</a> <a href="#question-Protektor-Desura" title="Answering Questions">💬</a></td>
|
||||||
|
</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>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
|
||||||
|
<!-- markdownlint-restore -->
|
||||||
|
<!-- prettier-ignore-end -->
|
||||||
|
|
||||||
|
<!-- ALL-CONTRIBUTORS-LIST:END -->
|
||||||
|
|
||||||
|
This project follows the [all-contributors](https://github.com/all-contributors/all-contributors) specification. Contributions of any kind welcome!
|
||||||
|
|
||||||
|
## Changelog
|
||||||
|
|
||||||
|
Detailed changes for each release are documented in the [release notes](https://github.com/IceWhaleTech/CasaOS/releases).
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
<p align="center">
|
||||||
|
<a href="https://dashboard.trackgit.com/token/l5q8egi92tfhlxd70l2l">
|
||||||
|
<img src="https://us-central1-trackgit-analytics.cloudfunctions.net/token/ping/l5q8egi92tfhlxd70l2l" alt="trackgit-views" />
|
||||||
|
</a>
|
||||||
|
</p>
|
||||||
|
|||||||
1
UI
1
UI
Submodule UI deleted from 7af1bf549d
41
alpha.md
41
alpha.md
@@ -1,41 +0,0 @@
|
|||||||
<!--
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-06-27 11:37:26
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-07-01 15:51:29
|
|
||||||
* @FilePath: /CasaOS/alpha.md
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
-->
|
|
||||||
|
|
||||||
# alpha Test Description
|
|
||||||
|
|
||||||
## :warning: Warning
|
|
||||||
|
|
||||||
There is a risk of data loss in non-release versions, so please be careful to back up your data.
|
|
||||||
|
|
||||||
## Install/Update
|
|
||||||
|
|
||||||
``` curl -fsSL https://get.casaos.io | bash -s -- -v v0.3.3-alpha ```
|
|
||||||
|
|
||||||
## Check change log
|
|
||||||
|
|
||||||
[CHANGELOG](https://github.com/IceWhaleTech/CasaOS/blob/main/CHANGELOG.md)
|
|
||||||
|
|
||||||
## Check Design drawings
|
|
||||||
|
|
||||||
[Design drawings](https://www.figma.com/file/pvlGobvuWEvbCb3GLqXfim/CasaOS-V0.3.3)
|
|
||||||
|
|
||||||
## Feedback questions
|
|
||||||
|
|
||||||
Go [here]() to give feedback on your question, note that try to match the picture or video
|
|
||||||
|
|
||||||
|
|
||||||
## Retest after update
|
|
||||||
|
|
||||||
Wait for the fix to appear and update and retest, and follow up on the issue
|
|
||||||
|
|
||||||
## Thanks
|
|
||||||
|
|
||||||
Thank you for your great support, we will return your support from time to time.
|
|
||||||
177
build/scripts/migration/script.d/03-migrate-casaos.sh
Normal file
177
build/scripts/migration/script.d/03-migrate-casaos.sh
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# functions
|
||||||
|
__info() {
|
||||||
|
echo -e "🟩 ${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__info_done() {
|
||||||
|
echo -e "✅ ${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__warning() {
|
||||||
|
echo -e "🟨 ${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__error() {
|
||||||
|
echo "🟥 ${1}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
__is_version_gt() {
|
||||||
|
test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"
|
||||||
|
}
|
||||||
|
__normalize_version() {
|
||||||
|
local version
|
||||||
|
if [ "${1::1}" = "v" ]; then
|
||||||
|
version="${1:1}"
|
||||||
|
else
|
||||||
|
version="${1}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$version"
|
||||||
|
}
|
||||||
|
|
||||||
|
__is_migration_needed() {
|
||||||
|
local version1
|
||||||
|
local version2
|
||||||
|
|
||||||
|
version1=$(__normalize_version "${1}")
|
||||||
|
version2=$(__normalize_version "${2}")
|
||||||
|
|
||||||
|
if [ "${version1}" = "${version2}" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "CURRENT_VERSION_NOT_FOUND" = "${version1}" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "LEGACY_WITHOUT_VERSION" = "${version1}" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
__is_version_gt "${version2}" "${version1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
BUILD_PATH=$(dirname "${BASH_SOURCE[0]}")/../../..
|
||||||
|
SOURCE_ROOT=${BUILD_PATH}/sysroot
|
||||||
|
|
||||||
|
APP_NAME="casaos"
|
||||||
|
|
||||||
|
# check if migration is needed
|
||||||
|
SOURCE_BIN_PATH=${SOURCE_ROOT}/usr/bin
|
||||||
|
SOURCE_BIN_FILE=${SOURCE_BIN_PATH}/${APP_NAME}
|
||||||
|
|
||||||
|
CURRENT_BIN_PATH=/usr/bin
|
||||||
|
CURRENT_BIN_PATH_LEGACY=/usr/local/bin
|
||||||
|
CURRENT_BIN_FILE=${CURRENT_BIN_PATH}/${APP_NAME}
|
||||||
|
CURRENT_BIN_FILE_LEGACY=$(realpath -e ${CURRENT_BIN_PATH_LEGACY}/${APP_NAME} || which ${APP_NAME} || echo CURRENT_BIN_FILE_LEGACY_NOT_FOUND)
|
||||||
|
|
||||||
|
SOURCE_VERSION="$(${SOURCE_BIN_FILE} -v)"
|
||||||
|
CURRENT_VERSION="$(${CURRENT_BIN_FILE} -v || ${CURRENT_BIN_FILE_LEGACY} -v || (stat "${CURRENT_BIN_FILE_LEGACY}" > /dev/null && echo LEGACY_WITHOUT_VERSION) || echo CURRENT_VERSION_NOT_FOUND)"
|
||||||
|
|
||||||
|
__info_done "CURRENT_VERSION: ${CURRENT_VERSION}"
|
||||||
|
__info_done "SOURCE_VERSION: ${SOURCE_VERSION}"
|
||||||
|
|
||||||
|
NEED_MIGRATION=$(__is_migration_needed "${CURRENT_VERSION}" "${SOURCE_VERSION}" && echo "true" || echo "false")
|
||||||
|
|
||||||
|
if [ "${NEED_MIGRATION}" = "false" ]; then
|
||||||
|
__info_done "Migration is not needed."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
ARCH="unknown"
|
||||||
|
|
||||||
|
case $(uname -m) in
|
||||||
|
x86_64)
|
||||||
|
ARCH="amd64"
|
||||||
|
;;
|
||||||
|
aarch64)
|
||||||
|
ARCH="arm64"
|
||||||
|
;;
|
||||||
|
armv7l)
|
||||||
|
ARCH="arm-7"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
__error "Unsupported architecture"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
__info "ARCH: ${ARCH}"
|
||||||
|
|
||||||
|
MIGRATION_SERVICE_DIR=${1}
|
||||||
|
|
||||||
|
if [ -z "${MIGRATION_SERVICE_DIR}" ]; then
|
||||||
|
MIGRATION_SERVICE_DIR=${BUILD_PATH}/scripts/migration/service.d/${APP_NAME}
|
||||||
|
fi
|
||||||
|
MIGRATION_LIST_FILE=${MIGRATION_SERVICE_DIR}/migration.list
|
||||||
|
MIGRATION_PATH=()
|
||||||
|
|
||||||
|
CURRENT_VERSION_FOUND="false"
|
||||||
|
|
||||||
|
# a VERSION_PAIR looks like "v0.3.5 <url>"
|
||||||
|
#
|
||||||
|
# - "v0.3.5" is the current version installed on this host
|
||||||
|
# - "<url>" is the url of the migration tool
|
||||||
|
while read -r VERSION_PAIR; do
|
||||||
|
if [ -z "${VERSION_PAIR}" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# obtain "v0.3.5" from "v0.3.5 v0.3.6-alpha2"
|
||||||
|
VER1=$(echo "${VERSION_PAIR}" | cut -d' ' -f1)
|
||||||
|
|
||||||
|
# obtain "<url>" from "v0.3.5 <url>"
|
||||||
|
URL=$(eval echo "${VERSION_PAIR}" | cut -d' ' -f2)
|
||||||
|
|
||||||
|
if [ "${CURRENT_VERSION}" = "${VER1// /}" ] || [ "${CURRENT_VERSION}" = "LEGACY_WITHOUT_VERSION" ]; then
|
||||||
|
CURRENT_VERSION_FOUND="true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${CURRENT_VERSION_FOUND}" = "true" ]; then
|
||||||
|
MIGRATION_PATH+=("${URL// /}")
|
||||||
|
fi
|
||||||
|
done < "${MIGRATION_LIST_FILE}"
|
||||||
|
|
||||||
|
if [ ${#MIGRATION_PATH[@]} -eq 0 ]; then
|
||||||
|
__warning "No migration path found from ${CURRENT_VERSION} to ${SOURCE_VERSION}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
pushd "${MIGRATION_SERVICE_DIR}"
|
||||||
|
|
||||||
|
{ for URL in "${MIGRATION_PATH[@]}"; do
|
||||||
|
MIGRATION_TOOL_FILE=$(basename "${URL}")
|
||||||
|
|
||||||
|
if [ -f "${MIGRATION_TOOL_FILE}" ]; then
|
||||||
|
__info "Migration tool ${MIGRATION_TOOL_FILE} exists. Skip downloading."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
__info "Dowloading ${URL}..."
|
||||||
|
curl -fsSL -o "${MIGRATION_TOOL_FILE}" -O "${URL}"
|
||||||
|
done
|
||||||
|
} || {
|
||||||
|
popd
|
||||||
|
__error "Failed to download migration tools"
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
for URL in "${MIGRATION_PATH[@]}"; do
|
||||||
|
MIGRATION_TOOL_FILE=$(basename "${URL}")
|
||||||
|
__info "Extracting ${MIGRATION_TOOL_FILE}..."
|
||||||
|
tar zxvf "${MIGRATION_TOOL_FILE}" || __error "Failed to extract ${MIGRATION_TOOL_FILE}"
|
||||||
|
|
||||||
|
MIGRATION_TOOL_PATH=build/sysroot/usr/bin/${APP_NAME}-migration-tool
|
||||||
|
__info "Running ${MIGRATION_TOOL_PATH}..."
|
||||||
|
${MIGRATION_TOOL_PATH}
|
||||||
|
done
|
||||||
|
} || {
|
||||||
|
popd
|
||||||
|
__error "Failed to extract and run migration tools"
|
||||||
|
}
|
||||||
|
|
||||||
|
popd
|
||||||
3
build/scripts/migration/service.d/casaos/migration.list
Normal file
3
build/scripts/migration/service.d/casaos/migration.list
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
LEGACY_WITHOUT_VERSION https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
|
v0.3.5 https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
|
v0.3.5.1 https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
54
build/scripts/setup/script.d/03-setup-casaos.sh
Executable file
54
build/scripts/setup/script.d/03-setup-casaos.sh
Executable file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BUILD_PATH=$(dirname "${BASH_SOURCE[0]}")/../../..
|
||||||
|
|
||||||
|
APP_NAME_SHORT=casaos
|
||||||
|
|
||||||
|
__get_setup_script_directory_by_os_release() {
|
||||||
|
pushd "$(dirname "${BASH_SOURCE[0]}")/../service.d/${APP_NAME_SHORT}" >/dev/null
|
||||||
|
|
||||||
|
{
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
{
|
||||||
|
source /etc/os-release
|
||||||
|
{
|
||||||
|
pushd "${ID}"/"${VERSION_CODENAME}" >/dev/null
|
||||||
|
} || {
|
||||||
|
pushd "${ID}" >/dev/null
|
||||||
|
} || {
|
||||||
|
pushd "${ID_LIKE}" >/dev/null
|
||||||
|
} || {
|
||||||
|
echo "Unsupported OS: ${ID} ${VERSION_CODENAME} (${ID_LIKE})"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
pwd
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
|
|
||||||
|
} || {
|
||||||
|
echo "Unsupported OS: unknown"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
SETUP_SCRIPT_DIRECTORY=$(__get_setup_script_directory_by_os_release)
|
||||||
|
SETUP_SCRIPT_FILENAME="setup-${APP_NAME_SHORT}.sh"
|
||||||
|
|
||||||
|
SETUP_SCRIPT_FILEPATH="${SETUP_SCRIPT_DIRECTORY}/${SETUP_SCRIPT_FILENAME}"
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "🟩 Running ${SETUP_SCRIPT_FILENAME}..."
|
||||||
|
$BASH "${SETUP_SCRIPT_FILEPATH}" "${BUILD_PATH}"
|
||||||
|
} || {
|
||||||
|
echo "🟥 ${SETUP_SCRIPT_FILENAME} failed."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "✅ ${SETUP_SCRIPT_FILENAME} finished."
|
||||||
40
build/scripts/setup/service.d/casaos/arch/setup-casaos.sh
Normal file
40
build/scripts/setup/service.d/casaos/arch/setup-casaos.sh
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: LinkLeong link@icewhale.org
|
||||||
|
# @Date: 2022-08-25 11:41:22
|
||||||
|
# @LastEditors: LinkLeong
|
||||||
|
# @LastEditTime: 2022-08-31 17:54:17
|
||||||
|
# @FilePath: /CasaOS/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh
|
||||||
|
# @Description:
|
||||||
|
|
||||||
|
# @Website: https://www.casaos.io
|
||||||
|
# Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
###
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
APP_NAME="casaos"
|
||||||
|
|
||||||
|
# copy config files
|
||||||
|
CONF_PATH=/etc/casaos
|
||||||
|
OLD_CONF_PATH=/etc/casaos.conf
|
||||||
|
CONF_FILE=${CONF_PATH}/${APP_NAME}.conf
|
||||||
|
CONF_FILE_SAMPLE=${CONF_PATH}/${APP_NAME}.conf.sample
|
||||||
|
|
||||||
|
|
||||||
|
if [ -f "${OLD_CONF_PATH}" ]; then
|
||||||
|
echo "copy old conf"
|
||||||
|
cp "${OLD_CONF_PATH}" "${CONF_FILE}"
|
||||||
|
fi
|
||||||
|
if [ ! -f "${CONF_FILE}" ]; then
|
||||||
|
echo "Initializing config file..."
|
||||||
|
cp -v "${CONF_FILE_SAMPLE}" "${CONF_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf /etc/systemd/system/casaos.service # remove old service file
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
# enable service (without starting)
|
||||||
|
echo "Enabling service..."
|
||||||
|
systemctl enable --force --no-ask-password "${APP_NAME}.service"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../setup-casaos.sh
|
||||||
40
build/scripts/setup/service.d/casaos/debian/setup-casaos.sh
Normal file
40
build/scripts/setup/service.d/casaos/debian/setup-casaos.sh
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: LinkLeong link@icewhale.org
|
||||||
|
# @Date: 2022-08-25 11:41:22
|
||||||
|
# @LastEditors: LinkLeong
|
||||||
|
# @LastEditTime: 2022-08-31 17:54:17
|
||||||
|
# @FilePath: /CasaOS/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh
|
||||||
|
# @Description:
|
||||||
|
|
||||||
|
# @Website: https://www.casaos.io
|
||||||
|
# Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
###
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
APP_NAME="casaos"
|
||||||
|
|
||||||
|
# copy config files
|
||||||
|
CONF_PATH=/etc/casaos
|
||||||
|
OLD_CONF_PATH=/etc/casaos.conf
|
||||||
|
CONF_FILE=${CONF_PATH}/${APP_NAME}.conf
|
||||||
|
CONF_FILE_SAMPLE=${CONF_PATH}/${APP_NAME}.conf.sample
|
||||||
|
|
||||||
|
|
||||||
|
if [ -f "${OLD_CONF_PATH}" ]; then
|
||||||
|
echo "copy old conf"
|
||||||
|
cp "${OLD_CONF_PATH}" "${CONF_FILE}"
|
||||||
|
fi
|
||||||
|
if [ ! -f "${CONF_FILE}" ]; then
|
||||||
|
echo "Initializing config file..."
|
||||||
|
cp -v "${CONF_FILE_SAMPLE}" "${CONF_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rf /etc/systemd/system/casaos.service # remove old service file
|
||||||
|
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
# enable service (without starting)
|
||||||
|
echo "Enabling service..."
|
||||||
|
systemctl enable --force --no-ask-password "${APP_NAME}.service"
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../setup-casaos.sh
|
||||||
1
build/scripts/setup/service.d/casaos/ubuntu/setup-casaos.sh
Symbolic link
1
build/scripts/setup/service.d/casaos/ubuntu/setup-casaos.sh
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../debian/setup-casaos.sh
|
||||||
22
build/sysroot/etc/casaos/casaos.conf.sample
Normal file
22
build/sysroot/etc/casaos/casaos.conf.sample
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[app]
|
||||||
|
PAGE_SIZE = 10
|
||||||
|
RuntimeRootPath = runtime/
|
||||||
|
LogPath = /var/log/casaos/
|
||||||
|
LogSaveName = log
|
||||||
|
LogFileExt = log
|
||||||
|
DateStrFormat = 20060102
|
||||||
|
DateTimeFormat = 2006-01-02 15:04:05
|
||||||
|
TimeFormat = 15:04:05
|
||||||
|
DateFormat = 2006-01-02
|
||||||
|
DBPath = /var/lib/casaos
|
||||||
|
ShellPath = /usr/share/casaos/shell
|
||||||
|
UserDataPath = /var/lib/casaos/conf
|
||||||
|
|
||||||
|
[server]
|
||||||
|
RunMode = release
|
||||||
|
ServerApi = https://api.casaos.io/casaos-api
|
||||||
|
Handshake = socket.casaos.io
|
||||||
|
Token =
|
||||||
|
USBAutoMount =
|
||||||
|
|
||||||
|
[system]
|
||||||
13
build/sysroot/usr/lib/systemd/system/casaos.service
Normal file
13
build/sysroot/usr/lib/systemd/system/casaos.service
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
After=casaos-gateway.service
|
||||||
|
ConditionFileNotEmpty=/etc/casaos/casaos.conf
|
||||||
|
Description=CasaOS Main Service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/casaos -c /etc/casaos/casaos.conf
|
||||||
|
PIDFile=/var/run/casaos/casaos.pid
|
||||||
|
Restart=always
|
||||||
|
Type=notify
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -0,0 +1,56 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: LinkLeong link@icewhale.org
|
||||||
|
# @Date: 2022-11-15 15:51:44
|
||||||
|
# @LastEditors: LinkLeong
|
||||||
|
# @LastEditTime: 2022-11-15 15:53:37
|
||||||
|
# @FilePath: /CasaOS/build/sysroot/usr/share/casaos/cleanup/script.d/03-cleanup-casaos.sh
|
||||||
|
# @Description:
|
||||||
|
# @Website: https://www.casaos.io
|
||||||
|
# Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
###
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
readonly APP_NAME_SHORT=casaos
|
||||||
|
|
||||||
|
__get_setup_script_directory_by_os_release() {
|
||||||
|
pushd "$(dirname "${BASH_SOURCE[0]}")/../service.d/${APP_NAME_SHORT}" &>/dev/null
|
||||||
|
|
||||||
|
{
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
{
|
||||||
|
source /etc/os-release
|
||||||
|
{
|
||||||
|
pushd "${ID}"/"${VERSION_CODENAME}" &>/dev/null
|
||||||
|
} || {
|
||||||
|
pushd "${ID}" &>/dev/null
|
||||||
|
} || {
|
||||||
|
pushd "${ID_LIKE}" &>/dev/null
|
||||||
|
} || {
|
||||||
|
echo "Unsupported OS: ${ID} ${VERSION_CODENAME} (${ID_LIKE})"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
pwd
|
||||||
|
|
||||||
|
popd &>/dev/null
|
||||||
|
|
||||||
|
} || {
|
||||||
|
echo "Unsupported OS: unknown"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
popd &>/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
SETUP_SCRIPT_DIRECTORY=$(__get_setup_script_directory_by_os_release)
|
||||||
|
|
||||||
|
readonly SETUP_SCRIPT_DIRECTORY
|
||||||
|
readonly SETUP_SCRIPT_FILENAME="cleanup-${APP_NAME_SHORT}.sh"
|
||||||
|
readonly SETUP_SCRIPT_FILEPATH="${SETUP_SCRIPT_DIRECTORY}/${SETUP_SCRIPT_FILENAME}"
|
||||||
|
|
||||||
|
echo "🟩 Running ${SETUP_SCRIPT_FILENAME}..."
|
||||||
|
$SHELL "${SETUP_SCRIPT_FILEPATH}" "${BUILD_PATH}"
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
readonly CASA_SERVICES=(
|
||||||
|
"casaos.service"
|
||||||
|
"devmon@devmon.service"
|
||||||
|
)
|
||||||
|
|
||||||
|
readonly CASA_EXEC=casaos
|
||||||
|
readonly CASA_CONF=/etc/casaos/casaos.conf
|
||||||
|
readonly CASA_URL=/var/run/casaos/casaos.url
|
||||||
|
readonly CASA_SERVICE_USR=/usr/lib/systemd/system/casaos.service
|
||||||
|
readonly CASA_SERVICE_LIB=/lib/systemd/system/casaos.service
|
||||||
|
readonly CASA_SERVICE_ETC=/etc/systemd/system/casaos.service
|
||||||
|
|
||||||
|
# Old Casa Files
|
||||||
|
readonly CASA_PATH=/casaOS
|
||||||
|
readonly CASA_CONF_PATH_OLD=/etc/casaos.conf
|
||||||
|
|
||||||
|
readonly aCOLOUR=(
|
||||||
|
'\e[38;5;154m' # green | Lines, bullets and separators
|
||||||
|
'\e[1m' # Bold white | Main descriptions
|
||||||
|
'\e[90m' # Grey | Credits
|
||||||
|
'\e[91m' # Red | Update notifications Alert
|
||||||
|
'\e[33m' # Yellow | Emphasis
|
||||||
|
)
|
||||||
|
|
||||||
|
Show() {
|
||||||
|
# OK
|
||||||
|
if (($1 == 0)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# FAILED
|
||||||
|
elif (($1 == 1)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# INFO
|
||||||
|
elif (($1 == 2)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# NOTICE
|
||||||
|
elif (($1 == 3)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Warn() {
|
||||||
|
echo -e "${aCOLOUR[3]}$1$COLOUR_RESET"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap 'onCtrlC' INT
|
||||||
|
onCtrlC() {
|
||||||
|
echo -e "${COLOUR_RESET}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Detecting_CasaOS() {
|
||||||
|
if [[ ! -x "$(command -v ${CASA_EXEC})" ]]; then
|
||||||
|
Show 2 "CasaOS is not detected, exit the script."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
Show 0 "This script will delete the containers you no longer use, and the CasaOS configuration files."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Uninstall_Container() {
|
||||||
|
if [[ ${UNINSTALL_ALL_CONTAINER} == true && "$(docker ps -aq)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting containers."
|
||||||
|
docker stop "$(docker ps -aq)" || Show 1 "Failed to stop all containers."
|
||||||
|
docker rm "$(docker ps -aq)" || Show 1 "Failed to delete all containers."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Remove_Images() {
|
||||||
|
if [[ ${REMOVE_IMAGES} == "all" && "$(docker images -q)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting all images."
|
||||||
|
docker rmi "$(docker images -q)" || Show 1 "Failed to delete all images."
|
||||||
|
elif [[ ${REMOVE_IMAGES} == "unuse" && "$(docker images -q)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting unuse images."
|
||||||
|
docker image prune -af || Show 1 "Failed to delete unuse images."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Uninstall_Casaos() {
|
||||||
|
|
||||||
|
for SERVICE in "${CASA_SERVICES[@]}"; do
|
||||||
|
Show 2 "Stopping ${SERVICE}..."
|
||||||
|
systemctl disable --now "${SERVICE}" || Show 3 "Failed to disable ${SERVICE}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Remove Service file
|
||||||
|
if [[ -f ${CASA_SERVICE_USR} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_USR}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_SERVICE_LIB} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_LIB}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_SERVICE_ETC} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_ETC}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Old Casa Files
|
||||||
|
if [[ -d ${CASA_PATH} ]]; then
|
||||||
|
rm -rvf ${CASA_PATH} || Show 1 "Failed to delete legacy CasaOS files."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_CONF_PATH_OLD} ]]; then
|
||||||
|
rm -rvf ${CASA_CONF_PATH_OLD}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# New Casa Files
|
||||||
|
if [[ ${REMOVE_APP_DATA} = true ]]; then
|
||||||
|
rm -rvf /DATA/AppData || Show 1 "Failed to delete AppData."
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rvf "$(which ${CASA_EXEC})" || Show 3 "Failed to remove ${CASA_EXEC}"
|
||||||
|
rm -rvf ${CASA_CONF} || Show 3 "Failed to remove ${CASA_CONF}"
|
||||||
|
rm -rvf ${CASA_URL} || Show 3 "Failed to remove ${CASA_URL}"
|
||||||
|
|
||||||
|
rm -rvf /var/lib/casaos/app_category.json
|
||||||
|
rm -rvf /var/lib/casaos/app_list.json
|
||||||
|
rm -rvf /var/lib/casaos/docker_root
|
||||||
|
}
|
||||||
|
|
||||||
|
Detecting_CasaOS
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all containers? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
UNINSTALL_ALL_CONTAINER=true
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
UNINSTALL_ALL_CONTAINER=false
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${UNINSTALL_ALL_CONTAINER} == true ]]; then
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all images? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_IMAGES="all"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_IMAGES="none"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all AppData of CasaOS? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_APP_DATA=true
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_APP_DATA=false
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
else
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want to delete all images that are not used by the container? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_IMAGES="unuse"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_IMAGES="none"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
Uninstall_Container
|
||||||
|
Remove_Images
|
||||||
|
Uninstall_Casaos
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../cleanup-casaos.sh
|
||||||
@@ -0,0 +1,204 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
readonly CASA_SERVICES=(
|
||||||
|
"casaos.service"
|
||||||
|
"devmon@devmon.service"
|
||||||
|
)
|
||||||
|
|
||||||
|
readonly CASA_EXEC=casaos
|
||||||
|
readonly CASA_CONF=/etc/casaos/casaos.conf
|
||||||
|
readonly CASA_URL=/var/run/casaos/casaos.url
|
||||||
|
readonly CASA_SERVICE_USR=/usr/lib/systemd/system/casaos.service
|
||||||
|
readonly CASA_SERVICE_LIB=/lib/systemd/system/casaos.service
|
||||||
|
readonly CASA_SERVICE_ETC=/etc/systemd/system/casaos.service
|
||||||
|
|
||||||
|
# Old Casa Files
|
||||||
|
readonly CASA_PATH=/casaOS
|
||||||
|
readonly CASA_CONF_PATH_OLD=/etc/casaos.conf
|
||||||
|
|
||||||
|
readonly aCOLOUR=(
|
||||||
|
'\e[38;5;154m' # green | Lines, bullets and separators
|
||||||
|
'\e[1m' # Bold white | Main descriptions
|
||||||
|
'\e[90m' # Grey | Credits
|
||||||
|
'\e[91m' # Red | Update notifications Alert
|
||||||
|
'\e[33m' # Yellow | Emphasis
|
||||||
|
)
|
||||||
|
|
||||||
|
Show() {
|
||||||
|
# OK
|
||||||
|
if (($1 == 0)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# FAILED
|
||||||
|
elif (($1 == 1)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# INFO
|
||||||
|
elif (($1 == 2)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
# NOTICE
|
||||||
|
elif (($1 == 3)); then
|
||||||
|
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Warn() {
|
||||||
|
echo -e "${aCOLOUR[3]}$1$COLOUR_RESET"
|
||||||
|
}
|
||||||
|
|
||||||
|
trap 'onCtrlC' INT
|
||||||
|
onCtrlC() {
|
||||||
|
echo -e "${COLOUR_RESET}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
Detecting_CasaOS() {
|
||||||
|
if [[ ! -x "$(command -v ${CASA_EXEC})" ]]; then
|
||||||
|
Show 2 "CasaOS is not detected, exit the script."
|
||||||
|
exit 1
|
||||||
|
else
|
||||||
|
Show 0 "This script will delete the containers you no longer use, and the CasaOS configuration files."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Uninstall_Container() {
|
||||||
|
if [[ ${UNINSTALL_ALL_CONTAINER} == true && "$(docker ps -aq)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting containers."
|
||||||
|
docker stop "$(docker ps -aq)" || Show 1 "Failed to stop all containers."
|
||||||
|
docker rm "$(docker ps -aq)" || Show 1 "Failed to delete all containers."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
Remove_Images() {
|
||||||
|
if [[ ${REMOVE_IMAGES} == "all" && "$(docker images -q)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting all images."
|
||||||
|
docker rmi "$(docker images -q)" || Show 1 "Failed to delete all images."
|
||||||
|
elif [[ ${REMOVE_IMAGES} == "unuse" && "$(docker images -q)" != "" ]]; then
|
||||||
|
Show 2 "Start deleting unuse images."
|
||||||
|
docker image prune -af || Show 1 "Failed to delete unuse images."
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
Uninstall_Casaos() {
|
||||||
|
|
||||||
|
for SERVICE in "${CASA_SERVICES[@]}"; do
|
||||||
|
Show 2 "Stopping ${SERVICE}..."
|
||||||
|
systemctl disable --now "${SERVICE}" || Show 3 "Failed to disable ${SERVICE}"
|
||||||
|
done
|
||||||
|
|
||||||
|
# Remove Service file
|
||||||
|
if [[ -f ${CASA_SERVICE_USR} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_USR}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_SERVICE_LIB} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_LIB}
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_SERVICE_ETC} ]]; then
|
||||||
|
rm -rvf ${CASA_SERVICE_ETC}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# Old Casa Files
|
||||||
|
if [[ -d ${CASA_PATH} ]]; then
|
||||||
|
rm -rvf ${CASA_PATH} || Show 1 "Failed to delete legacy CasaOS files."
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [[ -f ${CASA_CONF_PATH_OLD} ]]; then
|
||||||
|
rm -rvf ${CASA_CONF_PATH_OLD}
|
||||||
|
fi
|
||||||
|
|
||||||
|
# New Casa Files
|
||||||
|
if [[ ${REMOVE_APP_DATA} = true ]]; then
|
||||||
|
rm -rvf /DATA/AppData || Show 1 "Failed to delete AppData."
|
||||||
|
fi
|
||||||
|
|
||||||
|
rm -rvf "$(which ${CASA_EXEC})" || Show 3 "Failed to remove ${CASA_EXEC}"
|
||||||
|
rm -rvf ${CASA_CONF} || Show 3 "Failed to remove ${CASA_CONF}"
|
||||||
|
rm -rvf ${CASA_URL} || Show 3 "Failed to remove ${CASA_URL}"
|
||||||
|
|
||||||
|
rm -rvf /var/lib/casaos/app_category.json
|
||||||
|
rm -rvf /var/lib/casaos/app_list.json
|
||||||
|
rm -rvf /var/lib/casaos/docker_root
|
||||||
|
}
|
||||||
|
|
||||||
|
Detecting_CasaOS
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all containers? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
UNINSTALL_ALL_CONTAINER=true
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
UNINSTALL_ALL_CONTAINER=false
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
if [[ ${UNINSTALL_ALL_CONTAINER} == true ]]; then
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all images? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_IMAGES="all"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_IMAGES="none"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want delete all AppData of CasaOS? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_APP_DATA=true
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_APP_DATA=false
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
else
|
||||||
|
while true; do
|
||||||
|
echo -n -e " ${aCOLOUR[4]}Do you want to delete all images that are not used by the container? Y/n :${COLOUR_RESET}"
|
||||||
|
read -r input
|
||||||
|
case $input in
|
||||||
|
[yY][eE][sS] | [yY])
|
||||||
|
REMOVE_IMAGES="unuse"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
[nN][oO] | [nN])
|
||||||
|
REMOVE_IMAGES="none"
|
||||||
|
break
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
Warn " Invalid input..."
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
done
|
||||||
|
fi
|
||||||
|
|
||||||
|
Uninstall_Container
|
||||||
|
Remove_Images
|
||||||
|
Uninstall_Casaos
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../debian/cleanup-casaos.sh
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../../debian/bullseye/cleanup-casaos.sh
|
||||||
@@ -330,19 +330,59 @@ TarFolder() {
|
|||||||
du -sh /DATA
|
du -sh /DATA
|
||||||
}
|
}
|
||||||
|
|
||||||
USB_Move_File() {
|
USB_Start_Auto() {
|
||||||
((EUID)) && sudo_cmd="sudo"
|
((EUID)) && sudo_cmd="sudo"
|
||||||
$sudo_cmd cp -rf /casaOS/server/shell/11-usb-mount.rules /etc/udev/rules.d/
|
$sudo_cmd systemctl enable devmon@devmon
|
||||||
$sudo_cmd chmod +x /casaOS/server/shell/usb-mount.sh
|
$sudo_cmd systemctl start devmon@devmon
|
||||||
$sudo_cmd cp -rf /casaOS/server/shell/usb-mount@.service /etc/systemd/system/
|
|
||||||
}
|
}
|
||||||
|
|
||||||
USB_Remove_File() {
|
USB_Stop_Auto() {
|
||||||
((EUID)) && sudo_cmd="sudo"
|
((EUID)) && sudo_cmd="sudo"
|
||||||
$sudo_cmd rm -fr /etc/udev/rules.d/11-usb-mount.rules
|
$sudo_cmd systemctl stop devmon@devmon
|
||||||
$sudo_cmd rm -fr /etc/systemd/system/usb-mount@.service
|
$sudo_cmd systemctl disable devmon@devmon
|
||||||
|
$sudo_cmd udevil clean
|
||||||
}
|
}
|
||||||
|
|
||||||
GetDeviceTree(){
|
GetDeviceTree(){
|
||||||
cat /proc/device-tree/model
|
cat /proc/device-tree/model
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# restart samba service
|
||||||
|
RestartSMBD(){
|
||||||
|
$sudo_cmd systemctl restart smbd
|
||||||
|
}
|
||||||
|
|
||||||
|
# edit user password $1:username
|
||||||
|
EditSmabaUserPassword(){
|
||||||
|
$sudo_cmd smbpasswd $1
|
||||||
|
}
|
||||||
|
|
||||||
|
AddSmabaUser(){
|
||||||
|
$sudo_cmd useradd $1
|
||||||
|
$sudo_cmd smbpasswd -a $1 <<EOF
|
||||||
|
$2
|
||||||
|
$2
|
||||||
|
EOF
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1:username $2:host $3:share $4:port $5:mountpoint $6:password
|
||||||
|
MountCIFS(){
|
||||||
|
$sudo_cmd mount -t cifs -o username=$1,password=$6,port=$4 //$2/$3 $5
|
||||||
|
}
|
||||||
|
|
||||||
|
# $1:service name
|
||||||
|
CheckServiceStatus(){
|
||||||
|
rs="`systemctl status $1 |grep -E 'Active|PID'`"
|
||||||
|
#echo "$rs"
|
||||||
|
run="`echo "$rs" |grep -B 2 'running'`"
|
||||||
|
fai="`echo "$rs" |grep -E -B 2 'failed|inactive|dead'`"
|
||||||
|
if [ "$run" == "" ]
|
||||||
|
then
|
||||||
|
echo "failed"
|
||||||
|
else
|
||||||
|
echo "running"
|
||||||
|
fi
|
||||||
|
}
|
||||||
|
UDEVILUmount(){
|
||||||
|
$sudo_cmd udevil umount -f $1
|
||||||
|
}
|
||||||
12
build/sysroot/usr/share/casaos/shell/update.sh
Normal file
12
build/sysroot/usr/share/casaos/shell/update.sh
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: LinkLeong link@icewhale.com
|
||||||
|
# @Date: 2022-06-30 10:08:33
|
||||||
|
# @LastEditors: LinkLeong
|
||||||
|
# @LastEditTime: 2022-09-01 22:33:06
|
||||||
|
# @FilePath: /CasaOS/build/sysroot/usr/share/casaos/shell/update.sh
|
||||||
|
# @Description:
|
||||||
|
###
|
||||||
|
|
||||||
|
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash
|
||||||
37
cmd/migration-tool/log.go
Normal file
37
cmd/migration-tool/log.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Logger struct {
|
||||||
|
DebugMode bool
|
||||||
|
|
||||||
|
_debug *log.Logger
|
||||||
|
_info *log.Logger
|
||||||
|
_error *log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLogger() *Logger {
|
||||||
|
return &Logger{
|
||||||
|
DebugMode: false,
|
||||||
|
_debug: log.New(os.Stdout, "DEBUG: ", 0),
|
||||||
|
_info: log.New(os.Stdout, "", 0),
|
||||||
|
_error: log.New(os.Stderr, "ERROR: ", 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Debug(format string, v ...interface{}) {
|
||||||
|
if l.DebugMode {
|
||||||
|
l._debug.Printf(format, v...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Info(format string, v ...interface{}) {
|
||||||
|
l._info.Printf(format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Error(format string, v ...interface{}) {
|
||||||
|
l._error.Printf(format, v...)
|
||||||
|
}
|
||||||
120
cmd/migration-tool/main.go
Normal file
120
cmd/migration-tool/main.go
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-08-23 18:09:11
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-31 14:17:51
|
||||||
|
* @FilePath: /CasaOS/cmd/migration-tool/main.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
interfaces "github.com/IceWhaleTech/CasaOS-Common"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/systemctl"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Gateway/common"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
casaosServiceName = "casaos.service"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_logger *Logger
|
||||||
|
sqliteDB *gorm.DB
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
configFlag = ""
|
||||||
|
dbFlag = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
config.InitSetup(configFlag)
|
||||||
|
|
||||||
|
if len(dbFlag) == 0 {
|
||||||
|
dbFlag = config.AppInfo.DBPath + "/db"
|
||||||
|
}
|
||||||
|
|
||||||
|
sqliteDB = sqlite.GetDb(dbFlag)
|
||||||
|
// gredis.GetRedisConn(config.RedisInfo),
|
||||||
|
|
||||||
|
service.MyService = service.NewService(sqliteDB, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
versionFlag := flag.Bool("v", false, "version")
|
||||||
|
debugFlag := flag.Bool("d", true, "debug")
|
||||||
|
forceFlag := flag.Bool("f", true, "force")
|
||||||
|
flag.Parse()
|
||||||
|
_logger = NewLogger()
|
||||||
|
if *versionFlag {
|
||||||
|
fmt.Println(common.Version)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.Getuid() != 0 {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *debugFlag {
|
||||||
|
_logger.DebugMode = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !*forceFlag {
|
||||||
|
serviceEnabled, err := systemctl.IsServiceEnabled(casaosServiceName)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if serviceEnabled {
|
||||||
|
_logger.Info("%s is already enabled. If migration is still needed, try with -f.", casaosServiceName)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
migrationTools := []interfaces.MigrationTool{
|
||||||
|
// nothing to migrate from last version
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedMigrationTool interfaces.MigrationTool
|
||||||
|
|
||||||
|
// look for the right migration tool matching current version
|
||||||
|
for _, tool := range migrationTools {
|
||||||
|
migrationNeeded, err := tool.IsMigrationNeeded()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if migrationNeeded {
|
||||||
|
selectedMigrationTool = tool
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if selectedMigrationTool == nil {
|
||||||
|
_logger.Error("selectedMigrationTool is null")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := selectedMigrationTool.PreMigrate(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := selectedMigrationTool.Migrate(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := selectedMigrationTool.PostMigrate(); err != nil {
|
||||||
|
_logger.Error("Migration succeeded, but post-migration failed: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
60
cmd/migration-tool/migration-sample.go
Normal file
60
cmd/migration-tool/migration-sample.go
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-08-24 17:36:00
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-09-05 11:24:27
|
||||||
|
* @FilePath: /CasaOS/cmd/migration-tool/migration-034-035.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
interfaces "github.com/IceWhaleTech/CasaOS-Common"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/version"
|
||||||
|
)
|
||||||
|
|
||||||
|
type migrationTool struct{}
|
||||||
|
|
||||||
|
func (u *migrationTool) IsMigrationNeeded() (bool, error) {
|
||||||
|
majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion()
|
||||||
|
if err != nil {
|
||||||
|
if err == version.ErrLegacyVersionNotFound {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
return false, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if majorVersion > 0 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if minorVersion > 3 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
if minorVersion == 3 && patchVersion > 5 {
|
||||||
|
return false, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
_logger.Info("Migration is needed for a CasaOS version 0.3.5 and older...")
|
||||||
|
return true, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *migrationTool) PreMigrate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *migrationTool) Migrate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (u *migrationTool) PostMigrate() error {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewMigrationToolFor_036() interfaces.MigrationTool {
|
||||||
|
return &migrationTool{}
|
||||||
|
}
|
||||||
@@ -11,22 +11,15 @@ DateFormat = 2006-01-02
|
|||||||
DBPath = /var/lib/casaos
|
DBPath = /var/lib/casaos
|
||||||
ShellPath = /usr/share/casaos/shell
|
ShellPath = /usr/share/casaos/shell
|
||||||
UserDataPath = /var/lib/casaos/conf
|
UserDataPath = /var/lib/casaos/conf
|
||||||
TempPath = /var/lib/casaos/temp
|
|
||||||
|
|
||||||
[server]
|
[server]
|
||||||
HttpPort = 80
|
|
||||||
UDPPort =
|
|
||||||
RunMode = release
|
RunMode = release
|
||||||
ServerApi = https://api.casaos.io/casaos-api
|
ServerApi = https://api.casaos.io/casaos-api
|
||||||
Handshake = socket.casaos.io
|
Handshake = socket.casaos.io
|
||||||
Token =
|
Token =
|
||||||
USBAutoMount =
|
USBAutoMount =
|
||||||
|
|
||||||
|
|
||||||
[system]
|
[system]
|
||||||
WidgetList =
|
|
||||||
|
|
||||||
|
[common]
|
||||||
[file]
|
RuntimePath=/var/run/casaos
|
||||||
ShareDir =
|
|
||||||
DownloadDir =
|
|
||||||
73
go.mod
73
go.mod
@@ -4,82 +4,39 @@ go 1.16
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
|
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
|
||||||
github.com/Microsoft/go-winio v0.5.0 // indirect
|
github.com/IceWhaleTech/CasaOS-Common v0.4.0-alpha1
|
||||||
github.com/Microsoft/hcsshim v0.8.22 // indirect
|
github.com/IceWhaleTech/CasaOS-Gateway v0.3.6
|
||||||
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
|
|
||||||
github.com/ambelovsky/go-structs v1.1.0 // indirect
|
github.com/ambelovsky/go-structs v1.1.0 // indirect
|
||||||
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109
|
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109
|
||||||
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect
|
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.2.1 // indirect
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
|
||||||
github.com/containerd/containerd v1.5.7
|
|
||||||
github.com/containerd/continuity v0.2.0 // indirect
|
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
github.com/docker/distribution v2.8.0+incompatible // indirect
|
|
||||||
github.com/docker/docker v20.10.7+incompatible
|
|
||||||
github.com/docker/go-connections v0.4.0
|
|
||||||
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b
|
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b
|
||||||
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
|
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
|
||||||
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b
|
github.com/gin-contrib/gzip v0.0.6
|
||||||
github.com/gin-contrib/gzip v0.0.2
|
github.com/gin-gonic/gin v1.8.1
|
||||||
github.com/gin-gonic/gin v1.7.2
|
github.com/glebarez/sqlite v1.5.0
|
||||||
github.com/go-ini/ini v1.62.0
|
github.com/go-ini/ini v1.62.0
|
||||||
github.com/go-ole/go-ole v1.2.5 // indirect
|
github.com/golang/mock v1.6.0
|
||||||
github.com/go-openapi/spec v0.20.4 // indirect
|
|
||||||
github.com/go-playground/validator/v10 v10.6.1 // indirect
|
|
||||||
github.com/gogo/googleapis v1.4.1 // indirect
|
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.1
|
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
|
||||||
github.com/gomodule/redigo v1.8.5
|
github.com/gomodule/redigo v1.8.5
|
||||||
github.com/google/go-github/v36 v36.0.0
|
github.com/google/go-github/v36 v36.0.0
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
|
||||||
github.com/googollee/go-socket.io v1.6.2
|
github.com/googollee/go-socket.io v1.6.2
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/hirochachacha/go-smb2 v1.1.0
|
||||||
github.com/jinzhu/copier v0.3.2
|
|
||||||
github.com/json-iterator/go v1.1.11 // indirect
|
|
||||||
github.com/klauspost/compress v1.13.6 // indirect
|
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
|
||||||
github.com/lucas-clemente/quic-go v0.25.0
|
github.com/lucas-clemente/quic-go v0.25.0
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.11 // indirect
|
|
||||||
github.com/mholt/archiver/v3 v3.5.1
|
github.com/mholt/archiver/v3 v3.5.1
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
|
||||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
|
||||||
github.com/opencontainers/selinux v1.8.5 // indirect
|
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pkg/errors v0.9.1
|
|
||||||
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109
|
|
||||||
github.com/prometheus/procfs v0.7.3 // indirect
|
|
||||||
github.com/robfig/cron v1.2.0
|
github.com/robfig/cron v1.2.0
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shirou/gopsutil/v3 v3.21.5
|
github.com/shirou/gopsutil/v3 v3.22.7
|
||||||
github.com/sirupsen/logrus v1.8.1
|
|
||||||
github.com/smartystreets/assertions v1.2.0 // indirect
|
github.com/smartystreets/assertions v1.2.0 // indirect
|
||||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||||
github.com/swaggo/gin-swagger v1.3.0
|
github.com/stretchr/testify v1.8.0
|
||||||
github.com/swaggo/swag v1.7.3
|
|
||||||
github.com/tidwall/gjson v1.10.2
|
github.com/tidwall/gjson v1.10.2
|
||||||
github.com/tklauser/go-sysconf v0.3.6 // indirect
|
go.uber.org/zap v1.21.0
|
||||||
github.com/ugorji/go v1.2.6 // indirect
|
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
|
||||||
go.opencensus.io v0.23.0 // indirect
|
|
||||||
go.uber.org/zap v1.10.0
|
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
|
||||||
golang.org/x/mod v0.5.0 // indirect
|
golang.org/x/mod v0.5.0 // indirect
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309 // indirect
|
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
|
||||||
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 // indirect
|
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
|
||||||
golang.org/x/tools v0.1.7 // indirect
|
golang.org/x/tools v0.1.7 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
gorm.io/gorm v1.24.0
|
||||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0 // indirect
|
|
||||||
google.golang.org/grpc v1.41.0 // indirect
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
|
||||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect
|
|
||||||
gorm.io/driver/sqlite v1.2.6
|
|
||||||
gorm.io/gorm v1.22.5
|
|
||||||
)
|
)
|
||||||
|
|||||||
18
interfaces/migrationTool.go
Normal file
18
interfaces/migrationTool.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-08-24 17:37:36
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-24 17:38:48
|
||||||
|
* @FilePath: /CasaOS/interfaces/migrationTool.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package interfaces
|
||||||
|
|
||||||
|
type MigrationTool interface {
|
||||||
|
IsMigrationNeeded() (bool, error)
|
||||||
|
PostMigrate() error
|
||||||
|
Migrate() error
|
||||||
|
PreMigrate() error
|
||||||
|
}
|
||||||
181
main.go
181
main.go
@@ -3,55 +3,61 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
"github.com/IceWhaleTech/CasaOS/model/notify"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/random"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/route"
|
"github.com/IceWhaleTech/CasaOS/route"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
|
"github.com/coreos/go-systemd/daemon"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"github.com/robfig/cron"
|
"github.com/robfig/cron"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const LOCALHOST = "127.0.0.1"
|
||||||
|
|
||||||
var sqliteDB *gorm.DB
|
var sqliteDB *gorm.DB
|
||||||
|
|
||||||
var configFlag = flag.String("c", "", "config address")
|
var (
|
||||||
var dbFlag = flag.String("db", "", "db path")
|
configFlag = flag.String("c", "", "config address")
|
||||||
var showUserInfo = flag.Bool("show-user-info", false, "show user info")
|
dbFlag = flag.String("db", "", "db path")
|
||||||
var resetUser = flag.Bool("ru", false, "reset user")
|
versionFlag = flag.Bool("v", false, "version")
|
||||||
var user = flag.String("user", "", "user name")
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
|
if *versionFlag {
|
||||||
|
fmt.Println("v" + types.CURRENTVERSION)
|
||||||
|
return
|
||||||
|
}
|
||||||
config.InitSetup(*configFlag)
|
config.InitSetup(*configFlag)
|
||||||
config.UpdateSetup()
|
|
||||||
loger.LogInit()
|
logger.LogInit(config.AppInfo.LogPath, config.AppInfo.LogSaveName, config.AppInfo.LogFileExt)
|
||||||
if len(*dbFlag) == 0 {
|
if len(*dbFlag) == 0 {
|
||||||
*dbFlag = config.AppInfo.DBPath + "/db"
|
*dbFlag = config.AppInfo.DBPath + "/db"
|
||||||
}
|
}
|
||||||
|
|
||||||
sqliteDB = sqlite.GetDb(*dbFlag)
|
sqliteDB = sqlite.GetDb(*dbFlag)
|
||||||
//gredis.GetRedisConn(config.RedisInfo),
|
// gredis.GetRedisConn(config.RedisInfo),
|
||||||
service.MyService = service.NewService(sqliteDB)
|
|
||||||
|
service.MyService = service.NewService(sqliteDB, config.CommonInfo.RuntimePath)
|
||||||
|
|
||||||
service.Cache = cache.Init()
|
service.Cache = cache.Init()
|
||||||
|
|
||||||
service.GetToken()
|
service.GetCPUThermalZone()
|
||||||
service.UDPAddressMap = make(map[string]string)
|
|
||||||
//go service.SocketConnect()
|
|
||||||
service.CancelList = make(map[string]string)
|
|
||||||
service.InternalInspection = make(map[string][]string)
|
|
||||||
service.NewVersionApp = make(map[string]string)
|
|
||||||
route.InitFunction()
|
route.InitFunction()
|
||||||
|
|
||||||
// go service.LoopFriend()
|
|
||||||
// go service.MyService.App().CheckNewImage()
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @title casaOS API
|
// @title casaOS API
|
||||||
@@ -67,70 +73,25 @@ func init() {
|
|||||||
// @BasePath /v1
|
// @BasePath /v1
|
||||||
func main() {
|
func main() {
|
||||||
service.NotifyMsg = make(chan notify.Message, 10)
|
service.NotifyMsg = make(chan notify.Message, 10)
|
||||||
if *showUserInfo {
|
if *versionFlag {
|
||||||
fmt.Println("CasaOS User Info")
|
|
||||||
fmt.Println("UserName:" + config.UserInfo.UserName)
|
|
||||||
fmt.Println("Password:" + config.UserInfo.PWD)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
fmt.Println("Reset User", *resetUser)
|
|
||||||
if *resetUser {
|
|
||||||
|
|
||||||
if user == nil || len(*user) == 0 {
|
|
||||||
fmt.Println("user is empty")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
userData := service.MyService.User().GetUserAllInfoByName(*user)
|
|
||||||
if userData.Id == 0 {
|
|
||||||
fmt.Println("user not exist")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
password := random.RandomString(6, false)
|
|
||||||
userData.Password = encryption.GetMD5ByStr(password)
|
|
||||||
service.MyService.User().UpdateUserPassword(userData)
|
|
||||||
fmt.Println("User reset successful")
|
|
||||||
fmt.Println("UserName:" + userData.UserName)
|
|
||||||
fmt.Println("Password:" + password)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
go func() {
|
|
||||||
service.UDPService()
|
|
||||||
service.SendIPToServer()
|
|
||||||
}()
|
|
||||||
go route.SocketInit(service.NotifyMsg)
|
go route.SocketInit(service.NotifyMsg)
|
||||||
go func() {
|
// model.Setup()
|
||||||
for i := 0; i < 1000; i++ {
|
// gredis.Setup()
|
||||||
time.Sleep(2 * time.Second)
|
|
||||||
//service.NotifyMsg <- strconv.Itoa(i)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
//model.Setup()
|
|
||||||
//gredis.Setup()
|
|
||||||
r := route.InitRouter()
|
r := route.InitRouter()
|
||||||
//service.SyncTask(sqliteDB)
|
// service.SyncTask(sqliteDB)
|
||||||
cron2 := cron.New()
|
cron2 := cron.New()
|
||||||
//every day execution
|
// every day execution
|
||||||
err := cron2.AddFunc("0 0/5 * * * *", func() {
|
|
||||||
//service.PushIpInfo(*&config.ServerInfo.Token)
|
|
||||||
//service.UpdataDDNSList(mysqldb)
|
|
||||||
//service.SyncTask(sqliteDB)
|
|
||||||
|
|
||||||
service.SendIPToServer()
|
err := cron2.AddFunc("0/5 * * * * *", func() {
|
||||||
|
|
||||||
service.LoopFriend()
|
|
||||||
//service.MyService.App().CheckNewImage()
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
err = cron2.AddFunc("0/5 * * * * *", func() {
|
|
||||||
if service.ClientCount > 0 {
|
if service.ClientCount > 0 {
|
||||||
//route.SendNetINfoBySocket()
|
// route.SendNetINfoBySocket()
|
||||||
//route.SendCPUBySocket()
|
// route.SendCPUBySocket()
|
||||||
//route.SendMemBySocket()
|
// route.SendMemBySocket()
|
||||||
// route.SendDiskBySocket()
|
// route.SendDiskBySocket()
|
||||||
//route.SendUSBBySocket()
|
// route.SendUSBBySocket()
|
||||||
route.SendAllHardwareStatusBySocket()
|
route.SendAllHardwareStatusBySocket()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -138,18 +99,64 @@ func main() {
|
|||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
cron2.Start()
|
cron2.Start()
|
||||||
|
|
||||||
defer cron2.Stop()
|
defer cron2.Stop()
|
||||||
s := &http.Server{
|
|
||||||
Addr: fmt.Sprintf(":%v", config.ServerInfo.HttpPort),
|
listener, err := net.Listen("tcp", net.JoinHostPort(LOCALHOST, "0"))
|
||||||
Handler: r,
|
if err != nil {
|
||||||
ReadTimeout: 60 * time.Second,
|
panic(err)
|
||||||
WriteTimeout: 60 * time.Second,
|
}
|
||||||
MaxHeaderBytes: 1 << 20,
|
routers := []string{"sys", "port", "file", "folder", "batch", "image", "samba", "notify"}
|
||||||
|
for _, v := range routers {
|
||||||
|
err = service.MyService.Gateway().CreateRoute(&model.Route{
|
||||||
|
Path: "/v1/" + v,
|
||||||
|
Target: "http://" + listener.Addr().String(),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("err", err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
// v0.3.6
|
||||||
|
if config.ServerInfo.HttpPort != "" {
|
||||||
|
changePort := model.ChangePortRequest{}
|
||||||
|
changePort.Port = config.ServerInfo.HttpPort
|
||||||
|
err := service.MyService.Gateway().ChangePort(&changePort)
|
||||||
|
if err == nil {
|
||||||
|
config.Cfg.Section("server").Key("HttpPort").SetValue("")
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
urlFilePath := filepath.Join(config.CommonInfo.RuntimePath, "casaos.url")
|
||||||
|
if err := file.CreateFileAndWriteContent(urlFilePath, "http://"+listener.Addr().String()); err != nil {
|
||||||
|
logger.Error("error when creating address file", zap.Error(err),
|
||||||
|
zap.Any("address", listener.Addr().String()),
|
||||||
|
zap.Any("filepath", urlFilePath),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.ListenAndServe()
|
if supported, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil {
|
||||||
|
logger.Error("Failed to notify systemd that casaos main service is ready", zap.Any("error", err))
|
||||||
|
} else if supported {
|
||||||
|
logger.Info("Notified systemd that casaos main service is ready")
|
||||||
|
} else {
|
||||||
|
logger.Info("This process is not running as a systemd service.")
|
||||||
|
}
|
||||||
|
|
||||||
// if err := r.Run(fmt.Sprintf(":%v", config.ServerInfo.HttpPort)); err != nil {
|
s := &http.Server{
|
||||||
// fmt.Println("failed run app: ", err)
|
Handler: r,
|
||||||
// }
|
ReadHeaderTimeout: 5 * time.Second, // fix G112: Potential slowloris attack (see https://github.com/securego/gosec)
|
||||||
|
}
|
||||||
|
|
||||||
|
logger.Info("CasaOS main service is listening...", zap.Any("address", listener.Addr().String()))
|
||||||
|
|
||||||
|
err = s.Serve(listener) // not using http.serve() to fix G114: Use of net/http serve function that has no support for setting timeouts (see https://github.com/securego/gosec)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,58 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2021-10-08 10:29:08
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-06-21 15:10:03
|
|
||||||
* @FilePath: /CasaOS/middleware/gin.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package middleware
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Cors() gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
method := c.Request.Method
|
|
||||||
|
|
||||||
c.Header("Access-Control-Allow-Origin", "*")
|
|
||||||
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
|
|
||||||
//允许跨域设置可以返回其他子段,可以自定义字段
|
|
||||||
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language")
|
|
||||||
// 允许浏览器(客户端)可以解析的头部 (重要)
|
|
||||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
|
|
||||||
//c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With")
|
|
||||||
//设置缓存时间
|
|
||||||
c.Header("Access-Control-Max-Age", "172800")
|
|
||||||
c.Header("Access-Control-Allow-Credentials", "true")
|
|
||||||
c.Set("content-type", "application/json")
|
|
||||||
//}
|
|
||||||
|
|
||||||
//允许类型校验
|
|
||||||
if method == "OPTIONS" {
|
|
||||||
c.JSON(http.StatusOK, "ok!")
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func WriteLog() gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
loger.Info("request:", zap.Any("path", c.Request.URL.String()), zap.Any("param", c.Params), zap.Any("query", c.Request.URL.Query()), zap.Any("body", c.Request.Body), zap.Any("method", c.Request.Method))
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-03-18 11:40:55
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-05-13 14:48:01
|
|
||||||
* @FilePath: /CasaOS/model/app-analyse.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package model
|
|
||||||
|
|
||||||
type AppAnalyse struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
UUId string `json:"uuid"`
|
|
||||||
Language string `json:"language"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ConnectionStatus struct {
|
|
||||||
From string `json:"from"`
|
|
||||||
To string `json:"to"`
|
|
||||||
Error string `json:"error"`
|
|
||||||
UUId string `json:"uuid"`
|
|
||||||
Event string `json:"event"`
|
|
||||||
}
|
|
||||||
119
model/app.go
119
model/app.go
@@ -1,119 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql/driver"
|
|
||||||
"encoding/json"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ServerAppListCollection struct {
|
|
||||||
List []ServerAppList `json:"list"`
|
|
||||||
Recommend []ServerAppList `json:"recommend"`
|
|
||||||
Community []ServerAppList `json:"community"`
|
|
||||||
Version string `json:"version"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type ServerAppList struct {
|
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Tagline string `json:"tagline"`
|
|
||||||
Tags Strings `gorm:"type:json" json:"tags"`
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
|
|
||||||
Category string `json:"category"`
|
|
||||||
CategoryId int `json:"category_id"`
|
|
||||||
CategoryFont string `json:"category_font"`
|
|
||||||
PortMap string `json:"port_map"`
|
|
||||||
ImageVersion string `json:"image_version"`
|
|
||||||
Tip string `json:"tip"`
|
|
||||||
Envs EnvArray `json:"envs"`
|
|
||||||
Ports PortArray `json:"ports"`
|
|
||||||
Volumes PathArray `json:"volumes"`
|
|
||||||
Devices PathArray `json:"devices"`
|
|
||||||
NetworkModel string `json:"network_model"`
|
|
||||||
Image string `json:"image"`
|
|
||||||
Index string `json:"index"`
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
State string `json:"state"`
|
|
||||||
Author string `json:"author"`
|
|
||||||
MinMemory int `json:"min_memory"`
|
|
||||||
MinDisk int `json:"min_disk"`
|
|
||||||
MaxMemory uint64 `json:"max_memory"`
|
|
||||||
Thumbnail string `json:"thumbnail"`
|
|
||||||
Healthy string `json:"healthy"`
|
|
||||||
Plugins Strings `json:"plugins"`
|
|
||||||
Origin string `json:"origin"`
|
|
||||||
Type int `json:"type"`
|
|
||||||
QueryCount int `json:"query_count"`
|
|
||||||
Developer string `json:"developer"`
|
|
||||||
HostName string `json:"host_name"`
|
|
||||||
Privileged bool `json:"privileged"`
|
|
||||||
CapAdd Strings `json:"cap_add"`
|
|
||||||
Cmd Strings `json:"cmd"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Ports struct {
|
|
||||||
ContainerPort uint `json:"container_port"`
|
|
||||||
CommendPort int `json:"commend_port"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"` // 1:必选 2:可选 3:默认值不必显示 4:系统处理 5:container内容也可编辑
|
|
||||||
}
|
|
||||||
|
|
||||||
type Volume struct {
|
|
||||||
ContainerPath string `json:"container_path"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"` // 1:必选 2:可选 3:默认值不必显示 4:系统处理 5:container内容也可编辑
|
|
||||||
}
|
|
||||||
|
|
||||||
type Envs struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Value string `json:"value"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"` // 1:必选 2:可选 3:默认值不必显示 4:系统处理 5:container内容也可编辑
|
|
||||||
}
|
|
||||||
|
|
||||||
type Devices struct {
|
|
||||||
ContainerPath string `json:"container_path"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"` // 1:必选 2:可选 3:默认值不必显示 4:系统处理 5:container内容也可编辑
|
|
||||||
}
|
|
||||||
|
|
||||||
type configures struct {
|
|
||||||
TcpPorts []Ports `json:"tcp_ports"`
|
|
||||||
UdpPorts []Ports `json:"udp_ports"`
|
|
||||||
Envs []Envs `json:"envs"`
|
|
||||||
Volumes []Volume `json:"volumes"`
|
|
||||||
Devices []Devices `json:"devices"`
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************使gorm支持[]string结构*******************/
|
|
||||||
type Strings []string
|
|
||||||
|
|
||||||
func (c Strings) Value() (driver.Value, error) {
|
|
||||||
b, err := json.Marshal(c)
|
|
||||||
return string(b), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *Strings) Scan(input interface{}) error {
|
|
||||||
return json.Unmarshal(input.([]byte), c)
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************使gorm支持[]string结构*******************/
|
|
||||||
|
|
||||||
/****************使gorm支持[]string结构*******************/
|
|
||||||
type MapStrings []map[string]string
|
|
||||||
|
|
||||||
func (c MapStrings) Value() (driver.Value, error) {
|
|
||||||
b, err := json.Marshal(c)
|
|
||||||
return string(b), err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *MapStrings) Scan(input interface{}) error {
|
|
||||||
return json.Unmarshal(input.([]byte), c)
|
|
||||||
}
|
|
||||||
|
|
||||||
/****************使gorm支持[]string结构*******************/
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: link a624669980@163.com
|
|
||||||
* @Date: 2022-05-16 17:37:08
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-06-22 17:45:53
|
|
||||||
* @FilePath: /CasaOS/model/category.go
|
|
||||||
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
|
|
||||||
|
|
||||||
*/
|
|
||||||
package model
|
|
||||||
|
|
||||||
type ServerCategoryList struct {
|
|
||||||
Version string `json:"version"`
|
|
||||||
Item []CategoryList `json:"item"`
|
|
||||||
}
|
|
||||||
type CategoryList struct {
|
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
|
||||||
//CreatedAt time.Time `json:"created_at"`
|
|
||||||
//
|
|
||||||
//UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
Font string `json:"font"`
|
|
||||||
Name string `json:"name"`
|
|
||||||
Count uint `json:"count"`
|
|
||||||
}
|
|
||||||
20
model/connections.go
Normal file
20
model/connections.go
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-07-27 10:30:43
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-04 20:06:04
|
||||||
|
* @FilePath: /CasaOS/model/connections.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package model
|
||||||
|
|
||||||
|
type Connections struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
|
Username string `json:"username"`
|
||||||
|
Password string `json:"password,omitempty"`
|
||||||
|
Host string `json:"host"`
|
||||||
|
Port string `json:"port"`
|
||||||
|
MountPoint string `json:"mount_point"`
|
||||||
|
}
|
||||||
@@ -1,76 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
type LSBLKModel struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
FsType string `json:"fstype"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
FSSize string `json:"fssize"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Model string `json:"model"` //设备标识符
|
|
||||||
RM bool `json:"rm"` //是否为可移动设备
|
|
||||||
RO bool `json:"ro"` //是否为只读设备
|
|
||||||
State string `json:"state"`
|
|
||||||
PhySec int `json:"phy-sec"` //物理扇区大小
|
|
||||||
Type string `json:"type"`
|
|
||||||
Vendor string `json:"vendor"` //供应商
|
|
||||||
Rev string `json:"rev"` //修订版本
|
|
||||||
FSAvail string `json:"fsavail"` //可用空间
|
|
||||||
FSUse string `json:"fsuse%"` //已用百分比
|
|
||||||
MountPoint string `json:"mountpoint"`
|
|
||||||
Format string `json:"format"`
|
|
||||||
Health string `json:"health"`
|
|
||||||
HotPlug bool `json:"hotplug"`
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
FSUsed string `json:"fsused"`
|
|
||||||
Temperature int `json:"temperature"`
|
|
||||||
Tran string `json:"tran"`
|
|
||||||
MinIO uint64 `json:"min-io"`
|
|
||||||
UsedPercent float64 `json:"used_percent"`
|
|
||||||
Serial string `json:"serial"`
|
|
||||||
Children []LSBLKModel `json:"children"`
|
|
||||||
SubSystems string `json:"subsystems"`
|
|
||||||
//详情特有
|
|
||||||
StartSector uint64 `json:"start_sector,omitempty"`
|
|
||||||
Rota bool `json:"rota"` //true(hhd) false(ssd)
|
|
||||||
DiskType string `json:"disk_type"`
|
|
||||||
EndSector uint64 `json:"end_sector,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Drive struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Model string `json:"model"`
|
|
||||||
Health string `json:"health"`
|
|
||||||
Temperature int `json:"temperature"`
|
|
||||||
DiskType string `json:"disk_type"`
|
|
||||||
NeedFormat bool `json:"need_format"`
|
|
||||||
Serial string `json:"serial"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DriveUSB struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Used uint64 `json:"use"`
|
|
||||||
Model string `json:"model"`
|
|
||||||
Mount bool `json:"mount"` //是否完全挂载
|
|
||||||
Avail uint64 `json:"avail"` //可用空间
|
|
||||||
}
|
|
||||||
|
|
||||||
type Storage struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
MountPoint string `json:"mountpoint"`
|
|
||||||
Size string `json:"size"`
|
|
||||||
Avail string `json:"avail"` //可用空间
|
|
||||||
Type string `json:"type"`
|
|
||||||
CreatedAt int64 `json:"create_at"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
DriveName string `json:"drive_name"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Summary struct {
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Avail uint64 `json:"avail"` //可用空间
|
|
||||||
Health bool `json:"health"`
|
|
||||||
Used uint64 `json:"used"`
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2021-12-08 18:10:25
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-06-14 17:20:36
|
|
||||||
* @FilePath: /CasaOS/model/docker.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package model
|
|
||||||
|
|
||||||
type DockerStatsModel struct {
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
Title string `json:"title"`
|
|
||||||
Data interface{} `json:"data"`
|
|
||||||
Pre interface{} `json:"pre"`
|
|
||||||
}
|
|
||||||
@@ -1,132 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import (
|
|
||||||
"database/sql/driver"
|
|
||||||
"encoding/json"
|
|
||||||
)
|
|
||||||
|
|
||||||
type TcpPorts struct {
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
ContainerPort int `json:"container_port"`
|
|
||||||
}
|
|
||||||
type UdpPorts struct {
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
ContainerPort int `json:"container_port"`
|
|
||||||
}
|
|
||||||
|
|
||||||
/*******************使用gorm支持json************************************/
|
|
||||||
|
|
||||||
type PortMap struct {
|
|
||||||
ContainerPort string `json:"container"`
|
|
||||||
CommendPort string `json:"host"`
|
|
||||||
Protocol string `json:"protocol"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PortArray []PortMap
|
|
||||||
|
|
||||||
// Value 实现方法
|
|
||||||
func (p PortArray) Value() (driver.Value, error) {
|
|
||||||
return json.Marshal(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan 实现方法
|
|
||||||
func (p *PortArray) Scan(input interface{}) error {
|
|
||||||
return json.Unmarshal(input.([]byte), p)
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
/*******************使用gorm支持json************************************/
|
|
||||||
|
|
||||||
type Env struct {
|
|
||||||
Name string `json:"container"`
|
|
||||||
Value string `json:"host"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
Type int `json:"type"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type JSON json.RawMessage
|
|
||||||
|
|
||||||
type EnvArray []Env
|
|
||||||
|
|
||||||
// Value 实现方法
|
|
||||||
func (p EnvArray) Value() (driver.Value, error) {
|
|
||||||
return json.Marshal(p)
|
|
||||||
//return .MarshalJSON()
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan 实现方法
|
|
||||||
func (p *EnvArray) Scan(input interface{}) error {
|
|
||||||
return json.Unmarshal(input.([]byte), p)
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
/*******************使用gorm支持json************************************/
|
|
||||||
|
|
||||||
type PathMap struct {
|
|
||||||
ContainerPath string `json:"container"`
|
|
||||||
Path string `json:"host"`
|
|
||||||
Type int `json:"type"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type PathArray []PathMap
|
|
||||||
|
|
||||||
// Value 实现方法
|
|
||||||
func (p PathArray) Value() (driver.Value, error) {
|
|
||||||
return json.Marshal(p)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Scan 实现方法
|
|
||||||
func (p *PathArray) Scan(input interface{}) error {
|
|
||||||
return json.Unmarshal(input.([]byte), p)
|
|
||||||
}
|
|
||||||
|
|
||||||
/************************************************************************/
|
|
||||||
|
|
||||||
//type PostData struct {
|
|
||||||
// Envs EnvArrey `json:"envs,omitempty"`
|
|
||||||
// Udp PortArrey `json:"udp_ports"`
|
|
||||||
// Tcp PortArrey `json:"tcp_ports"`
|
|
||||||
// Volumes PathArrey `json:"volumes"`
|
|
||||||
// Devices PathArrey `json:"devices"`
|
|
||||||
// Port string `json:"port,omitempty"`
|
|
||||||
// PortMap string `json:"port_map"`
|
|
||||||
// CpuShares int64 `json:"cpu_shares,omitempty"`
|
|
||||||
// Memory int64 `json:"memory,omitempty"`
|
|
||||||
// Restart string `json:"restart,omitempty"`
|
|
||||||
// EnableUPNP bool `json:"enable_upnp"`
|
|
||||||
// Label string `json:"label"`
|
|
||||||
// Position bool `json:"position"`
|
|
||||||
//}
|
|
||||||
|
|
||||||
type CustomizationPostData struct {
|
|
||||||
CustomId string `json:"custom_id"`
|
|
||||||
Origin string `json:"origin"`
|
|
||||||
NetworkModel string `json:"network_model"`
|
|
||||||
Index string `json:"index"`
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
Image string `json:"image"`
|
|
||||||
Envs EnvArray `json:"envs"`
|
|
||||||
Ports PortArray `json:"ports"`
|
|
||||||
Volumes PathArray `json:"volumes"`
|
|
||||||
Devices PathArray `json:"devices"`
|
|
||||||
//Port string `json:"port,omitempty"`
|
|
||||||
PortMap string `json:"port_map"`
|
|
||||||
CpuShares int64 `json:"cpu_shares"`
|
|
||||||
Memory int64 `json:"memory"`
|
|
||||||
Restart string `json:"restart"`
|
|
||||||
EnableUPNP bool `json:"enable_upnp"`
|
|
||||||
Label string `json:"label"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
Position bool `json:"position"`
|
|
||||||
HostName string `json:"host_name"`
|
|
||||||
Privileged bool `json:"privileged"`
|
|
||||||
CapAdd []string `json:"cap_add"`
|
|
||||||
Cmd []string `json:"cmd"`
|
|
||||||
Protocol string `json:"protocol"`
|
|
||||||
Host string `json:"host"`
|
|
||||||
}
|
|
||||||
@@ -1,21 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-05-27 15:01:58
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-05-31 14:51:21
|
|
||||||
* @FilePath: /CasaOS/model/notify/application.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package notify
|
|
||||||
|
|
||||||
type Application struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
State string `json:"state"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
Icon string `json:"icon"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
Finished bool `json:"finished"`
|
|
||||||
Success bool `json:"success"`
|
|
||||||
}
|
|
||||||
@@ -1,16 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-05-27 18:42:42
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-05-27 18:43:08
|
|
||||||
* @FilePath: /CasaOS/model/notify/person.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package notify
|
|
||||||
|
|
||||||
type Person struct {
|
|
||||||
ShareId string `json:"share_id"`
|
|
||||||
Type string `json:"type"`
|
|
||||||
}
|
|
||||||
19
model/notify/storage.go
Normal file
19
model/notify/storage.go
Normal file
@@ -0,0 +1,19 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2022-07-15 10:43:00
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-07-15 10:56:17
|
||||||
|
* @FilePath: /CasaOS/model/notify/storage.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package notify
|
||||||
|
|
||||||
|
type StorageMessage struct {
|
||||||
|
Type string `json:"type"` //sata,usb
|
||||||
|
Action string `json:"action"` //remove add
|
||||||
|
Path string `json:"path"`
|
||||||
|
Volume string `json:"volume"`
|
||||||
|
Size uint64 `json:"size"`
|
||||||
|
}
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
type PersionModel struct {
|
|
||||||
Token string `json:"token"`
|
|
||||||
Ips []string `json:"ips"`
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
|
||||||
UpdatedAt time.Time `json:"updated_at"`
|
|
||||||
}
|
|
||||||
|
|
||||||
//记录链接状态
|
|
||||||
type ConnectState struct {
|
|
||||||
From string `json:"from"`
|
|
||||||
To string `json:"to"`
|
|
||||||
Type string `json:"type"` //current state 1:ready 2:ok
|
|
||||||
CreatedAt time.Time `json:"created_at"`
|
|
||||||
UUId string `json:"uuid"` //对接标识
|
|
||||||
}
|
|
||||||
type MessageModel struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Data interface{} `json:"data"`
|
|
||||||
UUId string `json:"uuid"`
|
|
||||||
From string `json:"from"`
|
|
||||||
To string `json:"to"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type TranFileModel struct {
|
|
||||||
Hash string `json:"hash"` //Verify current fragment integrity
|
|
||||||
Length int `json:"length"`
|
|
||||||
Index int `json:"index"`
|
|
||||||
}
|
|
||||||
|
|
||||||
//需要获取文件详情
|
|
||||||
type FileDetailModel struct {
|
|
||||||
Path string `json:"path"`
|
|
||||||
}
|
|
||||||
|
|
||||||
//返回文件详情
|
|
||||||
type FileSummaryModel struct {
|
|
||||||
Hash string `json:"hash"` //Verify file
|
|
||||||
Name string `json:"name"`
|
|
||||||
BlockSize int `json:"block_size"`
|
|
||||||
Length int `json:"length"`
|
|
||||||
Size int64 `json:"size"`
|
|
||||||
Message string `json:"message"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type FriendsModel struct {
|
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
|
||||||
NickName string `json:"nick_name"`
|
|
||||||
Desc string `json:"desc"`
|
|
||||||
ShareId string `json:"share_id"`
|
|
||||||
}
|
|
||||||
@@ -1 +0,0 @@
|
|||||||
package receive
|
|
||||||
17
model/share.go
Normal file
17
model/share.go
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-07-26 11:12:12
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-07-27 14:58:55
|
||||||
|
* @FilePath: /CasaOS/model/share.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package model
|
||||||
|
|
||||||
|
type Shares struct {
|
||||||
|
ID uint `json:"id"`
|
||||||
|
Anonymous bool `json:"anonymous"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2022-05-13 18:15:46
|
* @Date: 2022-05-13 18:15:46
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-06-16 17:50:56
|
* @LastEditTime: 2022-09-02 22:12:34
|
||||||
* @FilePath: /CasaOS/model/sys_common.go
|
* @FilePath: /CasaOS/model/sys_common.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -12,39 +12,24 @@ package model
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
//系统配置
|
// 系统配置
|
||||||
type SysInfoModel struct {
|
type SysInfoModel struct {
|
||||||
Name string //系统名称
|
Name string // 系统名称
|
||||||
}
|
}
|
||||||
|
|
||||||
//用户相关
|
// 服务配置
|
||||||
type UserModel struct {
|
|
||||||
UserName string
|
|
||||||
PWD string
|
|
||||||
Token string
|
|
||||||
Head string
|
|
||||||
Email string
|
|
||||||
Description string
|
|
||||||
Initialized bool
|
|
||||||
Avatar string
|
|
||||||
NickName string
|
|
||||||
Public string
|
|
||||||
}
|
|
||||||
|
|
||||||
//服务配置
|
|
||||||
type ServerModel struct {
|
type ServerModel struct {
|
||||||
HttpPort string
|
HttpPort string
|
||||||
RunMode string
|
RunMode string
|
||||||
ServerApi string
|
ServerApi string
|
||||||
LockAccount bool
|
LockAccount bool
|
||||||
Handshake string
|
|
||||||
Token string
|
Token string
|
||||||
UDPPort string
|
|
||||||
USBAutoMount string
|
USBAutoMount string
|
||||||
SocketPort string
|
SocketPort string
|
||||||
|
UpdateUrl string
|
||||||
}
|
}
|
||||||
|
|
||||||
//服务配置
|
// 服务配置
|
||||||
type APPModel struct {
|
type APPModel struct {
|
||||||
LogPath string
|
LogPath string
|
||||||
LogSaveName string
|
LogSaveName string
|
||||||
@@ -56,17 +41,19 @@ type APPModel struct {
|
|||||||
DateFormat string
|
DateFormat string
|
||||||
DBPath string
|
DBPath string
|
||||||
ShellPath string
|
ShellPath string
|
||||||
TempPath string
|
}
|
||||||
|
type CommonModel struct {
|
||||||
|
RuntimePath string
|
||||||
}
|
}
|
||||||
|
|
||||||
//公共返回模型
|
// 公共返回模型
|
||||||
type Result struct {
|
type Result struct {
|
||||||
Success int `json:"success" example:"200"`
|
Success int `json:"success" example:"200"`
|
||||||
Message string `json:"message" example:"ok"`
|
Message string `json:"message" example:"ok"`
|
||||||
Data interface{} `json:"data" example:"返回结果"`
|
Data interface{} `json:"data" example:"返回结果"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//redis配置文件
|
// redis配置文件
|
||||||
type RedisModel struct {
|
type RedisModel struct {
|
||||||
Host string
|
Host string
|
||||||
Password string
|
Password string
|
||||||
@@ -76,19 +63,15 @@ type RedisModel struct {
|
|||||||
}
|
}
|
||||||
|
|
||||||
type SystemConfig struct {
|
type SystemConfig struct {
|
||||||
ConfigStr string `json:"config_str"`
|
|
||||||
WidgetList string `json:"widget_list"`
|
|
||||||
ConfigPath string `json:"config_path"`
|
ConfigPath string `json:"config_path"`
|
||||||
SyncPort string `json:"sync_port"`
|
|
||||||
SyncKey string `json:"sync_key"`
|
|
||||||
Analyse string `json:"analyse"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type CasaOSGlobalVariables struct {
|
|
||||||
AppChange bool
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type FileSetting struct {
|
type FileSetting struct {
|
||||||
ShareDir []string `json:"share_dir" delim:"|"`
|
ShareDir []string `json:"share_dir" delim:"|"`
|
||||||
DownloadDir string `json:"download_dir"`
|
DownloadDir string `json:"download_dir"`
|
||||||
}
|
}
|
||||||
|
type BaseInfo struct {
|
||||||
|
Hash string `json:"i"`
|
||||||
|
Version string `json:"v"`
|
||||||
|
Channel string `json:"c,omitempty"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,14 +1,25 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-05-13 18:15:46
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-01 18:32:57
|
||||||
|
* @FilePath: /CasaOS/model/zima.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
package model
|
package model
|
||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type Path struct {
|
type Path struct {
|
||||||
Name string `json:"name"` //File name or document name
|
Name string `json:"name"` //File name or document name
|
||||||
Path string `json:"path"` //Full path to file or folder
|
Path string `json:"path"` //Full path to file or folder
|
||||||
IsDir bool `json:"is_dir"` //Is it a folder
|
IsDir bool `json:"is_dir"` //Is it a folder
|
||||||
Date time.Time `json:"date"`
|
Date time.Time `json:"date"`
|
||||||
Size int64 `json:"size"` //File Size
|
Size int64 `json:"size"` //File Size
|
||||||
Type string `json:"type,omitempty"`
|
Type string `json:"type,omitempty"`
|
||||||
Label string `json:"label,omitempty"`
|
Label string `json:"label,omitempty"`
|
||||||
Write bool `json:"write"`
|
Write bool `json:"write"`
|
||||||
|
Extensions map[string]interface{} `json:"extensions"`
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2021-09-30 18:18:14
|
* @Date: 2021-09-30 18:18:14
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-06-21 11:09:30
|
* @LastEditTime: 2022-08-31 17:04:02
|
||||||
* @FilePath: /CasaOS/pkg/config/config.go
|
* @FilePath: /CasaOS/pkg/config/config.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -11,5 +11,5 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
const (
|
const (
|
||||||
USERCONFIGURL = "/etc/casaos.conf"
|
USERCONFIGURL = "/etc/casaos/casaos.conf"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2022-05-13 18:15:46
|
* @Date: 2022-05-13 18:15:46
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-06-21 16:01:26
|
* @LastEditTime: 2022-09-05 11:58:02
|
||||||
* @FilePath: /CasaOS/pkg/config/init.go
|
* @FilePath: /CasaOS/pkg/config/init.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -23,32 +23,28 @@ import (
|
|||||||
"github.com/go-ini/ini"
|
"github.com/go-ini/ini"
|
||||||
)
|
)
|
||||||
|
|
||||||
//系统配置
|
// 系统配置
|
||||||
var SysInfo = &model.SysInfoModel{}
|
var SysInfo = &model.SysInfoModel{}
|
||||||
|
|
||||||
//用户相关
|
// 用户相关
|
||||||
var UserInfo = &model.UserModel{}
|
|
||||||
|
|
||||||
//用户相关
|
|
||||||
var AppInfo = &model.APPModel{}
|
var AppInfo = &model.APPModel{}
|
||||||
|
|
||||||
//var RedisInfo = &model.RedisModel{}
|
var CommonInfo = &model.CommonModel{}
|
||||||
|
|
||||||
//server相关
|
// var RedisInfo = &model.RedisModel{}
|
||||||
|
|
||||||
|
// server相关
|
||||||
var ServerInfo = &model.ServerModel{}
|
var ServerInfo = &model.ServerModel{}
|
||||||
|
|
||||||
var SystemConfigInfo = &model.SystemConfig{}
|
var SystemConfigInfo = &model.SystemConfig{}
|
||||||
|
|
||||||
var CasaOSGlobalVariables = &model.CasaOSGlobalVariables{}
|
|
||||||
|
|
||||||
var FileSettingInfo = &model.FileSetting{}
|
var FileSettingInfo = &model.FileSetting{}
|
||||||
|
|
||||||
var Cfg *ini.File
|
var Cfg *ini.File
|
||||||
|
|
||||||
//初始化设置,获取系统的部分信息。
|
// 初始化设置,获取系统的部分信息。
|
||||||
func InitSetup(config string) {
|
func InitSetup(config string) {
|
||||||
|
configDir := USERCONFIGURL
|
||||||
var configDir = USERCONFIGURL
|
|
||||||
if len(config) > 0 {
|
if len(config) > 0 {
|
||||||
configDir = config
|
configDir = config
|
||||||
}
|
}
|
||||||
@@ -56,45 +52,45 @@ func InitSetup(config string) {
|
|||||||
configDir = "./conf/conf.conf"
|
configDir = "./conf/conf.conf"
|
||||||
}
|
}
|
||||||
var err error
|
var err error
|
||||||
//读取文件
|
// 读取文件
|
||||||
Cfg, err = ini.Load(configDir)
|
Cfg, err = ini.Load(configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Fail to read file: %v", err)
|
Cfg, err = ini.Load("/etc/casaos.conf")
|
||||||
os.Exit(1)
|
if err != nil {
|
||||||
|
Cfg, err = ini.Load("/casaOS/server/conf/conf.ini")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Fail to read file: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mapTo("user", UserInfo)
|
|
||||||
mapTo("app", AppInfo)
|
mapTo("app", AppInfo)
|
||||||
//mapTo("redis", RedisInfo)
|
// mapTo("redis", RedisInfo)
|
||||||
mapTo("server", ServerInfo)
|
mapTo("server", ServerInfo)
|
||||||
mapTo("system", SystemConfigInfo)
|
mapTo("system", SystemConfigInfo)
|
||||||
mapTo("file", FileSettingInfo)
|
mapTo("file", FileSettingInfo)
|
||||||
|
mapTo("common", CommonInfo)
|
||||||
SystemConfigInfo.ConfigPath = configDir
|
SystemConfigInfo.ConfigPath = configDir
|
||||||
if len(AppInfo.DBPath) == 0 {
|
if len(AppInfo.DBPath) == 0 {
|
||||||
AppInfo.DBPath = "/var/lib/casaos"
|
AppInfo.DBPath = "/var/lib/casaos"
|
||||||
Cfg.SaveTo(configDir)
|
|
||||||
}
|
}
|
||||||
if len(AppInfo.LogPath) == 0 {
|
if len(AppInfo.LogPath) == 0 {
|
||||||
AppInfo.LogPath = "/var/log/casaos/"
|
AppInfo.LogPath = "/var/log/casaos/"
|
||||||
Cfg.SaveTo(configDir)
|
|
||||||
}
|
}
|
||||||
if len(AppInfo.ShellPath) == 0 {
|
if len(AppInfo.ShellPath) == 0 {
|
||||||
AppInfo.ShellPath = "/usr/share/casaos/shell"
|
AppInfo.ShellPath = "/usr/share/casaos/shell"
|
||||||
Cfg.SaveTo(configDir)
|
|
||||||
}
|
}
|
||||||
if len(AppInfo.UserDataPath) == 0 {
|
if len(AppInfo.UserDataPath) == 0 {
|
||||||
AppInfo.UserDataPath = "/var/lib/casaos/conf"
|
AppInfo.UserDataPath = "/var/lib/casaos/conf"
|
||||||
Cfg.SaveTo(configDir)
|
|
||||||
}
|
}
|
||||||
if len(AppInfo.TempPath) == 0 {
|
if len(CommonInfo.RuntimePath) == 0 {
|
||||||
AppInfo.TempPath = "/var/lib/casaos/temp"
|
CommonInfo.RuntimePath = "/var/run/casaos"
|
||||||
Cfg.SaveTo(configDir)
|
|
||||||
}
|
}
|
||||||
|
Cfg.SaveTo(configDir)
|
||||||
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//映射
|
// 映射
|
||||||
func mapTo(section string, v interface{}) {
|
func mapTo(section string, v interface{}) {
|
||||||
err := Cfg.Section(section).MapTo(v)
|
err := Cfg.Section(section).MapTo(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -111,6 +107,7 @@ func getCurrentAbPathByCaller() string {
|
|||||||
}
|
}
|
||||||
return abPath
|
return abPath
|
||||||
}
|
}
|
||||||
|
|
||||||
func getCurrentDirectory() string {
|
func getCurrentDirectory() string {
|
||||||
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
dir, err := filepath.Abs(filepath.Dir(os.Args[0]))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
|
||||||
)
|
|
||||||
|
|
||||||
//检查目录是否存在
|
|
||||||
func mkdirDATAAll() {
|
|
||||||
sysType := runtime.GOOS
|
|
||||||
var dirArray []string
|
|
||||||
if sysType == "linux" {
|
|
||||||
dirArray = []string{"/DATA/AppData", "/DATA/Documents", "/DATA/Downloads", "/DATA/Gallery", "/DATA/Media/Movies", "/DATA/Media/TV Shows", "/DATA/Media/Music"}
|
|
||||||
}
|
|
||||||
|
|
||||||
if sysType == "windows" {
|
|
||||||
dirArray = []string{"C:\\CasaOS\\DATA\\AppData", "C:\\CasaOS\\DATA\\Documents", "C:\\CasaOS\\DATA\\Downloads", "C:\\CasaOS\\DATA\\Gallery", "C:\\CasaOS\\DATA\\Media/Movies", "C:\\CasaOS\\DATA\\Media\\TV Shows", "C:\\CasaOS\\DATA\\Media\\Music"}
|
|
||||||
}
|
|
||||||
if sysType == "darwin" {
|
|
||||||
dirArray = []string{"./CasaOS/DATA/AppData", "./CasaOS/DATA/Documents", "./CasaOS/DATA/Downloads", "./CasaOS/DATA/Gallery", "./CasaOS/DATA/Media/Movies", "./CasaOS/DATA/Media/TV Shows", "./CasaOS/DATA/Media/Music"}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range dirArray {
|
|
||||||
file.IsNotExistMkDir(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateSetup() {
|
|
||||||
mkdirDATAAll()
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
package docker
|
|
||||||
|
|
||||||
const NETWORKNAME = "oasis"
|
|
||||||
@@ -1,403 +0,0 @@
|
|||||||
package docker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
json2 "encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"io"
|
|
||||||
"regexp"
|
|
||||||
"strconv"
|
|
||||||
"sync"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/gorilla/websocket"
|
|
||||||
"github.com/sirupsen/logrus"
|
|
||||||
"golang.org/x/crypto/ssh"
|
|
||||||
)
|
|
||||||
|
|
||||||
func NewSshClient(user, password string) (*ssh.Client, error) {
|
|
||||||
|
|
||||||
// connet to ssh
|
|
||||||
// addr = fmt.Sprintf("%s:%d", host, port)
|
|
||||||
|
|
||||||
config := &ssh.ClientConfig{
|
|
||||||
Timeout: time.Second * 5,
|
|
||||||
User: user,
|
|
||||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
|
||||||
//HostKeyCallback: ,
|
|
||||||
//HostKeyCallback: hostKeyCallBackFunc(h.Host),
|
|
||||||
}
|
|
||||||
//if h.Type == "password" {
|
|
||||||
config.Auth = []ssh.AuthMethod{ssh.Password(password)}
|
|
||||||
//} else {
|
|
||||||
// config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)}
|
|
||||||
//}
|
|
||||||
addr := fmt.Sprintf("%s:%d", "127.0.0.1", 22)
|
|
||||||
c, err := ssh.Dial("tcp", addr, config)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return c, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// setup ssh shell session
|
|
||||||
// set Session and StdinPipe here,
|
|
||||||
// and the Session.Stdout and Session.Sdterr are also set.
|
|
||||||
func NewSshConn(cols, rows int, sshClient *ssh.Client) (*SshConn, error) {
|
|
||||||
sshSession, err := sshClient.NewSession()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
|
|
||||||
stdinP, err := sshSession.StdinPipe()
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
comboWriter := new(wsBufferWriter)
|
|
||||||
|
|
||||||
sshSession.Stdout = comboWriter
|
|
||||||
sshSession.Stderr = comboWriter
|
|
||||||
|
|
||||||
modes := ssh.TerminalModes{
|
|
||||||
ssh.ECHO: 1, // disable echo
|
|
||||||
ssh.TTY_OP_ISPEED: 14400, // input speed = 14.4kbaud
|
|
||||||
ssh.TTY_OP_OSPEED: 14400, // output speed = 14.4kbaud
|
|
||||||
}
|
|
||||||
// Request pseudo terminal
|
|
||||||
if err := sshSession.RequestPty("xterm", rows, cols, modes); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
// Start remote shell
|
|
||||||
if err := sshSession.Shell(); err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return &SshConn{StdinPipe: stdinP, ComboOutput: comboWriter, Session: sshSession}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
type SshConn struct {
|
|
||||||
// calling Write() to write data into ssh server
|
|
||||||
StdinPipe io.WriteCloser
|
|
||||||
// Write() be called to receive data from ssh server
|
|
||||||
ComboOutput *wsBufferWriter
|
|
||||||
Session *ssh.Session
|
|
||||||
}
|
|
||||||
type wsBufferWriter struct {
|
|
||||||
buffer bytes.Buffer
|
|
||||||
mu sync.Mutex
|
|
||||||
}
|
|
||||||
|
|
||||||
func (w *wsBufferWriter) Write(p []byte) (int, error) {
|
|
||||||
w.mu.Lock()
|
|
||||||
defer w.mu.Unlock()
|
|
||||||
return w.buffer.Write(p)
|
|
||||||
}
|
|
||||||
func (s *SshConn) Close() {
|
|
||||||
if s.Session != nil {
|
|
||||||
s.Session.Close()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
const (
|
|
||||||
wsMsgCmd = "cmd"
|
|
||||||
wsMsgResize = "resize"
|
|
||||||
)
|
|
||||||
|
|
||||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
|
||||||
func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
|
||||||
//tells other go routine quit
|
|
||||||
username := ""
|
|
||||||
for {
|
|
||||||
|
|
||||||
//read websocket msg
|
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
msgObj := wsMsg{}
|
|
||||||
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
msgObj.Type = "cmd"
|
|
||||||
msgObj.Cmd = string(wsData)
|
|
||||||
}
|
|
||||||
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
|
||||||
//}
|
|
||||||
switch msgObj.Type {
|
|
||||||
case wsMsgCmd:
|
|
||||||
//handle xterm.js stdin
|
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
|
||||||
decodeBytes := []byte(msgObj.Cmd)
|
|
||||||
if msgObj.Cmd == "\u007f" {
|
|
||||||
if len(username) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
wsConn.WriteMessage(websocket.TextMessage, []byte("\b\x1b[K"))
|
|
||||||
username = username[:len(username)-1]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if msgObj.Cmd == "\r" {
|
|
||||||
return username
|
|
||||||
}
|
|
||||||
username += msgObj.Cmd
|
|
||||||
|
|
||||||
if err := wsConn.WriteMessage(websocket.TextMessage, decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
|
||||||
}
|
|
||||||
//write input cmd to log buffer
|
|
||||||
if _, err := logBuff.Write(decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
|
||||||
//tells other go routine quit
|
|
||||||
password := ""
|
|
||||||
for {
|
|
||||||
|
|
||||||
//read websocket msg
|
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("reading webSocket message failed")
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
msgObj := wsMsg{}
|
|
||||||
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
msgObj.Type = "cmd"
|
|
||||||
msgObj.Cmd = string(wsData)
|
|
||||||
}
|
|
||||||
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
|
||||||
//}
|
|
||||||
switch msgObj.Type {
|
|
||||||
case wsMsgCmd:
|
|
||||||
//handle xterm.js stdin
|
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
|
||||||
if msgObj.Cmd == "\r" {
|
|
||||||
return password
|
|
||||||
}
|
|
||||||
|
|
||||||
if msgObj.Cmd == "\u007f" {
|
|
||||||
if len(password) == 0 {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
password = password[:len(password)-1]
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
password += msgObj.Cmd
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
|
||||||
func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
|
||||||
//tells other go routine quit
|
|
||||||
defer setQuit(exitCh)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-exitCh:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
//read websocket msg
|
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("reading webSocket message failed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//unmashal bytes into struct
|
|
||||||
//msgObj := wsMsg{
|
|
||||||
// Type: "cmd",
|
|
||||||
// Cmd: "",
|
|
||||||
// Rows: 50,
|
|
||||||
// Cols: 180,
|
|
||||||
//}
|
|
||||||
msgObj := wsMsg{}
|
|
||||||
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
msgObj.Type = "cmd"
|
|
||||||
msgObj.Cmd = string(wsData)
|
|
||||||
}
|
|
||||||
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
|
||||||
//}
|
|
||||||
switch msgObj.Type {
|
|
||||||
|
|
||||||
case wsMsgResize:
|
|
||||||
//handle xterm.js size change
|
|
||||||
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
|
||||||
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
|
||||||
logrus.WithError(err).Error("ssh pty change windows size failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case wsMsgCmd:
|
|
||||||
//handle xterm.js stdin
|
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
|
||||||
decodeBytes := []byte(msgObj.Cmd)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
|
|
||||||
}
|
|
||||||
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
|
||||||
}
|
|
||||||
//write input cmd to log buffer
|
|
||||||
if _, err := logBuff.Write(decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool) {
|
|
||||||
//tells other go routine quit
|
|
||||||
//defer setQuit(exitCh)
|
|
||||||
|
|
||||||
//every 120ms write combine output bytes into websocket response
|
|
||||||
tick := time.NewTicker(time.Millisecond * time.Duration(120))
|
|
||||||
//for range time.Tick(120 * time.Millisecond){}
|
|
||||||
defer tick.Stop()
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-tick.C:
|
|
||||||
//write combine output bytes into websocket response
|
|
||||||
if err := flushComboOutput(ssConn.ComboOutput, wsConn); err != nil {
|
|
||||||
logrus.WithError(err).Error("ssh sending combo output to webSocket failed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
case <-exitCh:
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error {
|
|
||||||
if w.buffer.Len() != 0 {
|
|
||||||
err := wsConn.WriteMessage(websocket.TextMessage, w.buffer.Bytes())
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
w.buffer.Reset()
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
|
||||||
func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
|
||||||
//tells other go routine quit
|
|
||||||
defer setQuit(exitCh)
|
|
||||||
for {
|
|
||||||
select {
|
|
||||||
case <-exitCh:
|
|
||||||
return
|
|
||||||
default:
|
|
||||||
//read websocket msg
|
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("reading webSocket message failed")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//unmashal bytes into struct
|
|
||||||
//msgObj := wsMsg{
|
|
||||||
// Type: "cmd",
|
|
||||||
// Cmd: "",
|
|
||||||
// Rows: 50,
|
|
||||||
// Cols: 180,
|
|
||||||
//}
|
|
||||||
msgObj := wsMsg{}
|
|
||||||
if err := json2.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
msgObj.Type = "cmd"
|
|
||||||
msgObj.Cmd = string(wsData)
|
|
||||||
}
|
|
||||||
//if err := json.Unmarshal(wsData, &msgObj); err != nil {
|
|
||||||
// logrus.WithError(err).WithField("wsData", string(wsData)).Error("unmarshal websocket message failed")
|
|
||||||
//}
|
|
||||||
switch msgObj.Type {
|
|
||||||
|
|
||||||
case wsMsgResize:
|
|
||||||
//handle xterm.js size change
|
|
||||||
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
|
||||||
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
|
||||||
logrus.WithError(err).Error("ssh pty change windows size failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case wsMsgCmd:
|
|
||||||
//handle xterm.js stdin
|
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
|
||||||
decodeBytes := []byte(msgObj.Cmd)
|
|
||||||
if err != nil {
|
|
||||||
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
|
|
||||||
}
|
|
||||||
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
|
||||||
}
|
|
||||||
//write input cmd to log buffer
|
|
||||||
if _, err := logBuff.Write(decodeBytes); err != nil {
|
|
||||||
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (ssConn *SshConn) SessionWait(quitChan chan bool) {
|
|
||||||
if err := ssConn.Session.Wait(); err != nil {
|
|
||||||
logrus.WithError(err).Error("ssh session wait failed")
|
|
||||||
setQuit(quitChan)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setQuit(ch chan bool) {
|
|
||||||
ch <- true
|
|
||||||
}
|
|
||||||
|
|
||||||
type wsMsg struct {
|
|
||||||
Type string `json:"type"`
|
|
||||||
Cmd string `json:"cmd"`
|
|
||||||
Cols int `json:"cols"`
|
|
||||||
Rows int `json:"rows"`
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将终端的输出转发到前端
|
|
||||||
func WsWriterCopy(reader io.Reader, writer *websocket.Conn) {
|
|
||||||
buf := make([]byte, 8192)
|
|
||||||
reg1 := regexp.MustCompile(`stty rows \d+ && stty cols \d+ `)
|
|
||||||
for {
|
|
||||||
nr, err := reader.Read(buf)
|
|
||||||
if nr > 0 {
|
|
||||||
result1 := reg1.FindIndex(buf[0:nr])
|
|
||||||
if len(result1) > 0 {
|
|
||||||
fmt.Println(result1)
|
|
||||||
} else {
|
|
||||||
err := writer.WriteMessage(websocket.BinaryMessage, buf[0:nr])
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// 将前端的输入转发到终端
|
|
||||||
func WsReaderCopy(reader *websocket.Conn, writer io.Writer) {
|
|
||||||
for {
|
|
||||||
messageType, p, err := reader.ReadMessage()
|
|
||||||
if err != nil {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if messageType == websocket.TextMessage {
|
|
||||||
msgObj := wsMsg{}
|
|
||||||
if err = json2.Unmarshal(p, &msgObj); err != nil {
|
|
||||||
writer.Write(p)
|
|
||||||
} else if msgObj.Type == wsMsgResize {
|
|
||||||
writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,11 +0,0 @@
|
|||||||
package docker
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
func GetDir(id, envName string) string {
|
|
||||||
|
|
||||||
if strings.Contains(envName, "$AppID") && len(id) > 0 {
|
|
||||||
return strings.ReplaceAll(envName, "$AppID", id)
|
|
||||||
}
|
|
||||||
return envName
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package docker
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetDir(t *testing.T) {
|
|
||||||
fmt.Println(GetDir("", "config"))
|
|
||||||
}
|
|
||||||
75
pkg/samba/smaba.go
Normal file
75
pkg/samba/smaba.go
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-07-27 10:35:29
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-01 13:56:44
|
||||||
|
* @FilePath: /CasaOS/pkg/samba/smaba.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package samba
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
"net"
|
||||||
|
|
||||||
|
"github.com/hirochachacha/go-smb2"
|
||||||
|
)
|
||||||
|
|
||||||
|
func ConnectSambaService(host, port, username, password, directory string) error {
|
||||||
|
conn, err := net.Dial("tcp", host+":"+port)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
d := &smb2.Dialer{
|
||||||
|
Initiator: &smb2.NTLMInitiator{
|
||||||
|
User: username,
|
||||||
|
Password: password,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := d.Dial(conn)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer s.Logoff()
|
||||||
|
names, err := s.ListSharenames()
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, name := range names {
|
||||||
|
if name == directory {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.New("directory not found")
|
||||||
|
}
|
||||||
|
|
||||||
|
//get share name list
|
||||||
|
func GetSambaSharesList(host, port, username, password string) ([]string, error) {
|
||||||
|
conn, err := net.Dial("tcp", host+":"+port)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer conn.Close()
|
||||||
|
d := &smb2.Dialer{
|
||||||
|
Initiator: &smb2.NTLMInitiator{
|
||||||
|
User: username,
|
||||||
|
Password: password,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
s, err := d.Dial(conn)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
defer s.Logoff()
|
||||||
|
names, err := s.ListSharenames()
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return names, err
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2022-05-13 18:15:46
|
* @Date: 2022-05-13 18:15:46
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-06-22 18:50:44
|
* @LastEditTime: 2022-08-31 13:39:24
|
||||||
* @FilePath: /CasaOS/pkg/sqlite/db.go
|
* @FilePath: /CasaOS/pkg/sqlite/db.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -13,11 +13,11 @@ package sqlite
|
|||||||
import (
|
import (
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
"github.com/glebarez/sqlite"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
"gorm.io/driver/sqlite"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -28,24 +28,27 @@ func GetDb(dbPath string) *gorm.DB {
|
|||||||
return gdb
|
return gdb
|
||||||
}
|
}
|
||||||
// Refer https://github.com/go-sql-driver/mysql#dsn-data-source-name
|
// Refer https://github.com/go-sql-driver/mysql#dsn-data-source-name
|
||||||
//dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", m.User, m.PWD, m.IP, m.Port, m.DBName)
|
// dsn := fmt.Sprintf("%v:%v@tcp(%v:%v)/%v?charset=utf8mb4&parseTime=True&loc=Local", m.User, m.PWD, m.IP, m.Port, m.DBName)
|
||||||
//db, err := gorm.Open(mysql2.Open(dsn), &gorm.Config{})
|
// db, err := gorm.Open(mysql2.Open(dsn), &gorm.Config{})
|
||||||
file.IsNotExistMkDir(dbPath)
|
file.IsNotExistMkDir(dbPath)
|
||||||
db, err := gorm.Open(sqlite.Open(dbPath+"/casaOS.db"), &gorm.Config{})
|
db, err := gorm.Open(sqlite.Open(dbPath+"/casaOS.db"), &gorm.Config{})
|
||||||
c, _ := db.DB()
|
c, _ := db.DB()
|
||||||
c.SetMaxIdleConns(10)
|
c.SetMaxIdleConns(10)
|
||||||
c.SetMaxOpenConns(100)
|
c.SetMaxOpenConns(1)
|
||||||
c.SetConnMaxIdleTime(time.Second * 1000)
|
c.SetConnMaxIdleTime(time.Second * 1000)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
loger.Error("sqlite connect error", zap.Any("db connect error", err))
|
logger.Error("sqlite connect error", zap.Any("db connect error", err))
|
||||||
panic("sqlite connect error")
|
panic("sqlite connect error")
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
gdb = db
|
gdb = db
|
||||||
err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.PersonDownloadDBModel{}, model2.FriendModel{}, model2.PersonDownRecordDBModel{}, model2.UserDBModel{})
|
|
||||||
|
err = db.AutoMigrate(&model2.AppNotify{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{})
|
||||||
db.Exec("DROP TABLE IF EXISTS o_application")
|
db.Exec("DROP TABLE IF EXISTS o_application")
|
||||||
|
db.Exec("DROP TABLE IF EXISTS o_friend")
|
||||||
|
db.Exec("DROP TABLE IF EXISTS o_person_download")
|
||||||
|
db.Exec("DROP TABLE IF EXISTS o_person_down_record")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
loger.Error("check or create db error", zap.Any("error", err))
|
logger.Error("check or create db error", zap.Any("error", err))
|
||||||
}
|
}
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ func ExecResultStrArray(cmdStr string) []string {
|
|||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
//str, err := ioutil.ReadAll(stdout)
|
// str, err := ioutil.ReadAll(stdout)
|
||||||
var networklist = []string{}
|
networklist := []string{}
|
||||||
outputBuf := bufio.NewReader(stdout)
|
outputBuf := bufio.NewReader(stdout)
|
||||||
for {
|
for {
|
||||||
output, _, err := outputBuf.ReadLine()
|
output, _, err := outputBuf.ReadLine()
|
||||||
@@ -54,6 +54,8 @@ func ExecResultStrArray(cmdStr string) []string {
|
|||||||
|
|
||||||
func ExecResultStr(cmdStr string) string {
|
func ExecResultStr(cmdStr string) string {
|
||||||
cmd := exec.Command("/bin/bash", "-c", cmdStr)
|
cmd := exec.Command("/bin/bash", "-c", cmdStr)
|
||||||
|
println(cmd.String())
|
||||||
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@@ -73,7 +75,7 @@ func ExecResultStr(cmdStr string) string {
|
|||||||
return string(str)
|
return string(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
//执行 lsblk 命令
|
// 执行 lsblk 命令
|
||||||
func ExecLSBLK() []byte {
|
func ExecLSBLK() []byte {
|
||||||
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
|
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -83,7 +85,7 @@ func ExecLSBLK() []byte {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
//执行 lsblk 命令
|
// 执行 lsblk 命令
|
||||||
func ExecLSBLKByPath(path string) []byte {
|
func ExecLSBLKByPath(path string) []byte {
|
||||||
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -93,7 +95,7 @@ func ExecLSBLKByPath(path string) []byte {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
//exec smart
|
// exec smart
|
||||||
func ExecSmartCTLByPath(path string) []byte {
|
func ExecSmartCTLByPath(path string) []byte {
|
||||||
timeout := 3
|
timeout := 3
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
||||||
@@ -107,6 +109,5 @@ func ExecSmartCTLByPath(path string) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ExecEnabledSMART(path string) {
|
func ExecEnabledSMART(path string) {
|
||||||
|
|
||||||
exec.Command("smartctl", "-s on", path).Output()
|
exec.Command("smartctl", "-s on", path).Output()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,10 +2,11 @@ package common_err
|
|||||||
|
|
||||||
const (
|
const (
|
||||||
SUCCESS = 200
|
SUCCESS = 200
|
||||||
ERROR = 500
|
SERVICE_ERROR = 500
|
||||||
INVALID_PARAMS = 400
|
CLIENT_ERROR = 400
|
||||||
ERROR_AUTH_TOKEN = 401
|
ERROR_AUTH_TOKEN = 401
|
||||||
|
|
||||||
|
INVALID_PARAMS = 4000
|
||||||
//user
|
//user
|
||||||
PWD_INVALID = 10001
|
PWD_INVALID = 10001
|
||||||
PWD_IS_EMPTY = 10002
|
PWD_IS_EMPTY = 10002
|
||||||
@@ -26,6 +27,10 @@ const (
|
|||||||
PORT_IS_OCCUPIED = 20004
|
PORT_IS_OCCUPIED = 20004
|
||||||
COMMAND_ERROR_INVALID_OPERATION = 20005
|
COMMAND_ERROR_INVALID_OPERATION = 20005
|
||||||
VERIFICATION_FAILURE = 20006
|
VERIFICATION_FAILURE = 20006
|
||||||
|
Record_NOT_EXIST = 20007
|
||||||
|
Record_ALREADY_EXIST = 20008
|
||||||
|
SERVICE_NOT_RUNNING = 20009
|
||||||
|
CHARACTER_LIMIT = 20010
|
||||||
|
|
||||||
//disk
|
//disk
|
||||||
NAME_NOT_AVAILABLE = 40001
|
NAME_NOT_AVAILABLE = 40001
|
||||||
@@ -47,21 +52,15 @@ const (
|
|||||||
DIR_NOT_EXISTS = 60004
|
DIR_NOT_EXISTS = 60004
|
||||||
SOURCE_DES_SAME = 60005
|
SOURCE_DES_SAME = 60005
|
||||||
|
|
||||||
//shortcuts
|
//share
|
||||||
SHORTCUTS_URL_ERROR = 70001
|
SHARE_ALREADY_EXISTS = 70001
|
||||||
|
SHARE_NAME_ALREADY_EXISTS = 70002
|
||||||
//person
|
|
||||||
PERSON_REMOTE_ERROR = 80001
|
|
||||||
PERSON_DOWN_NOT_EXIST = 80002
|
|
||||||
PERSON_EXIST_DOWNLOAD = 80003
|
|
||||||
PERSON_NOT_EXIST_USER = 80004
|
|
||||||
PERSON_EXIST_FRIEND = 80005
|
|
||||||
PERSON_MYSELF = 80006
|
|
||||||
)
|
)
|
||||||
|
|
||||||
var MsgFlags = map[int]string{
|
var MsgFlags = map[int]string{
|
||||||
SUCCESS: "ok",
|
SUCCESS: "ok",
|
||||||
ERROR: "fail",
|
SERVICE_ERROR: "Fail",
|
||||||
|
CLIENT_ERROR: "Fail",
|
||||||
INVALID_PARAMS: "Parameters Error",
|
INVALID_PARAMS: "Parameters Error",
|
||||||
ERROR_AUTH_TOKEN: "Error auth token",
|
ERROR_AUTH_TOKEN: "Error auth token",
|
||||||
|
|
||||||
@@ -84,6 +83,10 @@ var MsgFlags = map[int]string{
|
|||||||
FILE_OR_DIR_EXISTS: "File or folder already exists",
|
FILE_OR_DIR_EXISTS: "File or folder already exists",
|
||||||
PORT_IS_OCCUPIED: "Port is occupied",
|
PORT_IS_OCCUPIED: "Port is occupied",
|
||||||
VERIFICATION_FAILURE: "Verification failure",
|
VERIFICATION_FAILURE: "Verification failure",
|
||||||
|
Record_ALREADY_EXIST: "Record already exists",
|
||||||
|
Record_NOT_EXIST: "Record does not exist",
|
||||||
|
SERVICE_NOT_RUNNING: "Service is not running",
|
||||||
|
CHARACTER_LIMIT: "Only uppercase letters, lowercase letters and numbers are allowed for username and password.",
|
||||||
|
|
||||||
//app
|
//app
|
||||||
UNINSTALL_APP_ERROR: "Error uninstalling app",
|
UNINSTALL_APP_ERROR: "Error uninstalling app",
|
||||||
@@ -97,31 +100,26 @@ var MsgFlags = map[int]string{
|
|||||||
REMOVE_MOUNT_POINT_ERROR: "Failed to remove mount point",
|
REMOVE_MOUNT_POINT_ERROR: "Failed to remove mount point",
|
||||||
DISK_BUSYING: "Drive is busy",
|
DISK_BUSYING: "Drive is busy",
|
||||||
FORMAT_ERROR: "Formatting failed, please check if the directory is occupied",
|
FORMAT_ERROR: "Formatting failed, please check if the directory is occupied",
|
||||||
|
//share
|
||||||
|
SHARE_ALREADY_EXISTS: "Share already exists",
|
||||||
|
SHARE_NAME_ALREADY_EXISTS: "Share name already exists",
|
||||||
//
|
//
|
||||||
SOURCE_DES_SAME: "Source and destination cannot be the same.",
|
SOURCE_DES_SAME: "Source and destination cannot be the same.",
|
||||||
FILE_DOES_NOT_EXIST: "File does not exist",
|
FILE_DOES_NOT_EXIST: "File does not exist",
|
||||||
|
|
||||||
DIR_NOT_EXISTS: "Directory does not exist",
|
DIR_NOT_EXISTS: "Directory does not exist",
|
||||||
|
|
||||||
FILE_READ_ERROR: "File read error",
|
FILE_READ_ERROR: "File read error",
|
||||||
FILE_DELETE_ERROR: "Delete error",
|
FILE_DELETE_ERROR: "Delete error",
|
||||||
SHORTCUTS_URL_ERROR: "URL error",
|
|
||||||
|
|
||||||
PERSON_REMOTE_ERROR: "Remote connection error",
|
|
||||||
PERSON_DOWN_NOT_EXIST: "Download record does not exist",
|
|
||||||
PERSON_EXIST_DOWNLOAD: "The same download task exists",
|
|
||||||
PERSON_EXIST_FRIEND: "Friend already exist",
|
|
||||||
PERSON_NOT_EXIST_USER: "User does not exist",
|
|
||||||
PERSON_MYSELF: "You can not add yourself",
|
|
||||||
COMMAND_ERROR_INVALID_OPERATION: "invalid operation",
|
COMMAND_ERROR_INVALID_OPERATION: "invalid operation",
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取错误信息
|
// 获取错误信息
|
||||||
func GetMsg(code int) string {
|
func GetMsg(code int) string {
|
||||||
msg, ok := MsgFlags[code]
|
msg, ok := MsgFlags[code]
|
||||||
if ok {
|
if ok {
|
||||||
return msg
|
return msg
|
||||||
}
|
}
|
||||||
return MsgFlags[ERROR]
|
return MsgFlags[SERVICE_ERROR]
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,26 +0,0 @@
|
|||||||
package env_helper
|
|
||||||
|
|
||||||
import "strings"
|
|
||||||
|
|
||||||
func ReplaceDefaultENV(key, tz string) string {
|
|
||||||
temp := ""
|
|
||||||
switch key {
|
|
||||||
case "$DefaultPassword":
|
|
||||||
temp = "casaos"
|
|
||||||
case "$DefaultUserName":
|
|
||||||
temp = "admin"
|
|
||||||
|
|
||||||
case "$PUID":
|
|
||||||
temp = "1000"
|
|
||||||
case "$PGID":
|
|
||||||
temp = "1000"
|
|
||||||
case "$TZ":
|
|
||||||
temp = tz
|
|
||||||
}
|
|
||||||
return temp
|
|
||||||
}
|
|
||||||
|
|
||||||
//replace env default setting
|
|
||||||
func ReplaceStringDefaultENV(str string) string {
|
|
||||||
return strings.ReplaceAll(strings.ReplaceAll(str, "$DefaultPassword", ReplaceDefaultENV("$DefaultPassword", "")), "$DefaultUserName", ReplaceDefaultENV("$DefaultUserName", ""))
|
|
||||||
}
|
|
||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
@@ -60,7 +61,7 @@ func MkDir(src string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
os.Chmod(src, 0777)
|
os.Chmod(src, 0o777)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -103,7 +104,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) {
|
|||||||
return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err)
|
return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
|
f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Fail to OpenFile :%v", err)
|
return nil, fmt.Errorf("Fail to OpenFile :%v", err)
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) {
|
|||||||
|
|
||||||
// 判断所给路径文件/文件夹是否存在
|
// 判断所给路径文件/文件夹是否存在
|
||||||
func Exists(path string) bool {
|
func Exists(path string) bool {
|
||||||
_, err := os.Stat(path) //os.Stat获取文件信息
|
_, err := os.Stat(path) // os.Stat获取文件信息
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsExist(err) {
|
if os.IsExist(err) {
|
||||||
return true
|
return true
|
||||||
@@ -147,7 +148,7 @@ func CreateFile(path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CreateFileAndWriteContent(path string, content string) error {
|
func CreateFileAndWriteContent(path string, content string) error {
|
||||||
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666)
|
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -163,7 +164,7 @@ func CreateFileAndWriteContent(path string, content string) error {
|
|||||||
|
|
||||||
// IsNotExistMkDir create a directory if it does not exist
|
// IsNotExistMkDir create a directory if it does not exist
|
||||||
func IsNotExistCreateFile(src string) error {
|
func IsNotExistCreateFile(src string) error {
|
||||||
if notExist := CheckNotExist(src); notExist == true {
|
if notExist := CheckNotExist(src); notExist {
|
||||||
if err := CreateFile(src); err != nil {
|
if err := CreateFile(src); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -267,7 +268,7 @@ func CopySingleFile(src, dst, style string) error {
|
|||||||
return os.Chmod(dst, srcinfo.Mode())
|
return os.Chmod(dst, srcinfo.Mode())
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check for duplicate file names
|
// Check for duplicate file names
|
||||||
func GetNoDuplicateFileName(fullPath string) string {
|
func GetNoDuplicateFileName(fullPath string) string {
|
||||||
path, fileName := filepath.Split(fullPath)
|
path, fileName := filepath.Split(fullPath)
|
||||||
fileSuffix := path2.Ext(fileName)
|
fileSuffix := path2.Ext(fileName)
|
||||||
@@ -293,7 +294,7 @@ func CopyDir(src string, dst string, style string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
//dstPath := dst
|
// dstPath := dst
|
||||||
lastPath := src[strings.LastIndex(src, "/")+1:]
|
lastPath := src[strings.LastIndex(src, "/")+1:]
|
||||||
dst += "/" + lastPath
|
dst += "/" + lastPath
|
||||||
// for i := 0; Exists(dst); i++ {
|
// for i := 0; Exists(dst); i++ {
|
||||||
@@ -314,7 +315,7 @@ func CopyDir(src string, dst string, style string) error {
|
|||||||
}
|
}
|
||||||
for _, fd := range fds {
|
for _, fd := range fds {
|
||||||
srcfp := path.Join(src, fd.Name())
|
srcfp := path.Join(src, fd.Name())
|
||||||
dstfp := dst //path.Join(dst, fd.Name())
|
dstfp := dst // path.Join(dst, fd.Name())
|
||||||
|
|
||||||
if fd.IsDir() {
|
if fd.IsDir() {
|
||||||
if err = CopyDir(srcfp, dstfp, style); err != nil {
|
if err = CopyDir(srcfp, dstfp, style); err != nil {
|
||||||
@@ -336,10 +337,17 @@ func WriteToPath(data []byte, path, name string) error {
|
|||||||
} else {
|
} else {
|
||||||
fullPath += "/" + name
|
fullPath += "/" + name
|
||||||
}
|
}
|
||||||
IsNotExistCreateFile(fullPath)
|
return WriteToFullPath(data, fullPath, 0o666)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error {
|
||||||
|
if err := IsNotExistCreateFile(fullPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
file, err := os.OpenFile(fullPath,
|
file, err := os.OpenFile(fullPath,
|
||||||
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
||||||
0666,
|
perm,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -350,26 +358,31 @@ func WriteToPath(data []byte, path, name string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//最终拼接
|
// 最终拼接
|
||||||
func SpliceFiles(dir, path string, length int, startPoint int) error {
|
func SpliceFiles(dir, path string, length int, startPoint int) error {
|
||||||
|
|
||||||
fullPath := path
|
fullPath := path
|
||||||
|
|
||||||
IsNotExistCreateFile(fullPath)
|
if err := IsNotExistCreateFile(fullPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
file, _ := os.OpenFile(fullPath,
|
file, _ := os.OpenFile(fullPath,
|
||||||
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
||||||
0666,
|
0o666,
|
||||||
)
|
)
|
||||||
|
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
bufferedWriter := bufio.NewWriter(file)
|
bufferedWriter := bufio.NewWriter(file)
|
||||||
for i := 0; i < length+startPoint; i++ {
|
|
||||||
|
// todo: here should have a goroutine to remove each partial file after it is read, to save disk space
|
||||||
|
|
||||||
|
for i := 0; i < length+startPoint-1; i++ {
|
||||||
data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint))
|
data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = bufferedWriter.Write(data)
|
if _, err := bufferedWriter.Write(data); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster write
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -380,7 +393,6 @@ func SpliceFiles(dir, path string, length int, startPoint int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
|
func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case "zip", "":
|
case "zip", "":
|
||||||
return ".zip", archiver.NewZip(), nil
|
return ".zip", archiver.NewZip(), nil
|
||||||
@@ -400,8 +412,8 @@ func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
|
|||||||
return "", nil, errors.New("format not implemented")
|
return "", nil, errors.New("format not implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func AddFile(ar archiver.Writer, path, commonPath string) error {
|
|
||||||
|
|
||||||
|
func AddFile(ar archiver.Writer, path, commonPath string) error {
|
||||||
info, err := os.Stat(path)
|
info, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -447,6 +459,7 @@ func AddFile(ar archiver.Writer, path, commonPath string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CommonPrefix(sep byte, paths ...string) string {
|
func CommonPrefix(sep byte, paths ...string) string {
|
||||||
// Handle special cases.
|
// Handle special cases.
|
||||||
switch len(paths) {
|
switch len(paths) {
|
||||||
@@ -513,7 +526,7 @@ func GetFileOrDirSize(path string) (int64, error) {
|
|||||||
return fileInfo.Size(), nil
|
return fileInfo.Size(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//getFileSize get file size by path(B)
|
// getFileSize get file size by path(B)
|
||||||
func DirSizeB(path string) (int64, error) {
|
func DirSizeB(path string) (int64, error) {
|
||||||
var size int64
|
var size int64
|
||||||
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
|
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
|
||||||
@@ -547,3 +560,20 @@ func MoveFile(sourcePath, destPath string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ReadLine(lineNumber int, path string) string {
|
||||||
|
file, err := os.Open(path)
|
||||||
|
if err != nil {
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
fileScanner := bufio.NewScanner(file)
|
||||||
|
lineCount := 1
|
||||||
|
for fileScanner.Scan() {
|
||||||
|
if lineCount == lineNumber {
|
||||||
|
return fileScanner.Text()
|
||||||
|
}
|
||||||
|
lineCount++
|
||||||
|
}
|
||||||
|
defer file.Close()
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|||||||
@@ -12,9 +12,9 @@ import (
|
|||||||
"github.com/tidwall/gjson"
|
"github.com/tidwall/gjson"
|
||||||
)
|
)
|
||||||
|
|
||||||
//发送GET请求
|
// 发送GET请求
|
||||||
//url:请求地址
|
// url:请求地址
|
||||||
//response:请求返回的内容
|
// response:请求返回的内容
|
||||||
func Get(url string, head map[string]string) (response string) {
|
func Get(url string, head map[string]string) (response string) {
|
||||||
client := &http.Client{Timeout: 30 * time.Second}
|
client := &http.Client{Timeout: 30 * time.Second}
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
@@ -28,10 +28,10 @@ func Get(url string, head map[string]string) (response string) {
|
|||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
//需要错误日志的处理
|
// 需要错误日志的处理
|
||||||
//loger.Error(error)
|
// logger.Error(error)
|
||||||
return ""
|
return ""
|
||||||
//panic(error)
|
// panic(error)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
var buffer [512]byte
|
var buffer [512]byte
|
||||||
@@ -42,7 +42,7 @@ func Get(url string, head map[string]string) (response string) {
|
|||||||
if err != nil && err == io.EOF {
|
if err != nil && err == io.EOF {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
//loger.Error(err)
|
// logger.Error(err)
|
||||||
return ""
|
return ""
|
||||||
// panic(err)
|
// panic(err)
|
||||||
}
|
}
|
||||||
@@ -51,22 +51,21 @@ func Get(url string, head map[string]string) (response string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//发送GET请求
|
// 发送GET请求
|
||||||
//url:请求地址
|
// url:请求地址
|
||||||
//response:请求返回的内容
|
// response:请求返回的内容
|
||||||
func PersonGet(url string) (response string) {
|
func PersonGet(url string) (response string) {
|
||||||
client := &http.Client{Timeout: 5 * time.Second}
|
client := &http.Client{Timeout: 5 * time.Second}
|
||||||
req, err := http.NewRequest("GET", url, nil)
|
req, err := http.NewRequest("GET", url, nil)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
resp, err := client.Do(req)
|
resp, err := client.Do(req)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
//需要错误日志的处理
|
// 需要错误日志的处理
|
||||||
//loger.Error(error)
|
// logger.Error(error)
|
||||||
return ""
|
return ""
|
||||||
//panic(error)
|
// panic(error)
|
||||||
}
|
}
|
||||||
defer resp.Body.Close()
|
defer resp.Body.Close()
|
||||||
var buffer [512]byte
|
var buffer [512]byte
|
||||||
@@ -77,7 +76,7 @@ func PersonGet(url string) (response string) {
|
|||||||
if err != nil && err == io.EOF {
|
if err != nil && err == io.EOF {
|
||||||
break
|
break
|
||||||
} else if err != nil {
|
} else if err != nil {
|
||||||
//loger.Error(err)
|
// logger.Error(err)
|
||||||
return ""
|
return ""
|
||||||
// panic(err)
|
// panic(err)
|
||||||
}
|
}
|
||||||
@@ -86,11 +85,10 @@ func PersonGet(url string) (response string) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//发送POST请求
|
// 发送POST请求
|
||||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
// url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
||||||
//content:请求放回的内容
|
// content:请求放回的内容
|
||||||
func Post(url string, data []byte, contentType string, head map[string]string) (content string) {
|
func Post(url string, data []byte, contentType string, head map[string]string) (content string) {
|
||||||
|
|
||||||
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
req, err := http.NewRequest("POST", url, bytes.NewBuffer(data))
|
||||||
req.Header.Add("content-type", contentType)
|
req.Header.Add("content-type", contentType)
|
||||||
for k, v := range head {
|
for k, v := range head {
|
||||||
@@ -113,9 +111,9 @@ func Post(url string, data []byte, contentType string, head map[string]string) (
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//发送POST请求
|
// 发送POST请求
|
||||||
//url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
// url:请求地址,data:POST请求提交的数据,contentType:请求体格式,如:application/json
|
||||||
//content:请求放回的内容
|
// content:请求放回的内容
|
||||||
func ZeroTierGet(url string, head map[string]string) (content string, code int) {
|
func ZeroTierGet(url string, head map[string]string) (content string, code int) {
|
||||||
req, err := http.NewRequest(http.MethodGet, url, nil)
|
req, err := http.NewRequest(http.MethodGet, url, nil)
|
||||||
for k, v := range head {
|
for k, v := range head {
|
||||||
@@ -138,11 +136,10 @@ func ZeroTierGet(url string, head map[string]string) (content string, code int)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//发送GET请求
|
// 发送GET请求
|
||||||
//url:请求地址
|
// url:请求地址
|
||||||
//response:请求返回的内容
|
// response:请求返回的内容
|
||||||
func OasisGet(url string) (response string) {
|
func OasisGet(url string) (response string) {
|
||||||
|
|
||||||
head := make(map[string]string)
|
head := make(map[string]string)
|
||||||
|
|
||||||
t := make(chan string)
|
t := make(chan string)
|
||||||
@@ -155,5 +152,4 @@ func OasisGet(url string) (response string) {
|
|||||||
head["Authorization"] = <-t
|
head["Authorization"] = <-t
|
||||||
|
|
||||||
return Get(url, head)
|
return Get(url, head)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,100 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2021-09-30 18:18:14
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-06-24 10:02:46
|
|
||||||
* @FilePath: /CasaOS/pkg/utils/jwt/jwt.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package jwt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
jwt "github.com/golang-jwt/jwt/v4"
|
|
||||||
)
|
|
||||||
|
|
||||||
// type Claims struct {
|
|
||||||
// UserName string `json:"username"`
|
|
||||||
// PassWord string `json:"password"`
|
|
||||||
// Id int `json:"id"`
|
|
||||||
// jwt.RegisteredClaims
|
|
||||||
// }
|
|
||||||
|
|
||||||
// var jwtSecret []byte
|
|
||||||
|
|
||||||
// //创建token
|
|
||||||
// func GenerateToken(username, password string, id int, issuer string, t time.Duration) (string, error) {
|
|
||||||
// clims := Claims{
|
|
||||||
// username,
|
|
||||||
// password,
|
|
||||||
// id,
|
|
||||||
// jwt.RegisteredClaims{
|
|
||||||
// ExpiresAt: jwt.NewNumericDate(time.Now().Add(t)),
|
|
||||||
// IssuedAt: jwt.NewNumericDate(time.Now()),
|
|
||||||
// NotBefore: jwt.NewNumericDate(time.Now()),
|
|
||||||
// Issuer: issuer,
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
|
|
||||||
// tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, clims)
|
|
||||||
// token, err := tokenClaims.SignedString(jwtSecret)
|
|
||||||
// return token, err
|
|
||||||
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //解析token
|
|
||||||
// func ParseToken(token string) (*Claims, error) {
|
|
||||||
// tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
|
||||||
// return jwtSecret, nil
|
|
||||||
// })
|
|
||||||
// if tokenClaims != nil {
|
|
||||||
// if clims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
|
|
||||||
// return clims, nil
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
|
|
||||||
//****************** soon to be removed ******************
|
|
||||||
|
|
||||||
type Claims struct {
|
|
||||||
UserName string `json:"username"`
|
|
||||||
PassWord string `json:"password"`
|
|
||||||
jwt.StandardClaims
|
|
||||||
}
|
|
||||||
|
|
||||||
var jwtSecret []byte
|
|
||||||
|
|
||||||
//创建token
|
|
||||||
func GenerateToken(username, password string) (string, error) {
|
|
||||||
expireTime := time.Now().AddDate(999, 0, 0)
|
|
||||||
clims := Claims{
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
jwt.StandardClaims{
|
|
||||||
ExpiresAt: expireTime.Unix(),
|
|
||||||
Issuer: "gin-blog",
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, clims)
|
|
||||||
token, err := tokenClaims.SignedString(jwtSecret)
|
|
||||||
return token, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//解析token
|
|
||||||
func ParseToken(token string) (*Claims, error) {
|
|
||||||
tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
|
||||||
return jwtSecret, nil
|
|
||||||
})
|
|
||||||
if tokenClaims != nil {
|
|
||||||
if clims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid {
|
|
||||||
return clims, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
@@ -1,113 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-06-17 14:01:25
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-07-04 16:26:22
|
|
||||||
* @FilePath: /CasaOS/pkg/utils/jwt/jwt_helper.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package jwt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// func JWT() gin.HandlerFunc {
|
|
||||||
// return func(c *gin.Context) {
|
|
||||||
// var code int
|
|
||||||
// code = common_err.SUCCESS
|
|
||||||
// token := c.GetHeader("Authorization")
|
|
||||||
// if len(token) == 0 {
|
|
||||||
// token = c.Query("token")
|
|
||||||
// }
|
|
||||||
// if token == "" {
|
|
||||||
// code = common_err.INVALID_PARAMS
|
|
||||||
// }
|
|
||||||
|
|
||||||
// claims, err := ParseToken(token)
|
|
||||||
// //_, err := ParseToken(token)
|
|
||||||
// if err != nil {
|
|
||||||
// code = common_err.ERROR_AUTH_TOKEN
|
|
||||||
// } else if !claims.VerifyExpiresAt(time.Now(), true) || !claims.VerifyIssuer("casaos", true) {
|
|
||||||
// code = common_err.ERROR_AUTH_TOKEN
|
|
||||||
// }
|
|
||||||
// if code != common_err.SUCCESS {
|
|
||||||
// c.JSON(code, model.Result{Success: code, Message: common_err.GetMsg(code)})
|
|
||||||
// c.Abort()
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// c.Request.Header.Add("user_id", strconv.Itoa(claims.Id))
|
|
||||||
// c.Next()
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// //get AccessToken
|
|
||||||
// func GetAccessToken(username, pwd string, id int) string {
|
|
||||||
// token, err := GenerateToken(username, pwd, id, "casaos", 3*time.Hour*time.Duration(1))
|
|
||||||
// if err == nil {
|
|
||||||
// return token
|
|
||||||
// } else {
|
|
||||||
// loger2.Error(fmt.Sprintf("Get Token Fail: %V", err))
|
|
||||||
// return ""
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func GetRefreshToken(username, pwd string, id int) string {
|
|
||||||
// token, err := GenerateToken(username, pwd, id, "fresh", 7*24*time.Hour*time.Duration(1))
|
|
||||||
// if err == nil {
|
|
||||||
// return token
|
|
||||||
// } else {
|
|
||||||
// loger2.Error(fmt.Sprintf("Get Token Fail: %V", err))
|
|
||||||
// return ""
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
|
||||||
//*************** soon to be removed *****************
|
|
||||||
|
|
||||||
func JWT() gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
var code int
|
|
||||||
code = common_err.SUCCESS
|
|
||||||
token := c.GetHeader("Authorization")
|
|
||||||
if len(token) == 0 {
|
|
||||||
token = c.Query("token")
|
|
||||||
}
|
|
||||||
if token == "" {
|
|
||||||
code = common_err.INVALID_PARAMS
|
|
||||||
}
|
|
||||||
|
|
||||||
//claims, err := ParseToken(token)
|
|
||||||
_, err := ParseToken(token)
|
|
||||||
if err != nil {
|
|
||||||
code = common_err.ERROR_AUTH_TOKEN
|
|
||||||
|
|
||||||
}
|
|
||||||
//else if time.Now().Unix() > claims.ExpiresAt {
|
|
||||||
// code = oasis_err2.ERROR_AUTH_TOKEN
|
|
||||||
//}
|
|
||||||
|
|
||||||
if code != common_err.SUCCESS {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: code, Message: common_err.GetMsg(code)})
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取token
|
|
||||||
func GetToken(username, pwd string) string {
|
|
||||||
token, err := GenerateToken(username, pwd)
|
|
||||||
if err == nil {
|
|
||||||
return token
|
|
||||||
} else {
|
|
||||||
//loger2.NewOLoger().Fatal(fmt.Sprintf("Get Token Fail: %V", err))
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,92 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-06-02 15:09:38
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-06-27 15:47:49
|
|
||||||
* @FilePath: /CasaOS/pkg/utils/loger/log.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package loger
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"go.uber.org/zap/zapcore"
|
|
||||||
"gopkg.in/natefinch/lumberjack.v2"
|
|
||||||
)
|
|
||||||
|
|
||||||
var loggers *zap.Logger
|
|
||||||
|
|
||||||
func getFileLogWriter() (writeSyncer zapcore.WriteSyncer) {
|
|
||||||
// 使用 lumberjack 实现 log rotate
|
|
||||||
lumberJackLogger := &lumberjack.Logger{
|
|
||||||
Filename: filepath.Join(config.AppInfo.LogPath, fmt.Sprintf("%s.%s",
|
|
||||||
config.AppInfo.LogSaveName,
|
|
||||||
config.AppInfo.LogFileExt,
|
|
||||||
)),
|
|
||||||
MaxSize: 10,
|
|
||||||
MaxBackups: 60,
|
|
||||||
MaxAge: 1,
|
|
||||||
Compress: true,
|
|
||||||
}
|
|
||||||
|
|
||||||
return zapcore.AddSync(lumberJackLogger)
|
|
||||||
}
|
|
||||||
|
|
||||||
func LogInit() {
|
|
||||||
encoderConfig := zap.NewProductionEncoderConfig()
|
|
||||||
encoderConfig.EncodeTime = zapcore.EpochTimeEncoder
|
|
||||||
encoder := zapcore.NewJSONEncoder(encoderConfig)
|
|
||||||
fileWriteSyncer := getFileLogWriter()
|
|
||||||
core := zapcore.NewTee(
|
|
||||||
zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), zapcore.InfoLevel),
|
|
||||||
zapcore.NewCore(encoder, fileWriteSyncer, zapcore.InfoLevel),
|
|
||||||
)
|
|
||||||
loggers = zap.New(core)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func Info(message string, fields ...zap.Field) {
|
|
||||||
callerFields := getCallerInfoForLog()
|
|
||||||
fields = append(fields, callerFields...)
|
|
||||||
loggers.Info(message, fields...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Debug(message string, fields ...zap.Field) {
|
|
||||||
callerFields := getCallerInfoForLog()
|
|
||||||
fields = append(fields, callerFields...)
|
|
||||||
loggers.Debug(message, fields...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Error(message string, fields ...zap.Field) {
|
|
||||||
callerFields := getCallerInfoForLog()
|
|
||||||
fields = append(fields, callerFields...)
|
|
||||||
loggers.Error(message, fields...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Warn(message string, fields ...zap.Field) {
|
|
||||||
callerFields := getCallerInfoForLog()
|
|
||||||
fields = append(fields, callerFields...)
|
|
||||||
loggers.Warn(message, fields...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func getCallerInfoForLog() (callerFields []zap.Field) {
|
|
||||||
|
|
||||||
pc, file, line, ok := runtime.Caller(2) // 回溯两层,拿到写日志的调用方的函数信息
|
|
||||||
if !ok {
|
|
||||||
return
|
|
||||||
}
|
|
||||||
funcName := runtime.FuncForPC(pc).Name()
|
|
||||||
funcName = path.Base(funcName) //Base函数返回路径的最后一个元素,只保留函数名
|
|
||||||
|
|
||||||
callerFields = append(callerFields, zap.String("func", funcName), zap.String("file", file), zap.Int("line", line))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
@@ -1,68 +0,0 @@
|
|||||||
package port
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net"
|
|
||||||
)
|
|
||||||
|
|
||||||
// 获取可用端口
|
|
||||||
func GetAvailablePort(t string) (int, error) {
|
|
||||||
address := fmt.Sprintf("%s:0", "0.0.0.0")
|
|
||||||
if t == "udp" {
|
|
||||||
add, err := net.ResolveUDPAddr(t, address)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
listener, err := net.ListenUDP(t, add)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer listener.Close()
|
|
||||||
return listener.LocalAddr().(*net.UDPAddr).Port, nil
|
|
||||||
} else {
|
|
||||||
add, err := net.ResolveTCPAddr(t, address)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
listener, err := net.ListenTCP(t, add)
|
|
||||||
if err != nil {
|
|
||||||
return 0, err
|
|
||||||
}
|
|
||||||
|
|
||||||
defer listener.Close()
|
|
||||||
return listener.Addr().(*net.TCPAddr).Port, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// 判断端口是否可以(未被占用)
|
|
||||||
// param t tcp/udp
|
|
||||||
func IsPortAvailable(port int, t string) bool {
|
|
||||||
address := fmt.Sprintf("%s:%d", "0.0.0.0", port)
|
|
||||||
if t == "udp" {
|
|
||||||
sadd, err := net.ResolveUDPAddr("udp", address)
|
|
||||||
uc, err := net.ListenUDP("udp", sadd)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err.Error())
|
|
||||||
return false
|
|
||||||
} else {
|
|
||||||
defer uc.Close()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
} else {
|
|
||||||
listener, err := net.Listen(t, address)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
//log.Infof("port %s is taken: %s", address, err)
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
defer listener.Close()
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
package port
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestPortAvailable(t *testing.T) {
|
|
||||||
// fmt.Println(PortAvailable())
|
|
||||||
//fmt.Println(IsPortAvailable(6881,"tcp"))
|
|
||||||
p, _ := GetAvailablePort("udp")
|
|
||||||
fmt.Println("udp", p)
|
|
||||||
fmt.Println(IsPortAvailable(p, "udp"))
|
|
||||||
|
|
||||||
t1, _ := GetAvailablePort("tcp")
|
|
||||||
fmt.Println("tcp", t1)
|
|
||||||
fmt.Println(IsPortAvailable(t1, "tcp"))
|
|
||||||
}
|
|
||||||
@@ -1,24 +0,0 @@
|
|||||||
package random
|
|
||||||
|
|
||||||
import (
|
|
||||||
"math/rand"
|
|
||||||
"time"
|
|
||||||
)
|
|
||||||
|
|
||||||
func RandomString(n int, onlyLetter bool) string {
|
|
||||||
|
|
||||||
var letters []rune
|
|
||||||
|
|
||||||
if onlyLetter {
|
|
||||||
letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ")
|
|
||||||
} else {
|
|
||||||
letters = []rune("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789")
|
|
||||||
}
|
|
||||||
|
|
||||||
b := make([]rune, n)
|
|
||||||
rand.Seed(time.Now().UnixNano())
|
|
||||||
for i := range b {
|
|
||||||
b[i] = letters[rand.Intn(len(letters))]
|
|
||||||
}
|
|
||||||
return string(b)
|
|
||||||
}
|
|
||||||
@@ -1,10 +0,0 @@
|
|||||||
package random
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestRandomString(t *testing.T) {
|
|
||||||
fmt.Println(RandomString(6, true))
|
|
||||||
}
|
|
||||||
33
pkg/utils/udev_helper.go
Normal file
33
pkg/utils/udev_helper.go
Normal file
@@ -0,0 +1,33 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-08-10 16:06:12
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-10 16:11:37
|
||||||
|
* @FilePath: /CasaOS/pkg/utils/udev_helper.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package utils
|
||||||
|
|
||||||
|
// func getOptionnalMatcher() (matcher netlink.Matcher, err error) {
|
||||||
|
// if filePath == nil || *filePath == "" {
|
||||||
|
// return nil, nil
|
||||||
|
// }
|
||||||
|
|
||||||
|
// stream, err := ioutil.ReadFile(*filePath)
|
||||||
|
// if err != nil {
|
||||||
|
// return nil, err
|
||||||
|
// }
|
||||||
|
|
||||||
|
// if stream == nil {
|
||||||
|
// return nil, fmt.Errorf("Empty, no rules provided in \"%s\", err: %w", *filePath, err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// var rules netlink.RuleDefinitions
|
||||||
|
// if err := json.Unmarshal(stream, &rules); err != nil {
|
||||||
|
// return nil, fmt.Errorf("Wrong rule syntax, err: %w", err)
|
||||||
|
// }
|
||||||
|
|
||||||
|
// return &rules, nil
|
||||||
|
// }
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2022-05-13 18:15:46
|
* @Date: 2022-05-13 18:15:46
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-06-29 14:29:34
|
* @LastEditTime: 2022-07-21 15:27:53
|
||||||
* @FilePath: /CasaOS/pkg/utils/version/version.go
|
* @FilePath: /CasaOS/pkg/utils/version/version.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -33,9 +33,6 @@ func IsNeedUpdate(version model.Version) (bool, model.Version) {
|
|||||||
for i := 0; i < len(v1); i++ {
|
for i := 0; i < len(v1); i++ {
|
||||||
a, _ := strconv.Atoi(v1[i])
|
a, _ := strconv.Atoi(v1[i])
|
||||||
b, _ := strconv.Atoi(v2[i])
|
b, _ := strconv.Atoi(v2[i])
|
||||||
if i == 0 && a > b {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if a > b {
|
if a > b {
|
||||||
return true, version
|
return true, version
|
||||||
}
|
}
|
||||||
|
|||||||
25
route/darwin.go
Normal file
25
route/darwin.go
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
//go:build darwin
|
||||||
|
// +build darwin
|
||||||
|
|
||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-08-12 14:22:28
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-09-05 16:27:55
|
||||||
|
* @FilePath: /CasaOS/route/darwin.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
|
||||||
|
package route
|
||||||
|
|
||||||
|
func MonitoryUSB() {
|
||||||
|
|
||||||
|
}
|
||||||
|
func SendAllHardwareStatusBySocket() {
|
||||||
|
|
||||||
|
}
|
||||||
|
func SendUSBBySocket() {
|
||||||
|
|
||||||
|
}
|
||||||
335
route/init.go
335
route/init.go
@@ -1,295 +1,92 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-11-15 15:51:44
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-11-15 15:55:16
|
||||||
|
* @FilePath: /CasaOS/route/init.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/xml"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/model/system_app"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
"github.com/IceWhaleTech/CasaOS/pkg/samba"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
uuid "github.com/satori/go.uuid"
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitFunction() {
|
func InitFunction() {
|
||||||
go checkSystemApp()
|
go InitNetworkMount()
|
||||||
ShellInit()
|
go InitInfo()
|
||||||
CheckSerialDiskMount()
|
|
||||||
|
|
||||||
CheckToken2_11()
|
|
||||||
ImportApplications()
|
|
||||||
ChangeAPIUrl()
|
|
||||||
|
|
||||||
MoveUserToDB()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
var syncIsExistence = false
|
func InitInfo() {
|
||||||
|
mb := model.BaseInfo{}
|
||||||
func installSyncthing(appId string) {
|
if file.Exists(config.AppInfo.DBPath + "/baseinfo.conf") {
|
||||||
|
err := json.Unmarshal(file.ReadFullFile(config.AppInfo.DBPath+"/baseinfo.conf"), &mb)
|
||||||
var appInfo model.ServerAppList
|
|
||||||
m := model.CustomizationPostData{}
|
|
||||||
var dockerImage string
|
|
||||||
var dockerImageVersion string
|
|
||||||
appInfo = service.MyService.Casa().GetServerAppInfo(appId, "system", "us_en")
|
|
||||||
dockerImage = appInfo.Image
|
|
||||||
dockerImageVersion = appInfo.ImageVersion
|
|
||||||
|
|
||||||
if len(appInfo.ImageVersion) == 0 {
|
|
||||||
dockerImageVersion = "latest"
|
|
||||||
}
|
|
||||||
|
|
||||||
if appInfo.NetworkModel != "host" {
|
|
||||||
for i := 0; i < len(appInfo.Ports); i++ {
|
|
||||||
if p, _ := strconv.Atoi(appInfo.Ports[i].ContainerPort); port.IsPortAvailable(p, appInfo.Ports[i].Protocol) {
|
|
||||||
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
|
||||||
} else {
|
|
||||||
if appInfo.Ports[i].Protocol == "tcp" {
|
|
||||||
if p, err := port.GetAvailablePort("tcp"); err == nil {
|
|
||||||
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
|
||||||
}
|
|
||||||
} else if appInfo.Ports[i].Protocol == "upd" {
|
|
||||||
if p, err := port.GetAvailablePort("udp"); err == nil {
|
|
||||||
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if appInfo.Ports[i].Type == 0 {
|
|
||||||
appInfo.PortMap = appInfo.Ports[i].CommendPort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(appInfo.Devices); i++ {
|
|
||||||
if !file.CheckNotExist(appInfo.Devices[i].ContainerPath) {
|
|
||||||
appInfo.Devices[i].Path = appInfo.Devices[i].ContainerPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(appInfo.Tip) > 0 {
|
|
||||||
appInfo.Tip = env_helper.ReplaceStringDefaultENV(appInfo.Tip)
|
|
||||||
}
|
|
||||||
|
|
||||||
appInfo.MaxMemory = service.MyService.System().GetMemInfo()["total"].(uint64) >> 20
|
|
||||||
|
|
||||||
id := uuid.NewV4().String()
|
|
||||||
|
|
||||||
// step:下载镜像
|
|
||||||
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, "", "")
|
|
||||||
if err != nil {
|
|
||||||
//pull image error
|
|
||||||
fmt.Println("pull image error", err, dockerImage, dockerImageVersion)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) {
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
|
||||||
|
|
||||||
m.CpuShares = 50
|
|
||||||
m.Envs = appInfo.Envs
|
|
||||||
m.Memory = int64(appInfo.MaxMemory)
|
|
||||||
m.Origin = "system"
|
|
||||||
m.PortMap = appInfo.PortMap
|
|
||||||
m.Ports = appInfo.Ports
|
|
||||||
m.Restart = "always"
|
|
||||||
m.Volumes = appInfo.Volumes
|
|
||||||
m.NetworkModel = appInfo.NetworkModel
|
|
||||||
m.Label = id
|
|
||||||
m.CustomId = id
|
|
||||||
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m)
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println("container create error", err)
|
|
||||||
// create container error
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//step:start container
|
|
||||||
err = service.MyService.Docker().DockerContainerStart(containerId)
|
|
||||||
if err != nil {
|
|
||||||
//start container error
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
checkSystemApp()
|
|
||||||
}
|
|
||||||
|
|
||||||
// check if the system application is installed
|
|
||||||
func checkSystemApp() {
|
|
||||||
list := service.MyService.App().GetSystemAppList()
|
|
||||||
for _, v := range list {
|
|
||||||
info, err := service.MyService.Docker().DockerContainerInfo(v.ID)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
logger.Error("baseinfo.conf", zap.String("error", err.Error()))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if file.Exists("/etc/CHANNEL") {
|
||||||
|
channel := file.ReadFullFile("/etc/CHANNEL")
|
||||||
|
mb.Channel = string(channel)
|
||||||
|
}
|
||||||
|
mac, err := service.MyService.System().GetMacAddress()
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("GetMacAddress", zap.String("error", err.Error()))
|
||||||
|
}
|
||||||
|
mb.Hash = encryption.GetMD5ByStr(mac)
|
||||||
|
mb.Version = types.CURRENTVERSION
|
||||||
|
os.Remove(config.AppInfo.DBPath + "/baseinfo.conf")
|
||||||
|
by, err := json.Marshal(mb)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("init info err", zap.Any("err", err))
|
||||||
|
return
|
||||||
|
}
|
||||||
|
file.WriteToFullPath(by, config.AppInfo.DBPath+"/baseinfo.conf", 0o666)
|
||||||
|
}
|
||||||
|
|
||||||
|
func InitNetworkMount() {
|
||||||
|
time.Sleep(time.Second * 10)
|
||||||
|
connections := service.MyService.Connections().GetConnectionsList()
|
||||||
|
for _, v := range connections {
|
||||||
|
connection := service.MyService.Connections().GetConnectionByID(fmt.Sprint(v.ID))
|
||||||
|
directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
|
||||||
|
if err != nil {
|
||||||
|
service.MyService.Connections().DeleteConnection(fmt.Sprint(connection.ID))
|
||||||
|
logger.Error("mount samba err", zap.Any("err", err), zap.Any("info", connection))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
if strings.Contains(info.Config.Image, "linuxserver/syncthing") {
|
baseHostPath := "/mnt/" + connection.Host
|
||||||
if v.State != "running" {
|
|
||||||
//step:start container
|
|
||||||
service.MyService.Docker().DockerContainerStart(v.ID)
|
|
||||||
}
|
|
||||||
syncIsExistence = true
|
|
||||||
if config.SystemConfigInfo.SyncPort != v.Labels["web"] {
|
|
||||||
config.SystemConfigInfo.SyncPort = v.Labels["web"]
|
|
||||||
}
|
|
||||||
|
|
||||||
path := ""
|
mountPointList := service.MyService.System().GetDirPath(baseHostPath)
|
||||||
for _, i := range info.Mounts {
|
for _, v := range mountPointList {
|
||||||
if i.Destination == "/config" {
|
service.MyService.Connections().UnmountSmaba(v.Path)
|
||||||
path = i.Source
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
content := file.ReadFullFile(filepath.Join(path, "config.xml"))
|
|
||||||
syncConfig := &system_app.SyncConfig{}
|
|
||||||
xml.Unmarshal(content, &syncConfig)
|
|
||||||
config.SystemConfigInfo.SyncKey = syncConfig.Key
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if !syncIsExistence {
|
|
||||||
installSyncthing("74")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func CheckSerialDiskMount() {
|
|
||||||
// check mount point
|
|
||||||
dbList := service.MyService.Disk().GetSerialAll()
|
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
mountPoint := make(map[string]string, len(dbList))
|
|
||||||
//remount
|
|
||||||
for _, v := range dbList {
|
|
||||||
mountPoint[v.UUID] = v.MountPoint
|
|
||||||
}
|
|
||||||
for _, v := range list {
|
|
||||||
command.ExecEnabledSMART(v.Path)
|
|
||||||
if v.Children != nil {
|
|
||||||
for _, h := range v.Children {
|
|
||||||
if len(h.MountPoint) == 0 && len(v.Children) == 1 && h.FsType == "ext4" {
|
|
||||||
if m, ok := mountPoint[h.UUID]; ok {
|
|
||||||
//mount point check
|
|
||||||
volume := m
|
|
||||||
if !file.CheckNotExist(m) {
|
|
||||||
for i := 0; file.CheckNotExist(volume); i++ {
|
|
||||||
volume = m + strconv.Itoa(i+1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
service.MyService.Disk().MountDisk(h.Path, volume)
|
|
||||||
if volume != m {
|
|
||||||
ms := model2.SerialDisk{}
|
|
||||||
ms.UUID = v.UUID
|
|
||||||
ms.MountPoint = volume
|
|
||||||
service.MyService.Disk().UpdateMountPoint(ms)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;AutoRemoveUnuseDir")
|
|
||||||
}
|
|
||||||
func ShellInit() {
|
|
||||||
command.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/assist.sh | bash")
|
|
||||||
if !file.CheckNotExist("/casaOS") {
|
|
||||||
command.OnlyExec("source /casaOS/server/shell/update.sh ;")
|
|
||||||
command.OnlyExec("source " + config.AppInfo.ShellPath + "/delete-old-service.sh ;")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
func CheckToken2_11() {
|
|
||||||
if len(config.ServerInfo.Token) == 0 {
|
|
||||||
token := uuid.NewV4().String
|
|
||||||
config.ServerInfo.Token = token()
|
|
||||||
config.Cfg.Section("server").Key("Token").SetValue(token())
|
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
sysType := runtime.GOOS
|
|
||||||
if len(config.FileSettingInfo.DownloadDir) == 0 {
|
|
||||||
downloadPath := "/DATA/Downloads"
|
|
||||||
if sysType == "windows" {
|
|
||||||
downloadPath = "C:\\CasaOS\\DATA\\Downloads"
|
|
||||||
}
|
|
||||||
if sysType == "darwin" {
|
|
||||||
downloadPath = "./CasaOS/DATA/Downloads"
|
|
||||||
}
|
|
||||||
config.Cfg.Section("file").Key("DownloadDir").SetValue(downloadPath)
|
|
||||||
config.FileSettingInfo.DownloadDir = downloadPath
|
|
||||||
file.IsNotExistMkDir(config.FileSettingInfo.DownloadDir)
|
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(config.UserInfo.Description) == 0 {
|
|
||||||
config.Cfg.Section("user").Key("Description").SetValue("nothing")
|
|
||||||
config.UserInfo.Description = "nothing"
|
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
}
|
|
||||||
if len(config.ServerInfo.Handshake) == 0 {
|
|
||||||
config.Cfg.Section("server").Key("Handshake").SetValue("socket.casaos.io")
|
|
||||||
config.ServerInfo.Handshake = "socket.casaos.io"
|
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") {
|
|
||||||
service.MyService.System().UpdateUSBAutoMount("False")
|
|
||||||
service.MyService.System().ExecUSBAutoMountShell("False")
|
|
||||||
}
|
|
||||||
|
|
||||||
// str := []string{}
|
|
||||||
// str = append(str, "ddd")
|
|
||||||
// str = append(str, "aaa")
|
|
||||||
// ddd := strings.Join(str, "|")
|
|
||||||
// config.Cfg.Section("file").Key("ShareDir").SetValue(ddd)
|
|
||||||
|
|
||||||
// config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func ImportApplications() {
|
|
||||||
service.MyService.App().ImportApplications(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0.3.1
|
|
||||||
func ChangeAPIUrl() {
|
|
||||||
|
|
||||||
newAPIUrl := "https://api.casaos.io/casaos-api"
|
|
||||||
if config.ServerInfo.ServerApi == "https://api.casaos.zimaboard.com" {
|
|
||||||
config.ServerInfo.ServerApi = newAPIUrl
|
|
||||||
config.Cfg.Section("server").Key("ServerApi").SetValue(newAPIUrl)
|
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//0.3.3
|
|
||||||
//Transferring user data to the database
|
|
||||||
func MoveUserToDB() {
|
|
||||||
|
|
||||||
if len(config.UserInfo.UserName) > 0 && service.MyService.User().GetUserInfoByUserName(config.UserInfo.UserName).Id == 0 {
|
|
||||||
user := model2.UserDBModel{}
|
|
||||||
user.UserName = config.UserInfo.UserName
|
|
||||||
user.Email = config.UserInfo.Email
|
|
||||||
user.NickName = config.UserInfo.NickName
|
|
||||||
user.Password = encryption.GetMD5ByStr(config.UserInfo.PWD)
|
|
||||||
user.Role = "admin"
|
|
||||||
user = service.MyService.User().CreateUser(user)
|
|
||||||
if user.Id > 0 {
|
|
||||||
userPath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id)
|
|
||||||
file.MkDir(userPath)
|
|
||||||
os.Rename("/casaOS/server/conf/app_order.json", userPath+"/app_order.json")
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
os.RemoveAll(baseHostPath)
|
||||||
|
|
||||||
|
file.IsNotExistMkDir(baseHostPath)
|
||||||
|
for _, v := range directories {
|
||||||
|
mountPoint := baseHostPath + "/" + v
|
||||||
|
file.IsNotExistMkDir(mountPoint)
|
||||||
|
service.MyService.Connections().MountSmaba(connection.Username, connection.Host, v, connection.Port, mountPoint, connection.Password)
|
||||||
|
}
|
||||||
|
connection.Directories = strings.Join(directories, ",")
|
||||||
|
service.MyService.Connections().UpdateConnection(&connection)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,18 +1,11 @@
|
|||||||
|
//go:build !darwin
|
||||||
|
// +build !darwin
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2022-07-01 15:11:36
|
* @Date: 2022-07-01 15:11:36
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-07-01 15:16:00
|
* @LastEditTime: 2022-09-05 16:28:46
|
||||||
* @FilePath: /CasaOS/route/periodical.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-05-27 15:55:36
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-06-29 16:47:19
|
|
||||||
* @FilePath: /CasaOS/route/periodical.go
|
* @FilePath: /CasaOS/route/periodical.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -21,8 +14,6 @@
|
|||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
@@ -62,110 +53,7 @@ func SendMemBySocket() {
|
|||||||
service.MyService.Notify().SendMemInfoBySocket(service.MyService.System().GetMemInfo())
|
service.MyService.Notify().SendMemInfoBySocket(service.MyService.System().GetMemInfo())
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendDiskBySocket() {
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
|
|
||||||
summary := model.Summary{}
|
|
||||||
healthy := true
|
|
||||||
findSystem := 0
|
|
||||||
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
if len(list[i].Children) > 0 && findSystem == 0 {
|
|
||||||
|
|
||||||
for j := 0; j < len(list[i].Children); j++ {
|
|
||||||
|
|
||||||
if len(list[i].Children[j].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children[j].Children {
|
|
||||||
if v.MountPoint == "/" {
|
|
||||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if list[i].Children[j].MountPoint == "/" {
|
|
||||||
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if findSystem == 1 {
|
|
||||||
findSystem += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
|
|
||||||
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
|
||||||
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
|
||||||
healthy = true
|
|
||||||
} else {
|
|
||||||
healthy = temp.SmartStatus.Passed
|
|
||||||
}
|
|
||||||
|
|
||||||
//list[i].Temperature = temp.Temperature.Current
|
|
||||||
|
|
||||||
if len(list[i].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children {
|
|
||||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
summary.Health = healthy
|
|
||||||
service.MyService.Notify().SendDiskInfoBySocket(summary)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendUSBBySocket() {
|
|
||||||
usbList := service.MyService.Disk().LSBLK(false)
|
|
||||||
usb := []model.DriveUSB{}
|
|
||||||
for _, v := range usbList {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Name
|
|
||||||
temp.Size = v.Size
|
|
||||||
mountTemp := true
|
|
||||||
if len(v.Children) == 0 {
|
|
||||||
mountTemp = false
|
|
||||||
}
|
|
||||||
for _, child := range v.Children {
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
temp.Avail += avail
|
|
||||||
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
|
|
||||||
temp.Used += used
|
|
||||||
} else {
|
|
||||||
mountTemp = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
temp.Mount = mountTemp
|
|
||||||
usb = append(usb, temp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
service.MyService.Notify().SendUSBInfoBySocket(usb)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendAllHardwareStatusBySocket() {
|
func SendAllHardwareStatusBySocket() {
|
||||||
|
|
||||||
netList := service.MyService.System().GetNetInfo()
|
netList := service.MyService.System().GetNetInfo()
|
||||||
newNet := []model.IOCountersStat{}
|
newNet := []model.IOCountersStat{}
|
||||||
nets := service.MyService.System().GetNet(true)
|
nets := service.MyService.System().GetNet(true)
|
||||||
@@ -181,105 +69,61 @@ func SendAllHardwareStatusBySocket() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
cpu := service.MyService.System().GetCpuPercent()
|
cpu := service.MyService.System().GetCpuPercent()
|
||||||
|
|
||||||
|
var cpuModel = "arm"
|
||||||
|
if cpu := service.MyService.System().GetCpuInfo(); len(cpu) > 0 {
|
||||||
|
if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "intel") > 0 {
|
||||||
|
cpuModel = "intel"
|
||||||
|
} else if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "amd") > 0 {
|
||||||
|
cpuModel = "amd"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
num := service.MyService.System().GetCpuCoreNum()
|
num := service.MyService.System().GetCpuCoreNum()
|
||||||
cpuData := make(map[string]interface{})
|
cpuData := make(map[string]interface{})
|
||||||
cpuData["percent"] = cpu
|
cpuData["percent"] = cpu
|
||||||
cpuData["num"] = num
|
cpuData["num"] = num
|
||||||
|
cpuData["temperature"] = service.MyService.System().GetCPUTemperature()
|
||||||
|
cpuData["power"] = service.MyService.System().GetCPUPower()
|
||||||
|
cpuData["model"] = cpuModel
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
|
|
||||||
summary := model.Summary{}
|
|
||||||
healthy := true
|
|
||||||
findSystem := 0
|
|
||||||
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
if len(list[i].Children) > 0 && findSystem == 0 {
|
|
||||||
|
|
||||||
for j := 0; j < len(list[i].Children); j++ {
|
|
||||||
|
|
||||||
if len(list[i].Children[j].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children[j].Children {
|
|
||||||
if v.MountPoint == "/" {
|
|
||||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if list[i].Children[j].MountPoint == "/" {
|
|
||||||
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if findSystem == 1 {
|
|
||||||
findSystem += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
|
|
||||||
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
|
||||||
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
|
||||||
healthy = true
|
|
||||||
} else {
|
|
||||||
healthy = temp.SmartStatus.Passed
|
|
||||||
}
|
|
||||||
if len(list[i].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children {
|
|
||||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
summary.Health = healthy
|
|
||||||
|
|
||||||
usbList := service.MyService.Disk().LSBLK(false)
|
|
||||||
usb := []model.DriveUSB{}
|
|
||||||
for _, v := range usbList {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Name
|
|
||||||
temp.Size = v.Size
|
|
||||||
mountTemp := true
|
|
||||||
if len(v.Children) == 0 {
|
|
||||||
mountTemp = false
|
|
||||||
}
|
|
||||||
for _, child := range v.Children {
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
temp.Avail += avail
|
|
||||||
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
|
|
||||||
temp.Used += used
|
|
||||||
} else {
|
|
||||||
mountTemp = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
temp.Mount = mountTemp
|
|
||||||
usb = append(usb, temp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memInfo := service.MyService.System().GetMemInfo()
|
memInfo := service.MyService.System().GetMemInfo()
|
||||||
|
|
||||||
service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memInfo, cpuData, newNet)
|
service.MyService.Notify().SendAllHardwareStatusBySocket(memInfo, cpuData, newNet)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// func MonitoryUSB() {
|
||||||
|
// var matcher netlink.Matcher
|
||||||
|
|
||||||
|
// conn := new(netlink.UEventConn)
|
||||||
|
// if err := conn.Connect(netlink.UdevEvent); err != nil {
|
||||||
|
// logger.Error("udev err", zap.Any("Unable to connect to Netlink Kobject UEvent socket", err))
|
||||||
|
// }
|
||||||
|
// defer conn.Close()
|
||||||
|
|
||||||
|
// queue := make(chan netlink.UEvent)
|
||||||
|
// errors := make(chan error)
|
||||||
|
// quit := conn.Monitor(queue, errors, matcher)
|
||||||
|
|
||||||
|
// signals := make(chan os.Signal, 1)
|
||||||
|
// signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||||
|
// go func() {
|
||||||
|
// <-signals
|
||||||
|
// close(quit)
|
||||||
|
// os.Exit(0)
|
||||||
|
// }()
|
||||||
|
|
||||||
|
// for {
|
||||||
|
// select {
|
||||||
|
// case uevent := <-queue:
|
||||||
|
// if uevent.Env["DEVTYPE"] == "disk" {
|
||||||
|
// time.Sleep(time.Microsecond * 500)
|
||||||
|
// SendUSBBySocket()
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// case err := <-errors:
|
||||||
|
// logger.Error("udev err", zap.Any("err", err))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|||||||
298
route/route.go
298
route/route.go
@@ -1,229 +1,167 @@
|
|||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"os"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/middleware"
|
"github.com/IceWhaleTech/CasaOS-Common/middleware"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
|
|
||||||
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
||||||
"github.com/IceWhaleTech/CasaOS/web"
|
|
||||||
|
|
||||||
"github.com/gin-contrib/gzip"
|
"github.com/gin-contrib/gzip"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
var OnlineDemo bool = false
|
|
||||||
|
|
||||||
func InitRouter() *gin.Engine {
|
func InitRouter() *gin.Engine {
|
||||||
|
ginMode := gin.ReleaseMode
|
||||||
|
if config.ServerInfo.RunMode != "" {
|
||||||
|
ginMode = config.ServerInfo.RunMode
|
||||||
|
}
|
||||||
|
if os.Getenv(gin.EnvGinMode) != "" {
|
||||||
|
ginMode = os.Getenv(gin.EnvGinMode)
|
||||||
|
}
|
||||||
|
gin.SetMode(ginMode)
|
||||||
|
|
||||||
r := gin.Default()
|
r := gin.New()
|
||||||
|
r.Use(gin.Recovery())
|
||||||
r.Use(middleware.Cors())
|
r.Use(middleware.Cors())
|
||||||
r.Use(middleware.WriteLog())
|
|
||||||
r.Use(gzip.Gzip(gzip.DefaultCompression))
|
r.Use(gzip.Gzip(gzip.DefaultCompression))
|
||||||
gin.SetMode(config.ServerInfo.RunMode)
|
if ginMode != gin.ReleaseMode {
|
||||||
r.StaticFS("/ui", http.FS(web.Static))
|
r.Use(middleware.WriteLog())
|
||||||
r.GET("/", WebUIHome)
|
}
|
||||||
|
|
||||||
|
// r.StaticFS("/ui", http.FS(web.Static))
|
||||||
|
// r.GET("/", WebUIHome)
|
||||||
// r.StaticFS("/assets", http.Dir("./static/assets"))
|
// r.StaticFS("/assets", http.Dir("./static/assets"))
|
||||||
// r.StaticFile("/favicon.ico", "./static/favicon.ico")
|
// r.StaticFile("/favicon.ico", "./static/favicon.ico")
|
||||||
//r.GET("/", func(c *gin.Context) {
|
//r.GET("/", func(c *gin.Context) {
|
||||||
// c.Redirect(http.StatusMovedPermanently, "ui/")
|
// c.Redirect(http.StatusMovedPermanently, "ui/")
|
||||||
//})
|
//})
|
||||||
|
|
||||||
r.POST("/v1/user/register/:key", v1.PostUserRegister)
|
// r.POST("/v1/users/register", v1.PostUserRegister)
|
||||||
r.POST("/v1/user/login", v1.PostUserLogin) //
|
// r.POST("/v1/users/login", v1.PostUserLogin)
|
||||||
r.GET("/v1/user/all/name", v1.GetUserAllUserName)
|
// r.GET("/v1/users/name", v1.GetUserAllUsername) //all/name
|
||||||
|
// r.POST("/v1/users/refresh", v1.PostUserRefreshToken)
|
||||||
|
// // No short-term modifications
|
||||||
|
// r.GET("/v1/users/image", v1.GetUserImage)
|
||||||
|
|
||||||
r.GET("/v1/sys/init/check", v1.GetSystemInitCheck)
|
// r.GET("/v1/users/status", v1.GetUserStatus) //init/check
|
||||||
r.GET("/v1/guide/check", v1.GetGuideCheck)
|
// r.GET("/v1/guide/check", v1.GetGuideCheck) // /v1/sys/guide_check
|
||||||
r.GET("/v1/debug", v1.GetSystemConfigDebug)
|
r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug
|
||||||
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
|
|
||||||
r.GET("/v1/user/info/:id", v1.GetUserInfo)
|
|
||||||
r.GET("/v1/user/avatar/:id", v1.GetUserAvatar)
|
|
||||||
r.GET("/v1/user/image", v1.GetUserImage)
|
|
||||||
|
|
||||||
//get user info
|
r.GET("/v1/sys/socket-port", v1.GetSystemSocketPort) //sys/socket_port
|
||||||
r.GET("/v1/person/shareid", v1.GetPersonShareId)
|
r.GET("/v1/sys/version/check", v1.GetSystemCheckVersion)
|
||||||
r.GET("/v1/sys/socket/port", v1.GetSystemSocketPort)
|
r.GET("/ping", func(ctx *gin.Context) {
|
||||||
//r.POST("/v1/user/refresh/token", v1.PostUserRefreshToken)
|
ctx.String(200, "pong")
|
||||||
|
})
|
||||||
v1Group := r.Group("/v1")
|
v1Group := r.Group("/v1")
|
||||||
|
|
||||||
v1Group.Use(jwt2.JWT())
|
v1Group.Use(jwt.ExceptLocalhost())
|
||||||
{
|
{
|
||||||
v1UserGroup := v1Group.Group("/user")
|
|
||||||
v1UserGroup.Use()
|
|
||||||
{
|
|
||||||
|
|
||||||
//****************** New version needs to be modified start ******************
|
|
||||||
//chang user name
|
|
||||||
v1UserGroup.PUT("/username", v1.PutUserName)
|
|
||||||
v1UserGroup.PUT("/password", v1.PutUserPwd)
|
|
||||||
v1UserGroup.PUT("/nick", v1.PutUserNick)
|
|
||||||
v1UserGroup.PUT("/desc", v1.PutUserDesc)
|
|
||||||
v1UserGroup.GET("/info", v1.GetUserInfoByUserName)
|
|
||||||
v1UserGroup.GET("/custom/:id/:key", v1.GetUserCustomConf)
|
|
||||||
v1UserGroup.POST("/custom/:id/:key", v1.PostUserCustomConf)
|
|
||||||
v1UserGroup.DELETE("/custom/:id/:key", v1.DeleteUserCustomConf)
|
|
||||||
v1UserGroup.POST("/upload/image/:id/:key", v1.PostUserUploadImage)
|
|
||||||
v1UserGroup.POST("/file/image/:id/:key", v1.PostUserFileImage)
|
|
||||||
v1UserGroup.DELETE("/image/:id", v1.DeleteUserImage)
|
|
||||||
//****************** New version needs to be modified end ******************
|
|
||||||
|
|
||||||
//****************** soon to be removed start ******************
|
|
||||||
v1UserGroup.POST("/person/info", v1.PostUserPersonInfo)
|
|
||||||
v1UserGroup.GET("/shareid", v1.GetUserShareID)
|
|
||||||
//****************** soon to be removed end ******************
|
|
||||||
|
|
||||||
//v1UserGroup.GET("/info", v1.GetUserInfo)
|
|
||||||
|
|
||||||
v1UserGroup.PUT("/avatar", v1.PutUserAvatar)
|
|
||||||
v1UserGroup.GET("/avatar", v1.GetUserAvatar)
|
|
||||||
v1UserGroup.DELETE("/delete/:id", v1.DeleteUser)
|
|
||||||
|
|
||||||
}
|
|
||||||
v1AppGroup := v1Group.Group("/app")
|
|
||||||
v1AppGroup.Use()
|
|
||||||
{
|
|
||||||
//获取我的已安装的列表
|
|
||||||
v1AppGroup.GET("/my/list", v1.MyAppList)
|
|
||||||
//
|
|
||||||
v1AppGroup.GET("/usage", v1.AppUsageList)
|
|
||||||
//app详情
|
|
||||||
v1AppGroup.GET("/appinfo/:id", v1.AppInfo)
|
|
||||||
//获取未安装的列表
|
|
||||||
v1AppGroup.GET("/list", v1.AppList)
|
|
||||||
//获取端口
|
|
||||||
v1AppGroup.GET("/port", v1.GetPort)
|
|
||||||
//检查端口
|
|
||||||
v1AppGroup.GET("/check/:port", v1.PortCheck)
|
|
||||||
|
|
||||||
v1AppGroup.GET("/category", v1.CategoryList)
|
|
||||||
|
|
||||||
v1AppGroup.GET("/terminal/:id", v1.DockerTerminal)
|
|
||||||
//app容器详情
|
|
||||||
v1AppGroup.GET("/info/:id", v1.ContainerInfo)
|
|
||||||
//app容器日志
|
|
||||||
v1AppGroup.GET("/logs/:id", v1.ContainerLog)
|
|
||||||
//暂停或启动容器
|
|
||||||
v1AppGroup.PUT("/state/:id", v1.ChangAppState)
|
|
||||||
//安装app
|
|
||||||
v1AppGroup.POST("/install", v1.InstallApp)
|
|
||||||
//卸载app
|
|
||||||
v1AppGroup.DELETE("/uninstall/:id", v1.UnInstallApp)
|
|
||||||
//获取进度
|
|
||||||
v1AppGroup.GET("/state/:id", v1.GetContainerState)
|
|
||||||
//更新容器配置
|
|
||||||
v1AppGroup.PUT("/update/:id/setting", v1.UpdateSetting)
|
|
||||||
//获取可能新数据
|
|
||||||
v1AppGroup.GET("/update/:id/info", v1.ContainerUpdateInfo)
|
|
||||||
v1AppGroup.GET("/rely/:id/info", v1.ContainerRelyInfo)
|
|
||||||
v1AppGroup.GET("/install/config", v1.GetDockerInstallConfig)
|
|
||||||
v1AppGroup.PUT("/update/:id", v1.PutAppUpdate)
|
|
||||||
v1AppGroup.POST("/share", v1.ShareAppFile)
|
|
||||||
}
|
|
||||||
|
|
||||||
v1SysGroup := v1Group.Group("/sys")
|
v1SysGroup := v1Group.Group("/sys")
|
||||||
v1SysGroup.Use()
|
v1SysGroup.Use()
|
||||||
{
|
{
|
||||||
v1SysGroup.GET("/version/check", v1.GetSystemCheckVersion)
|
v1SysGroup.GET("/version", v1.GetSystemCheckVersion) // version/check
|
||||||
v1SysGroup.GET("/hardware/info", v1.GetSystemHardwareInfo)
|
|
||||||
v1SysGroup.POST("/update", v1.SystemUpdate)
|
v1SysGroup.POST("/update", v1.SystemUpdate)
|
||||||
|
|
||||||
|
v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) // hardware/info
|
||||||
|
|
||||||
v1SysGroup.GET("/wsssh", v1.WsSsh)
|
v1SysGroup.GET("/wsssh", v1.WsSsh)
|
||||||
v1SysGroup.GET("/config", v1.GetSystemConfig)
|
v1SysGroup.POST("/ssh-login", v1.PostSshLogin)
|
||||||
//v1SysGroup.POST("/config", v1.PostSetSystemConfig)
|
// v1SysGroup.GET("/config", v1.GetSystemConfig) //delete
|
||||||
v1SysGroup.GET("/error/logs", v1.GetCasaOSErrorLogs)
|
// v1SysGroup.POST("/config", v1.PostSetSystemConfig)
|
||||||
v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)
|
v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) // error/logs
|
||||||
v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)
|
// v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete
|
||||||
v1SysGroup.GET("/port", v1.GetCasaOSPort)
|
// v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)//delete
|
||||||
v1SysGroup.PUT("/port", v1.PutCasaOSPort)
|
|
||||||
v1SysGroup.POST("/stop", v1.PostKillCasaOS)
|
v1SysGroup.POST("/stop", v1.PostKillCasaOS)
|
||||||
|
|
||||||
v1SysGroup.GET("/utilization", v1.GetSystemUtilization)
|
v1SysGroup.GET("/utilization", v1.GetSystemUtilization)
|
||||||
v1SysGroup.PUT("/usb/:status", v1.PutSystemUSBAutoMount)
|
// v1SysGroup.GET("/cpu", v1.GetSystemCupInfo)
|
||||||
v1SysGroup.GET("/usb/status", v1.GetSystemUSBAutoMount)
|
// v1SysGroup.GET("/mem", v1.GetSystemMemInfo)
|
||||||
v1SysGroup.GET("/cpu", v1.GetSystemCupInfo)
|
// v1SysGroup.GET("/disk", v1.GetSystemDiskInfo)
|
||||||
v1SysGroup.GET("/mem", v1.GetSystemMemInfo)
|
// v1SysGroup.GET("/network", v1.GetSystemNetInfo)
|
||||||
v1SysGroup.GET("/disk", v1.GetSystemDiskInfo)
|
|
||||||
v1SysGroup.GET("/network", v1.GetSystemNetInfo)
|
v1SysGroup.GET("/server-info", nil)
|
||||||
|
v1SysGroup.PUT("/server-info", nil)
|
||||||
|
// v1SysGroup.GET("/port", v1.GetCasaOSPort)
|
||||||
|
// v1SysGroup.PUT("/port", v1.PutCasaOSPort)
|
||||||
|
v1SysGroup.GET("/proxy", v1.GetSystemProxy)
|
||||||
|
v1SysGroup.PUT("/state/:state", v1.PutSystemState)
|
||||||
}
|
}
|
||||||
|
v1PortGroup := v1Group.Group("/port")
|
||||||
|
v1PortGroup.Use()
|
||||||
|
{
|
||||||
|
v1PortGroup.GET("/", v1.GetPort) // app/port
|
||||||
|
v1PortGroup.GET("/state/:port", v1.PortCheck) // app/check/:port
|
||||||
|
}
|
||||||
|
|
||||||
v1FileGroup := v1Group.Group("/file")
|
v1FileGroup := v1Group.Group("/file")
|
||||||
v1FileGroup.Use()
|
v1FileGroup.Use()
|
||||||
{
|
{
|
||||||
v1FileGroup.PUT("/rename", v1.RenamePath)
|
v1FileGroup.GET("", v1.GetDownloadSingleFile) // download/:path
|
||||||
v1FileGroup.GET("/read", v1.GetFilerContent)
|
v1FileGroup.POST("", v1.PostCreateFile)
|
||||||
|
v1FileGroup.PUT("", v1.PutFileContent)
|
||||||
|
v1FileGroup.PUT("/name", v1.RenamePath)
|
||||||
|
// file/rename
|
||||||
|
v1FileGroup.GET("/content", v1.GetFilerContent) // file/read
|
||||||
|
|
||||||
|
// File uploads need to be handled separately, and will not be modified here
|
||||||
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
||||||
v1FileGroup.GET("/upload", v1.GetFileUpload)
|
v1FileGroup.GET("/upload", v1.GetFileUpload)
|
||||||
v1FileGroup.GET("/dirpath", v1.DirPath)
|
// v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
||||||
//create folder
|
|
||||||
v1FileGroup.POST("/mkdir", v1.MkdirAll)
|
|
||||||
v1FileGroup.POST("/create", v1.PostCreateFile)
|
|
||||||
|
|
||||||
v1FileGroup.GET("/download", v1.GetDownloadFile)
|
|
||||||
v1FileGroup.GET("/download/*path", v1.GetDownloadSingleFile)
|
|
||||||
v1FileGroup.POST("/operate", v1.PostOperateFileOrDir)
|
|
||||||
v1FileGroup.DELETE("/delete", v1.DeleteFile)
|
|
||||||
v1FileGroup.PUT("/update", v1.PutFileContent)
|
|
||||||
v1FileGroup.GET("/image", v1.GetFileImage)
|
|
||||||
v1FileGroup.DELETE("/operate/:id", v1.DeleteOperateFileOrDir)
|
|
||||||
//v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
|
||||||
}
|
}
|
||||||
v1DiskGroup := v1Group.Group("/disk")
|
v1FolderGroup := v1Group.Group("/folder")
|
||||||
v1DiskGroup.Use()
|
v1FolderGroup.Use()
|
||||||
{
|
{
|
||||||
v1DiskGroup.GET("/check", v1.GetDiskCheck)
|
v1FolderGroup.PUT("/name", v1.RenamePath)
|
||||||
|
v1FolderGroup.GET("", v1.DirPath) ///file/dirpath
|
||||||
v1DiskGroup.GET("/list", v1.GetDiskList)
|
v1FolderGroup.POST("", v1.MkdirAll) ///file/mkdir
|
||||||
|
|
||||||
//获取磁盘详情
|
|
||||||
v1DiskGroup.GET("/info", v1.GetDiskInfo)
|
|
||||||
|
|
||||||
//format storage
|
|
||||||
v1DiskGroup.POST("/format", v1.PostDiskFormat)
|
|
||||||
|
|
||||||
// add storage
|
|
||||||
v1DiskGroup.POST("/storage", v1.PostDiskAddPartition)
|
|
||||||
|
|
||||||
//mount SATA disk
|
|
||||||
v1DiskGroup.POST("/mount", v1.PostMountDisk)
|
|
||||||
|
|
||||||
//umount sata disk
|
|
||||||
v1DiskGroup.POST("/umount", v1.PostDiskUmount)
|
|
||||||
|
|
||||||
//获取可以格式化的内容
|
|
||||||
v1DiskGroup.GET("/type", v1.FormatDiskType)
|
|
||||||
|
|
||||||
//删除分区
|
|
||||||
v1DiskGroup.DELETE("/delpart", v1.RemovePartition)
|
|
||||||
v1DiskGroup.GET("/usb", v1.GetUSBList)
|
|
||||||
|
|
||||||
}
|
}
|
||||||
v1PersonGroup := v1Group.Group("/person")
|
v1BatchGroup := v1Group.Group("/batch")
|
||||||
v1PersonGroup.Use()
|
v1BatchGroup.Use()
|
||||||
{
|
{
|
||||||
v1PersonGroup.GET("/detection", v1.GetPersonDetection)
|
|
||||||
v1PersonGroup.GET("/users", v1.GetPersonFriend)
|
|
||||||
v1PersonGroup.POST("/user/:shareids", v1.PostAddPersonFriend)
|
|
||||||
v1PersonGroup.DELETE("/user/:shareid", v1.DeletePersonFriend)
|
|
||||||
v1PersonGroup.GET("/directory", v1.GetPersonDirectory)
|
|
||||||
v1PersonGroup.GET("/file", v1.GetPersonFile)
|
|
||||||
v1PersonGroup.GET("/refile/:uuid", v1.GetPersonReFile)
|
|
||||||
v1PersonGroup.PUT("/remarks/:shareid", v1.PutPersonRemarks)
|
|
||||||
v1PersonGroup.GET("/list", v1.GetPersonDownloadList)
|
|
||||||
v1PersonGroup.DELETE("/file/:uuid", v1.DeletePersonDownloadFile)
|
|
||||||
|
|
||||||
v1PersonGroup.POST("/share", v1.PostPersonShare)
|
|
||||||
v1PersonGroup.POST("/file/:shareid", v1.PostPersonFile)
|
|
||||||
v1PersonGroup.GET("/share", v1.GetPersonShare)
|
|
||||||
v1PersonGroup.POST("/down/dir", v1.PostPersonDownDir)
|
|
||||||
v1PersonGroup.GET("/down/dir", v1.GetPersonDownDir)
|
|
||||||
v1PersonGroup.PUT("/block/:shareid", v1.PutPersonBlock)
|
|
||||||
v1PersonGroup.GET("/public", v1.GetPersonPublic)
|
|
||||||
v1PersonGroup.PUT("/friend/:shareid", v1.PutPersonAgreeFriend)
|
|
||||||
v1PersonGroup.PUT("/write/:shareid", v1.PutPersonWrite)
|
|
||||||
v1PersonGroup.GET("/image/thumbnail/:shareid", v1.GetPersonImageThumbnail)
|
|
||||||
|
|
||||||
|
v1BatchGroup.DELETE("", v1.DeleteFile) // file/delete
|
||||||
|
v1BatchGroup.DELETE("/:id/task", v1.DeleteOperateFileOrDir)
|
||||||
|
v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) // file/operate
|
||||||
|
v1BatchGroup.GET("", v1.GetDownloadFile)
|
||||||
|
}
|
||||||
|
v1ImageGroup := v1Group.Group("/image")
|
||||||
|
v1ImageGroup.Use()
|
||||||
|
{
|
||||||
|
v1ImageGroup.GET("", v1.GetFileImage)
|
||||||
|
}
|
||||||
|
v1SambaGroup := v1Group.Group("/samba")
|
||||||
|
v1SambaGroup.Use()
|
||||||
|
{
|
||||||
|
v1ConnectionsGroup := v1SambaGroup.Group("/connections")
|
||||||
|
v1ConnectionsGroup.Use()
|
||||||
|
{
|
||||||
|
v1ConnectionsGroup.GET("", v1.GetSambaConnectionsList)
|
||||||
|
v1ConnectionsGroup.POST("", v1.PostSambaConnectionsCreate)
|
||||||
|
v1ConnectionsGroup.DELETE("/:id", v1.DeleteSambaConnections)
|
||||||
|
}
|
||||||
|
v1SharesGroup := v1SambaGroup.Group("/shares")
|
||||||
|
v1SharesGroup.Use()
|
||||||
|
{
|
||||||
|
v1SharesGroup.GET("", v1.GetSambaSharesList)
|
||||||
|
v1SharesGroup.POST("", v1.PostSambaSharesCreate)
|
||||||
|
v1SharesGroup.DELETE("/:id", v1.DeleteSambaShares)
|
||||||
|
v1SharesGroup.GET("/status", v1.GetSambaStatus)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
v1NotifyGroup := v1Group.Group("/notify")
|
||||||
|
v1NotifyGroup.Use()
|
||||||
|
{
|
||||||
|
v1NotifyGroup.POST("/:path", v1.PostNotifyMessage)
|
||||||
|
// merge to system
|
||||||
|
v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify)
|
||||||
|
v1NotifyGroup.POST("/install_app", v1.PostInstallAppNotify)
|
||||||
|
v1NotifyGroup.POST("/uninstall_app", v1.PostUninstallAppNotify)
|
||||||
}
|
}
|
||||||
v1Group.GET("/sync/config", v1.GetSyncConfig)
|
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,15 +14,14 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/port"
|
||||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
"github.com/IceWhaleTech/CasaOS/model/notify"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
f "github.com/ambelovsky/gosf"
|
f "github.com/ambelovsky/gosf"
|
||||||
)
|
)
|
||||||
|
|
||||||
func SocketInit(msg chan notify.Message) {
|
func SocketInit(msg chan notify.Message) {
|
||||||
|
|
||||||
// set socket port
|
// set socket port
|
||||||
socketPort := 0
|
socketPort := 0
|
||||||
if len(config.ServerInfo.SocketPort) == 0 {
|
if len(config.ServerInfo.SocketPort) == 0 {
|
||||||
@@ -51,10 +50,9 @@ func SocketInit(msg chan notify.Message) {
|
|||||||
f.Broadcast("", v.Path, &v.Msg)
|
f.Broadcast("", v.Path, &v.Msg)
|
||||||
time.Sleep(time.Millisecond * 100)
|
time.Sleep(time.Millisecond * 100)
|
||||||
}
|
}
|
||||||
|
|
||||||
}(msg)
|
}(msg)
|
||||||
|
|
||||||
f.Startup(map[string]interface{}{
|
f.Startup(map[string]interface{}{
|
||||||
"port": socketPort})
|
"port": socketPort,
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
25
route/ui.go
25
route/ui.go
@@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-06-23 17:27:43
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-06-23 17:27:48
|
|
||||||
* @FilePath: /CasaOS/route/ui.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package route
|
|
||||||
|
|
||||||
import (
|
|
||||||
"html/template"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/web"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
func WebUIHome(c *gin.Context) {
|
|
||||||
c.Writer.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
index, _ := template.ParseFS(web.Static, "index.html")
|
|
||||||
index.Execute(c.Writer, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
251
route/v1/app.go
251
route/v1/app.go
@@ -1,251 +0,0 @@
|
|||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
|
||||||
|
|
||||||
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// @Summary 获取远程列表
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags app
|
|
||||||
// @Param index query int false "页码"
|
|
||||||
// @Param size query int false "每页数量"
|
|
||||||
// @Param category_id query int false "分类id"
|
|
||||||
// @Param type query string false "rank,new"
|
|
||||||
// @Param key query string false "search key"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /app/list [get]
|
|
||||||
func AppList(c *gin.Context) {
|
|
||||||
|
|
||||||
//service.MyService.Docker().DockerContainerCommit("test2")
|
|
||||||
|
|
||||||
index := c.DefaultQuery("index", "1")
|
|
||||||
size := c.DefaultQuery("size", "10000")
|
|
||||||
t := c.DefaultQuery("type", "rank")
|
|
||||||
categoryId := c.DefaultQuery("category_id", "0")
|
|
||||||
key := c.DefaultQuery("key", "")
|
|
||||||
if len(index) == 0 || len(size) == 0 || len(t) == 0 || len(categoryId) == 0 {
|
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
collection := service.MyService.Casa().GetServerList(index, size, t, categoryId, key)
|
|
||||||
// for i := 0; i < len(recommend); i++ {
|
|
||||||
// ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion)
|
|
||||||
// if ct != nil {
|
|
||||||
// recommend[i].State = ct.State
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for i := 0; i < len(list); i++ {
|
|
||||||
// ct, _ := service.MyService.Docker().DockerListByImage(list[i].Image, list[i].ImageVersion)
|
|
||||||
// if ct != nil {
|
|
||||||
// list[i].State = ct.State
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// for i := 0; i < len(community); i++ {
|
|
||||||
// ct, _ := service.MyService.Docker().DockerListByImage(community[i].Image, community[i].ImageVersion)
|
|
||||||
// if ct != nil {
|
|
||||||
// community[i].State = ct.State
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
data := make(map[string]interface{}, 3)
|
|
||||||
data["recommend"] = collection.Recommend
|
|
||||||
data["list"] = collection.List
|
|
||||||
data["community"] = collection.Community
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取一个可用端口
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags app
|
|
||||||
// @Param type query string true "端口类型 udp/tcp"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /app/getport [get]
|
|
||||||
func GetPort(c *gin.Context) {
|
|
||||||
t := c.DefaultQuery("type", "tcp")
|
|
||||||
var p int
|
|
||||||
ok := true
|
|
||||||
for ok {
|
|
||||||
p, _ = port2.GetAvailablePort(t)
|
|
||||||
ok = !port2.IsPortAvailable(p, t)
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: p})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 检查端口是否可用
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags app
|
|
||||||
// @Param port path int true "端口号"
|
|
||||||
// @Param type query string true "端口类型 udp/tcp"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /app/check/{port} [get]
|
|
||||||
func PortCheck(c *gin.Context) {
|
|
||||||
p, _ := strconv.Atoi(c.Param("port"))
|
|
||||||
t := c.DefaultQuery("type", "tcp")
|
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port2.IsPortAvailable(p, t)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 我的应用列表
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags app
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param index query int false "index"
|
|
||||||
// @Param size query int false "size"
|
|
||||||
// @Param position query bool false "是否是首页应用"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /app/my/list [get]
|
|
||||||
func MyAppList(c *gin.Context) {
|
|
||||||
index, _ := strconv.Atoi(c.DefaultQuery("index", "1"))
|
|
||||||
size, _ := strconv.Atoi(c.DefaultQuery("size", "0"))
|
|
||||||
position, _ := strconv.ParseBool(c.DefaultQuery("position", "true"))
|
|
||||||
list, unTranslation := service.MyService.App().GetMyList(index, size, position)
|
|
||||||
data := make(map[string]interface{}, 2)
|
|
||||||
data["list"] = list
|
|
||||||
data["local"] = unTranslation
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary my app hardware usage list
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags app
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /app/usage [get]
|
|
||||||
func AppUsageList(c *gin.Context) {
|
|
||||||
list := service.MyService.App().GetHardwareUsage()
|
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 应用详情
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags app
|
|
||||||
// @Param id path int true "id"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /app/appinfo/{id} [get]
|
|
||||||
func AppInfo(c *gin.Context) {
|
|
||||||
|
|
||||||
id := c.Param("id")
|
|
||||||
language := c.GetHeader("Language")
|
|
||||||
info := service.MyService.Casa().GetServerAppInfo(id, "", language)
|
|
||||||
if info.NetworkModel != "host" {
|
|
||||||
for i := 0; i < len(info.Ports); i++ {
|
|
||||||
if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {
|
|
||||||
info.Ports[i].CommendPort = strconv.Itoa(p)
|
|
||||||
} else {
|
|
||||||
if info.Ports[i].Protocol == "tcp" {
|
|
||||||
if p, err := port2.GetAvailablePort("tcp"); err == nil {
|
|
||||||
info.Ports[i].CommendPort = strconv.Itoa(p)
|
|
||||||
}
|
|
||||||
} else if info.Ports[i].Protocol == "upd" {
|
|
||||||
if p, err := port2.GetAvailablePort("udp"); err == nil {
|
|
||||||
info.Ports[i].CommendPort = strconv.Itoa(p)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if info.Ports[i].Type == 0 {
|
|
||||||
info.PortMap = info.Ports[i].CommendPort
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
for i := 0; i < len(info.Ports); i++ {
|
|
||||||
if info.Ports[i].Type == 0 {
|
|
||||||
info.PortMap = info.Ports[i].ContainerPort
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(info.Devices); i++ {
|
|
||||||
if !file.CheckNotExist(info.Devices[i].ContainerPath) {
|
|
||||||
info.Devices[i].Path = info.Devices[i].ContainerPath
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// if len(info.Tip) > 0 {
|
|
||||||
// info.Tip = env_helper.ReplaceStringDefaultENV(info.Tip)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// portOrder := func(c1, c2 *model.Ports) bool {
|
|
||||||
// return c1.Type < c2.Type
|
|
||||||
// }
|
|
||||||
|
|
||||||
// envOrder := func(c1, c2 *model.Envs) bool {
|
|
||||||
// return c1.Type < c2.Type
|
|
||||||
// }
|
|
||||||
|
|
||||||
// volOrder := func(c1, c2 *model.Volume) bool {
|
|
||||||
// return c1.Type < c2.Type
|
|
||||||
// }
|
|
||||||
|
|
||||||
// devOrder := func(c1, c2 *model.Devices) bool {
|
|
||||||
// return c1.Type < c2.Type
|
|
||||||
// }
|
|
||||||
|
|
||||||
//sort
|
|
||||||
// if info.NetworkModel != "host" {
|
|
||||||
// sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
|
|
||||||
// sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// sort.EnvSort(envOrder).Sort(info.Envs)
|
|
||||||
// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
|
|
||||||
// sort.DevSort(devOrder).Sort(info.Devices)
|
|
||||||
|
|
||||||
info.MaxMemory = (service.MyService.System().GetMemInfo()["total"]).(uint64) >> 20
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取远程分类列表
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags app
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /app/category [get]
|
|
||||||
func CategoryList(c *gin.Context) {
|
|
||||||
list := service.MyService.Casa().GetServerCategoryList()
|
|
||||||
var count uint = 0
|
|
||||||
for _, category := range list {
|
|
||||||
count += category.Count
|
|
||||||
}
|
|
||||||
|
|
||||||
rear := append([]model.CategoryList{}, list[0:]...)
|
|
||||||
list = append(list[:0], model.CategoryList{Count: count, Name: "All", Font: "apps"})
|
|
||||||
list = append(list, rear...)
|
|
||||||
c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 分享该应用配置
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags app
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /app/share [post]
|
|
||||||
func ShareAppFile(c *gin.Context) {
|
|
||||||
str, _ := ioutil.ReadAll(c.Request.Body)
|
|
||||||
content := service.MyService.Casa().ShareAppFile(str)
|
|
||||||
c.JSON(http.StatusOK, json.RawMessage(content))
|
|
||||||
}
|
|
||||||
499
route/v1/disk.go
499
route/v1/disk.go
@@ -1,499 +0,0 @@
|
|||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
|
||||||
)
|
|
||||||
|
|
||||||
var diskMap = make(map[string]string)
|
|
||||||
|
|
||||||
// @Summary disk list
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/list [get]
|
|
||||||
func GetDiskList(c *gin.Context) {
|
|
||||||
list := service.MyService.Disk().LSBLK(false)
|
|
||||||
dbList := service.MyService.Disk().GetSerialAll()
|
|
||||||
part := make(map[string]int64, len(dbList))
|
|
||||||
for _, v := range dbList {
|
|
||||||
part[v.MountPoint] = v.CreatedAt
|
|
||||||
}
|
|
||||||
findSystem := 0
|
|
||||||
|
|
||||||
disks := []model.Drive{}
|
|
||||||
storage := []model.Storage{}
|
|
||||||
avail := []model.Drive{}
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
disk := model.Drive{}
|
|
||||||
if list[i].Rota {
|
|
||||||
disk.DiskType = "HDD"
|
|
||||||
} else {
|
|
||||||
disk.DiskType = "SSD"
|
|
||||||
}
|
|
||||||
disk.Serial = list[i].Serial
|
|
||||||
disk.Name = list[i].Name
|
|
||||||
disk.Size = list[i].Size
|
|
||||||
disk.Path = list[i].Path
|
|
||||||
disk.Model = list[i].Model
|
|
||||||
|
|
||||||
if len(list[i].Children) > 0 && findSystem == 0 {
|
|
||||||
for j := 0; j < len(list[i].Children); j++ {
|
|
||||||
if len(list[i].Children[j].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children[j].Children {
|
|
||||||
if v.MountPoint == "/" {
|
|
||||||
stor := model.Storage{}
|
|
||||||
stor.Name = "System"
|
|
||||||
stor.MountPoint = v.MountPoint
|
|
||||||
stor.Size = v.FSSize
|
|
||||||
stor.Avail = v.FSAvail
|
|
||||||
stor.Path = v.Path
|
|
||||||
stor.Type = v.FsType
|
|
||||||
stor.DriveName = "System"
|
|
||||||
disk.Model = "System"
|
|
||||||
if strings.Contains(v.SubSystems, "mmc") {
|
|
||||||
disk.DiskType = "MMC"
|
|
||||||
} else if strings.Contains(v.SubSystems, "usb") {
|
|
||||||
disk.DiskType = "USB"
|
|
||||||
}
|
|
||||||
disk.Health = "true"
|
|
||||||
|
|
||||||
disks = append(disks, disk)
|
|
||||||
storage = append(storage, stor)
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if list[i].Children[j].MountPoint == "/" {
|
|
||||||
stor := model.Storage{}
|
|
||||||
stor.Name = "System"
|
|
||||||
stor.MountPoint = list[i].Children[j].MountPoint
|
|
||||||
stor.Size = list[i].Children[j].FSSize
|
|
||||||
stor.Avail = list[i].Children[j].FSAvail
|
|
||||||
stor.Path = list[i].Children[j].Path
|
|
||||||
stor.Type = list[i].Children[j].FsType
|
|
||||||
stor.DriveName = "System"
|
|
||||||
disk.Model = "System"
|
|
||||||
if strings.Contains(list[i].Children[j].SubSystems, "mmc") {
|
|
||||||
disk.DiskType = "MMC"
|
|
||||||
} else if strings.Contains(list[i].Children[j].SubSystems, "usb") {
|
|
||||||
disk.DiskType = "USB"
|
|
||||||
}
|
|
||||||
disk.Health = "true"
|
|
||||||
|
|
||||||
disks = append(disks, disk)
|
|
||||||
storage = append(storage, stor)
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if findSystem == 1 {
|
|
||||||
findSystem += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
|
|
||||||
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
|
||||||
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
|
||||||
temp.SmartStatus.Passed = true
|
|
||||||
}
|
|
||||||
if len(list[i].Children) == 1 && len(list[i].Children[0].MountPoint) > 0 {
|
|
||||||
stor := model.Storage{}
|
|
||||||
stor.MountPoint = list[i].Children[0].MountPoint
|
|
||||||
stor.Size = list[i].Children[0].FSSize
|
|
||||||
stor.Avail = list[i].Children[0].FSAvail
|
|
||||||
stor.Path = list[i].Children[0].Path
|
|
||||||
stor.Type = list[i].Children[0].FsType
|
|
||||||
stor.DriveName = list[i].Name
|
|
||||||
pathArr := strings.Split(list[i].Children[0].MountPoint, "/")
|
|
||||||
if len(pathArr) == 3 {
|
|
||||||
stor.Name = pathArr[2]
|
|
||||||
}
|
|
||||||
if t, ok := part[list[i].Children[0].MountPoint]; ok {
|
|
||||||
stor.CreatedAt = t
|
|
||||||
}
|
|
||||||
storage = append(storage, stor)
|
|
||||||
} else {
|
|
||||||
//todo 长度有问题
|
|
||||||
if len(list[i].Children) == 1 && list[i].Children[0].FsType == "ext4" {
|
|
||||||
disk.NeedFormat = false
|
|
||||||
avail = append(avail, disk)
|
|
||||||
} else {
|
|
||||||
disk.NeedFormat = true
|
|
||||||
avail = append(avail, disk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
disk.Temperature = temp.Temperature.Current
|
|
||||||
disk.Health = strconv.FormatBool(temp.SmartStatus.Passed)
|
|
||||||
|
|
||||||
disks = append(disks, disk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data := make(map[string]interface{}, 3)
|
|
||||||
data["drive"] = disks
|
|
||||||
data["storage"] = storage
|
|
||||||
data["avail"] = avail
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary get disk list
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/lists [get]
|
|
||||||
func GetPlugInDisks(c *gin.Context) {
|
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
var result []*disk.UsageStat
|
|
||||||
for _, item := range list {
|
|
||||||
result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path))
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: result})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary disk detail
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path query string true "for example /dev/sda"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/info [get]
|
|
||||||
func GetDiskInfo(c *gin.Context) {
|
|
||||||
path := c.Query("path")
|
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
}
|
|
||||||
m := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary format storage
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "e.g. /dev/sda1"
|
|
||||||
// @Param pwd formData string true "user password"
|
|
||||||
// @Param volume formData string true "mount point"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/format [post]
|
|
||||||
func PostDiskFormat(c *gin.Context) {
|
|
||||||
path := c.PostForm("path")
|
|
||||||
t := "ext4"
|
|
||||||
pwd := c.PostForm("pwd")
|
|
||||||
volume := c.PostForm("volume")
|
|
||||||
|
|
||||||
if pwd != config.UserInfo.PWD {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(path) == 0 || len(t) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, ok := diskMap[path]; ok {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
diskMap[path] = "busying"
|
|
||||||
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
|
||||||
format := service.MyService.Disk().FormatDisk(path, t)
|
|
||||||
if len(format) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
|
|
||||||
delete(diskMap, path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
service.MyService.Disk().MountDisk(path, volume)
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
delete(diskMap, path)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取支持的格式
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/type [get]
|
|
||||||
func FormatDiskType(c *gin.Context) {
|
|
||||||
var strArr = [4]string{"fat32", "ntfs", "ext4", "exfat"}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: strArr})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除分区
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "磁盘路径 例如/dev/sda1"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/delpart [delete]
|
|
||||||
func RemovePartition(c *gin.Context) {
|
|
||||||
path := c.PostForm("path")
|
|
||||||
|
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
}
|
|
||||||
var p = path[:len(path)-1]
|
|
||||||
var n = path[len(path)-1:]
|
|
||||||
service.MyService.Disk().DelPartition(p, n)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary add storage
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "disk path e.g. /dev/sda"
|
|
||||||
// @Param serial formData string true "serial"
|
|
||||||
// @Param name formData string true "name"
|
|
||||||
// @Param format formData bool true "need format(true)"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/storage [post]
|
|
||||||
func PostDiskAddPartition(c *gin.Context) {
|
|
||||||
|
|
||||||
name := c.PostForm("name")
|
|
||||||
path := c.PostForm("path")
|
|
||||||
format, _ := strconv.ParseBool(c.PostForm("format"))
|
|
||||||
|
|
||||||
if len(name) == 0 || len(path) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, ok := diskMap[path]; ok {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !file.CheckNotExist("/DATA/" + name) {
|
|
||||||
// /mnt/name exist
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
diskMap[path] = "busying"
|
|
||||||
currentDisk := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
if !format {
|
|
||||||
if len(currentDisk.Children) != 1 || !(len(currentDisk.Children) > 0 && currentDisk.Children[0].FsType == "ext4") {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
|
|
||||||
delete(diskMap, path)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
service.MyService.Disk().AddPartition(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
formatBool := true
|
|
||||||
for formatBool {
|
|
||||||
currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
fmt.Println(currentDisk.Children)
|
|
||||||
if len(currentDisk.Children) > 0 {
|
|
||||||
formatBool = false
|
|
||||||
break
|
|
||||||
}
|
|
||||||
time.Sleep(time.Second)
|
|
||||||
}
|
|
||||||
currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
if len(currentDisk.Children) != 1 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
mountPath := "/DATA/" + name
|
|
||||||
m := model2.SerialDisk{}
|
|
||||||
m.MountPoint = mountPath
|
|
||||||
m.Path = currentDisk.Children[0].Path
|
|
||||||
m.UUID = currentDisk.Children[0].UUID
|
|
||||||
m.State = 0
|
|
||||||
m.CreatedAt = time.Now().Unix()
|
|
||||||
service.MyService.Disk().SaveMountPoint(m)
|
|
||||||
|
|
||||||
//mount dir
|
|
||||||
service.MyService.Disk().MountDisk(currentDisk.Children[0].Path, mountPath)
|
|
||||||
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
|
|
||||||
delete(diskMap, path)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary add mount point
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "for example: /dev/sda1"
|
|
||||||
// @Param serial formData string true "disk id"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/mount [post]
|
|
||||||
func PostMountDisk(c *gin.Context) {
|
|
||||||
// for example: path=/dev/sda1
|
|
||||||
path := c.PostForm("path")
|
|
||||||
serial := c.PostForm("serial")
|
|
||||||
|
|
||||||
mountPath := "/DATA/volume"
|
|
||||||
var list = service.MyService.Disk().GetSerialAll()
|
|
||||||
var pathMapList = make(map[string]string, len(list))
|
|
||||||
for _, v := range list {
|
|
||||||
pathMapList[v.MountPoint] = "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
for i := 0; i < len(list)+1; i++ {
|
|
||||||
if _, ok := pathMapList[mountPath+strconv.Itoa(i)]; !ok {
|
|
||||||
mountPath = mountPath + strconv.Itoa(i)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//mount dir
|
|
||||||
service.MyService.Disk().MountDisk(path, mountPath)
|
|
||||||
|
|
||||||
m := model2.SerialDisk{}
|
|
||||||
m.MountPoint = mountPath
|
|
||||||
m.Path = path
|
|
||||||
m.UUID = serial
|
|
||||||
m.State = 0
|
|
||||||
//service.MyService.Disk().SaveMountPoint(m)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary remove mount point
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "e.g. /dev/sda1"
|
|
||||||
// @Param mount_point formData string true "e.g. /mnt/volume1"
|
|
||||||
// @Param pwd formData string true "user password"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/umount [post]
|
|
||||||
func PostDiskUmount(c *gin.Context) {
|
|
||||||
|
|
||||||
path := c.PostForm("path")
|
|
||||||
mountPoint := c.PostForm("volume")
|
|
||||||
pwd := c.PostForm("pwd")
|
|
||||||
|
|
||||||
if len(path) == 0 || len(mountPoint) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if pwd != config.UserInfo.PWD {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := diskMap[path]; ok {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
|
||||||
//delete data
|
|
||||||
service.MyService.Disk().DeleteMountPoint(path, mountPoint)
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary confirm delete disk
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param id path string true "id"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/remove/{id} [delete]
|
|
||||||
func DeleteDisk(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
service.MyService.Disk().DeleteMount(id)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary check mount point
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/init [get]
|
|
||||||
func GetDiskCheck(c *gin.Context) {
|
|
||||||
|
|
||||||
dbList := service.MyService.Disk().GetSerialAll()
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
|
|
||||||
mapList := make(map[string]string)
|
|
||||||
|
|
||||||
for _, v := range list {
|
|
||||||
mapList[v.Serial] = "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range dbList {
|
|
||||||
if _, ok := mapList[v.UUID]; !ok {
|
|
||||||
//disk undefind
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: "disk undefind"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary check mount point
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/usb [get]
|
|
||||||
func GetUSBList(c *gin.Context) {
|
|
||||||
list := service.MyService.Disk().LSBLK(false)
|
|
||||||
data := []model.DriveUSB{}
|
|
||||||
for _, v := range list {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Name
|
|
||||||
temp.Size = v.Size
|
|
||||||
mountTemp := true
|
|
||||||
if len(v.Children) == 0 {
|
|
||||||
mountTemp = false
|
|
||||||
}
|
|
||||||
for _, child := range v.Children {
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
temp.Avail += avail
|
|
||||||
} else {
|
|
||||||
mountTemp = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
temp.Mount = mountTemp
|
|
||||||
data = append(data, temp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
}
|
|
||||||
1242
route/v1/docker.go
1242
route/v1/docker.go
File diff suppressed because it is too large
Load Diff
301
route/v1/file.go
301
route/v1/file.go
@@ -1,8 +1,6 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
|
||||||
"encoding/csv"
|
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -17,41 +15,16 @@ import (
|
|||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
func downloadReadFile(c *gin.Context) {
|
|
||||||
//http下载地址 csv
|
|
||||||
csvFileUrl := c.PostForm("file_name")
|
|
||||||
res, err := http.Get(csvFileUrl)
|
|
||||||
if err != nil {
|
|
||||||
c.String(400, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
defer res.Body.Close()
|
|
||||||
//读取csv
|
|
||||||
reader := csv.NewReader(bufio.NewReader(res.Body))
|
|
||||||
for {
|
|
||||||
line, err := reader.Read()
|
|
||||||
if err == io.EOF {
|
|
||||||
break
|
|
||||||
} else if err != nil {
|
|
||||||
c.String(400, err.Error())
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//line 就是每一行的内容
|
|
||||||
fmt.Println(line)
|
|
||||||
//line[0] 就是第几列
|
|
||||||
fmt.Println(line[0])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 读取文件
|
// @Summary 读取文件
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
@@ -63,23 +36,23 @@ func downloadReadFile(c *gin.Context) {
|
|||||||
func GetFilerContent(c *gin.Context) {
|
func GetFilerContent(c *gin.Context) {
|
||||||
filePath := c.Query("path")
|
filePath := c.Query("path")
|
||||||
if len(filePath) == 0 {
|
if len(filePath) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{
|
c.JSON(common_err.CLIENT_ERROR, model.Result{
|
||||||
Success: common_err.INVALID_PARAMS,
|
Success: common_err.INVALID_PARAMS,
|
||||||
Message: common_err.GetMsg(common_err.INVALID_PARAMS),
|
Message: common_err.GetMsg(common_err.INVALID_PARAMS),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if !file.Exists(filePath) {
|
if !file.Exists(filePath) {
|
||||||
c.JSON(http.StatusOK, model.Result{
|
c.JSON(common_err.SERVICE_ERROR, model.Result{
|
||||||
Success: common_err.FILE_DOES_NOT_EXIST,
|
Success: common_err.FILE_DOES_NOT_EXIST,
|
||||||
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
|
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//文件读取任务是将文件内容读取到内存中。
|
// 文件读取任务是将文件内容读取到内存中。
|
||||||
info, err := ioutil.ReadFile(filePath)
|
info, err := ioutil.ReadFile(filePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{
|
c.JSON(common_err.SERVICE_ERROR, model.Result{
|
||||||
Success: common_err.FILE_READ_ERROR,
|
Success: common_err.FILE_READ_ERROR,
|
||||||
Message: common_err.GetMsg(common_err.FILE_READ_ERROR),
|
Message: common_err.GetMsg(common_err.FILE_READ_ERROR),
|
||||||
Data: err.Error(),
|
Data: err.Error(),
|
||||||
@@ -88,8 +61,7 @@ func GetFilerContent(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
result := string(info)
|
result := string(info)
|
||||||
|
|
||||||
//返回结果
|
c.JSON(common_err.SUCCESS, model.Result{
|
||||||
c.JSON(http.StatusOK, model.Result{
|
|
||||||
Success: common_err.SUCCESS,
|
Success: common_err.SUCCESS,
|
||||||
Message: common_err.GetMsg(common_err.SUCCESS),
|
Message: common_err.GetMsg(common_err.SUCCESS),
|
||||||
Data: result,
|
Data: result,
|
||||||
@@ -113,7 +85,6 @@ func GetLocalFile(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.File(path)
|
c.File(path)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary download
|
// @Summary download
|
||||||
@@ -121,18 +92,17 @@ func GetLocalFile(c *gin.Context) {
|
|||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
// @Tags file
|
// @Tags file
|
||||||
// @Security ApiKeyAuth
|
// @Security ApiKeyAuth
|
||||||
// @Param t query string false "Compression format" Enums(zip,tar,targz)
|
// @Param format query string false "Compression format" Enums(zip,tar,targz)
|
||||||
// @Param files query string true "file list eg: filename1,filename2,filename3 "
|
// @Param files query string true "file list eg: filename1,filename2,filename3 "
|
||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/download [get]
|
// @Router /file/download [get]
|
||||||
func GetDownloadFile(c *gin.Context) {
|
func GetDownloadFile(c *gin.Context) {
|
||||||
|
t := c.Query("format")
|
||||||
t := c.Query("t")
|
|
||||||
|
|
||||||
files := c.Query("files")
|
files := c.Query("files")
|
||||||
|
|
||||||
if len(files) == 0 {
|
if len(files) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{
|
c.JSON(common_err.CLIENT_ERROR, model.Result{
|
||||||
Success: common_err.INVALID_PARAMS,
|
Success: common_err.INVALID_PARAMS,
|
||||||
Message: common_err.GetMsg(common_err.INVALID_PARAMS),
|
Message: common_err.GetMsg(common_err.INVALID_PARAMS),
|
||||||
})
|
})
|
||||||
@@ -141,7 +111,7 @@ func GetDownloadFile(c *gin.Context) {
|
|||||||
list := strings.Split(files, ",")
|
list := strings.Split(files, ",")
|
||||||
for _, v := range list {
|
for _, v := range list {
|
||||||
if !file.Exists(v) {
|
if !file.Exists(v) {
|
||||||
c.JSON(http.StatusOK, model.Result{
|
c.JSON(common_err.SERVICE_ERROR, model.Result{
|
||||||
Success: common_err.FILE_DOES_NOT_EXIST,
|
Success: common_err.FILE_DOES_NOT_EXIST,
|
||||||
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
|
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
|
||||||
})
|
})
|
||||||
@@ -165,11 +135,11 @@ func GetDownloadFile(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
if !info.IsDir() {
|
if !info.IsDir() {
|
||||||
|
|
||||||
//打开文件
|
// 打开文件
|
||||||
fileTmp, _ := os.Open(filePath)
|
fileTmp, _ := os.Open(filePath)
|
||||||
defer fileTmp.Close()
|
defer fileTmp.Close()
|
||||||
|
|
||||||
//获取文件的名称
|
// 获取文件的名称
|
||||||
fileName := path.Base(filePath)
|
fileName := path.Base(filePath)
|
||||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
||||||
c.File(filePath)
|
c.File(filePath)
|
||||||
@@ -179,7 +149,7 @@ func GetDownloadFile(c *gin.Context) {
|
|||||||
|
|
||||||
extension, ar, err := file.GetCompressionAlgorithm(t)
|
extension, ar, err := file.GetCompressionAlgorithm(t)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{
|
c.JSON(common_err.CLIENT_ERROR, model.Result{
|
||||||
Success: common_err.INVALID_PARAMS,
|
Success: common_err.INVALID_PARAMS,
|
||||||
Message: common_err.GetMsg(common_err.INVALID_PARAMS),
|
Message: common_err.GetMsg(common_err.INVALID_PARAMS),
|
||||||
})
|
})
|
||||||
@@ -188,9 +158,9 @@ func GetDownloadFile(c *gin.Context) {
|
|||||||
|
|
||||||
err = ar.Create(c.Writer)
|
err = ar.Create(c.Writer)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{
|
c.JSON(common_err.SERVICE_ERROR, model.Result{
|
||||||
Success: common_err.ERROR,
|
Success: common_err.SERVICE_ERROR,
|
||||||
Message: common_err.GetMsg(common_err.ERROR),
|
Message: common_err.GetMsg(common_err.SERVICE_ERROR),
|
||||||
Data: err.Error(),
|
Data: err.Error(),
|
||||||
})
|
})
|
||||||
return
|
return
|
||||||
@@ -209,16 +179,29 @@ func GetDownloadFile(c *gin.Context) {
|
|||||||
log.Printf("Failed to archive %s: %v", fname, err)
|
log.Printf("Failed to archive %s: %v", fname, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDownloadSingleFile(c *gin.Context) {
|
func GetDownloadSingleFile(c *gin.Context) {
|
||||||
filePath := c.Param("path")
|
filePath := c.Query("path")
|
||||||
fileTmp, _ := os.Open(filePath)
|
if len(filePath) == 0 {
|
||||||
|
c.JSON(service.ClientCount, model.Result{
|
||||||
|
Success: common_err.INVALID_PARAMS,
|
||||||
|
Message: common_err.GetMsg(common_err.INVALID_PARAMS),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
fileTmp, err := os.Open(filePath)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(common_err.SERVICE_ERROR, model.Result{
|
||||||
|
Success: common_err.FILE_DOES_NOT_EXIST,
|
||||||
|
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
|
||||||
|
})
|
||||||
|
return
|
||||||
|
}
|
||||||
defer fileTmp.Close()
|
defer fileTmp.Close()
|
||||||
|
|
||||||
fileName := path.Base(filePath)
|
fileName := path.Base(filePath)
|
||||||
//c.Header("Content-Disposition", "inline")
|
// c.Header("Content-Disposition", "inline")
|
||||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
||||||
c.File(filePath)
|
c.File(filePath)
|
||||||
}
|
}
|
||||||
@@ -234,47 +217,24 @@ func GetDownloadSingleFile(c *gin.Context) {
|
|||||||
func DirPath(c *gin.Context) {
|
func DirPath(c *gin.Context) {
|
||||||
path := c.DefaultQuery("path", "")
|
path := c.DefaultQuery("path", "")
|
||||||
info := service.MyService.System().GetDirPath(path)
|
info := service.MyService.System().GetDirPath(path)
|
||||||
if path == "/DATA/AppData" {
|
shares := service.MyService.Shares().GetSharesList()
|
||||||
list := service.MyService.Docker().DockerContainerList()
|
sharesMap := make(map[string]string)
|
||||||
apps := make(map[string]string, len(list))
|
for _, v := range shares {
|
||||||
for _, v := range list {
|
sharesMap[v.Path] = fmt.Sprint(v.ID)
|
||||||
apps[strings.ReplaceAll(v.Names[0], "/", "")] = strings.ReplaceAll(v.Names[0], "/", "")
|
|
||||||
}
|
|
||||||
for i := 0; i < len(info); i++ {
|
|
||||||
if v, ok := apps[info[i].Name]; ok {
|
|
||||||
info[i].Label = v
|
|
||||||
info[i].Type = "application"
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if path == "/DATA" {
|
|
||||||
disk := make(map[string]string)
|
|
||||||
lsblk := service.MyService.Disk().LSBLK(true)
|
|
||||||
for _, v := range lsblk {
|
|
||||||
if len(v.Children) > 0 {
|
|
||||||
t := v.Tran
|
|
||||||
for _, c := range v.Children {
|
|
||||||
if len(c.Children) > 0 {
|
|
||||||
for _, gc := range c.Children {
|
|
||||||
if len(gc.MountPoint) > 0 {
|
|
||||||
disk[gc.MountPoint] = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(c.MountPoint) > 0 {
|
|
||||||
disk[c.MountPoint] = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < len(info); i++ {
|
|
||||||
if v, ok := disk[info[i].Path]; ok {
|
|
||||||
info[i].Type = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//Hide the files or folders in operation
|
for i := 0; i < len(info); i++ {
|
||||||
|
if v, ok := sharesMap[info[i].Path]; ok {
|
||||||
|
ex := make(map[string]interface{})
|
||||||
|
|
||||||
|
shareEx := make(map[string]string)
|
||||||
|
shareEx["shared"] = "true"
|
||||||
|
shareEx["id"] = v
|
||||||
|
ex["share"] = shareEx
|
||||||
|
info[i].Extensions = ex
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// Hide the files or folders in operation
|
||||||
fileQueue := make(map[string]string)
|
fileQueue := make(map[string]string)
|
||||||
if len(service.OpStrArr) > 0 {
|
if len(service.OpStrArr) > 0 {
|
||||||
for _, v := range service.OpStrArr {
|
for _, v := range service.OpStrArr {
|
||||||
@@ -292,12 +252,15 @@ func DirPath(c *gin.Context) {
|
|||||||
|
|
||||||
pathList := []model.Path{}
|
pathList := []model.Path{}
|
||||||
for i := 0; i < len(info); i++ {
|
for i := 0; i < len(info); i++ {
|
||||||
|
if info[i].Name == ".temp" && info[i].IsDir {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if _, ok := fileQueue[info[i].Path]; !ok {
|
if _, ok := fileQueue[info[i].Path]; !ok {
|
||||||
pathList = append(pathList, info[i])
|
pathList = append(pathList, info[i])
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: pathList})
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: pathList})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary rename file or dir
|
// @Summary rename file or dir
|
||||||
@@ -311,15 +274,15 @@ func DirPath(c *gin.Context) {
|
|||||||
// @Router /file/rename [put]
|
// @Router /file/rename [put]
|
||||||
func RenamePath(c *gin.Context) {
|
func RenamePath(c *gin.Context) {
|
||||||
json := make(map[string]string)
|
json := make(map[string]string)
|
||||||
c.BindJSON(&json)
|
c.ShouldBind(&json)
|
||||||
op := json["oldpath"]
|
op := json["old_path"]
|
||||||
np := json["newpath"]
|
np := json["new_path"]
|
||||||
if len(op) == 0 || len(np) == 0 {
|
if len(op) == 0 || len(np) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
success, err := service.MyService.System().RenameFile(op, np)
|
success, err := service.MyService.System().RenameFile(op, np)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: success, Message: common_err.GetMsg(success), Data: err})
|
c.JSON(common_err.SUCCESS, model.Result{Success: success, Message: common_err.GetMsg(success), Data: err})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary create folder
|
// @Summary create folder
|
||||||
@@ -332,11 +295,11 @@ func RenamePath(c *gin.Context) {
|
|||||||
// @Router /file/mkdir [post]
|
// @Router /file/mkdir [post]
|
||||||
func MkdirAll(c *gin.Context) {
|
func MkdirAll(c *gin.Context) {
|
||||||
json := make(map[string]string)
|
json := make(map[string]string)
|
||||||
c.BindJSON(&json)
|
c.ShouldBind(&json)
|
||||||
path := json["path"]
|
path := json["path"]
|
||||||
var code int
|
var code int
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// decodedPath, err := url.QueryUnescape(path)
|
// decodedPath, err := url.QueryUnescape(path)
|
||||||
@@ -345,7 +308,7 @@ func MkdirAll(c *gin.Context) {
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
code, _ = service.MyService.System().MkdirAll(path)
|
code, _ = service.MyService.System().MkdirAll(path)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: code, Message: common_err.GetMsg(code)})
|
c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary create file
|
// @Summary create file
|
||||||
@@ -358,11 +321,11 @@ func MkdirAll(c *gin.Context) {
|
|||||||
// @Router /file/create [post]
|
// @Router /file/create [post]
|
||||||
func PostCreateFile(c *gin.Context) {
|
func PostCreateFile(c *gin.Context) {
|
||||||
json := make(map[string]string)
|
json := make(map[string]string)
|
||||||
c.BindJSON(&json)
|
c.ShouldBind(&json)
|
||||||
path := json["path"]
|
path := json["path"]
|
||||||
var code int
|
var code int
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// decodedPath, err := url.QueryUnescape(path)
|
// decodedPath, err := url.QueryUnescape(path)
|
||||||
@@ -371,7 +334,7 @@ func PostCreateFile(c *gin.Context) {
|
|||||||
// return
|
// return
|
||||||
// }
|
// }
|
||||||
code, _ = service.MyService.System().CreateFile(path)
|
code, _ = service.MyService.System().CreateFile(path)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: code, Message: common_err.GetMsg(code)})
|
c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary upload file
|
// @Summary upload file
|
||||||
@@ -384,7 +347,6 @@ func PostCreateFile(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/upload [get]
|
// @Router /file/upload [get]
|
||||||
func GetFileUpload(c *gin.Context) {
|
func GetFileUpload(c *gin.Context) {
|
||||||
|
|
||||||
relative := c.Query("relativePath")
|
relative := c.Query("relativePath")
|
||||||
fileName := c.Query("filename")
|
fileName := c.Query("filename")
|
||||||
chunkNumber := c.Query("chunkNumber")
|
chunkNumber := c.Query("chunkNumber")
|
||||||
@@ -392,7 +354,7 @@ func GetFileUpload(c *gin.Context) {
|
|||||||
path := c.Query("path")
|
path := c.Query("path")
|
||||||
dirPath := ""
|
dirPath := ""
|
||||||
hash := file.GetHashByContent([]byte(fileName))
|
hash := file.GetHashByContent([]byte(fileName))
|
||||||
tempDir := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/"
|
tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
|
||||||
if fileName != relative {
|
if fileName != relative {
|
||||||
dirPath = strings.TrimSuffix(relative, fileName)
|
dirPath = strings.TrimSuffix(relative, fileName)
|
||||||
tempDir += dirPath
|
tempDir += dirPath
|
||||||
@@ -428,54 +390,90 @@ func PostFileUpload(c *gin.Context) {
|
|||||||
hash := file.GetHashByContent([]byte(fileName))
|
hash := file.GetHashByContent([]byte(fileName))
|
||||||
|
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
c.JSON(common_err.INVALID_PARAMS, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
logger.Error("path should not be empty")
|
||||||
|
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tempDir := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/"
|
tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
|
||||||
|
|
||||||
if fileName != relative {
|
if fileName != relative {
|
||||||
dirPath = strings.TrimSuffix(relative, fileName)
|
dirPath = strings.TrimSuffix(relative, fileName)
|
||||||
tempDir += dirPath
|
tempDir += dirPath
|
||||||
file.MkDir(path + "/" + dirPath)
|
if err := file.MkDir(path + "/" + dirPath); err != nil {
|
||||||
|
logger.Error("error when trying to create `"+path+"/"+dirPath+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
path += "/" + relative
|
path += "/" + relative
|
||||||
|
|
||||||
if !file.CheckNotExist(tempDir + chunkNumber) {
|
if !file.CheckNotExist(tempDir + chunkNumber) {
|
||||||
file.RMDir(tempDir + chunkNumber)
|
if err := file.RMDir(tempDir + chunkNumber); err != nil {
|
||||||
|
logger.Error("error when trying to remove existing `"+tempDir+chunkNumber+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if totalChunks > 1 {
|
if totalChunks > 1 {
|
||||||
file.IsNotExistMkDir(tempDir)
|
if err := file.IsNotExistMkDir(tempDir); err != nil {
|
||||||
|
logger.Error("error when trying to create `"+tempDir+"`", zap.Error(err))
|
||||||
out, _ := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0644)
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
defer out.Close()
|
|
||||||
_, err := io.Copy(out, f)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out, err := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0o644)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("error when trying to open `"+tempDir+chunkNumber+"` for creation", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer out.Close()
|
||||||
|
|
||||||
|
if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
|
||||||
|
logger.Error("error when trying to write to `"+tempDir+chunkNumber+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fileNum, err := ioutil.ReadDir(tempDir)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("error when trying to read number of files under `"+tempDir+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if totalChunks == len(fileNum) {
|
||||||
|
if err := file.SpliceFiles(tempDir, path, totalChunks, 1); err != nil {
|
||||||
|
logger.Error("error when trying to splice files under `"+tempDir+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := file.RMDir(tempDir); err != nil {
|
||||||
|
logger.Error("error when trying to remove `"+tempDir+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
|
out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o644)
|
||||||
defer out.Close()
|
|
||||||
_, err := io.Copy(out, f)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
logger.Error("error when trying to open `"+path+"` for creation", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fileNum, err := ioutil.ReadDir(tempDir)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if totalChunks == len(fileNum) {
|
|
||||||
file.SpliceFiles(tempDir, path, totalChunks, 1)
|
|
||||||
file.RMDir(tempDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
|
defer out.Close()
|
||||||
|
|
||||||
|
if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
|
||||||
|
logger.Error("error when trying to write to `"+path+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -488,16 +486,15 @@ func PostFileUpload(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/operate [post]
|
// @Router /file/operate [post]
|
||||||
func PostOperateFileOrDir(c *gin.Context) {
|
func PostOperateFileOrDir(c *gin.Context) {
|
||||||
|
|
||||||
list := model.FileOperate{}
|
list := model.FileOperate{}
|
||||||
c.BindJSON(&list)
|
c.ShouldBind(&list)
|
||||||
|
|
||||||
if len(list.Item) == 0 {
|
if len(list.Item) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if list.To == list.Item[0].From[:strings.LastIndex(list.Item[0].From, "/")] {
|
if list.To == list.Item[0].From[:strings.LastIndex(list.Item[0].From, "/")] {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SOURCE_DES_SAME, Message: common_err.GetMsg(common_err.SOURCE_DES_SAME)})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SOURCE_DES_SAME, Message: common_err.GetMsg(common_err.SOURCE_DES_SAME)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -526,7 +523,7 @@ func PostOperateFileOrDir(c *gin.Context) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary delete file
|
// @Summary delete file
|
||||||
@@ -538,11 +535,10 @@ func PostOperateFileOrDir(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/delete [delete]
|
// @Router /file/delete [delete]
|
||||||
func DeleteFile(c *gin.Context) {
|
func DeleteFile(c *gin.Context) {
|
||||||
|
|
||||||
paths := []string{}
|
paths := []string{}
|
||||||
c.BindJSON(&paths)
|
c.ShouldBind(&paths)
|
||||||
if len(paths) == 0 {
|
if len(paths) == 0 {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// path := c.Query("path")
|
// path := c.Query("path")
|
||||||
@@ -552,12 +548,12 @@ func DeleteFile(c *gin.Context) {
|
|||||||
for _, v := range paths {
|
for _, v := range paths {
|
||||||
err := os.RemoveAll(v)
|
err := os.RemoveAll(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary update file
|
// @Summary update file
|
||||||
@@ -570,28 +566,27 @@ func DeleteFile(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/update [put]
|
// @Router /file/update [put]
|
||||||
func PutFileContent(c *gin.Context) {
|
func PutFileContent(c *gin.Context) {
|
||||||
|
|
||||||
fi := model.FileUpdate{}
|
fi := model.FileUpdate{}
|
||||||
c.BindJSON(&fi)
|
c.ShouldBind(&fi)
|
||||||
|
|
||||||
// path := c.PostForm("path")
|
// path := c.PostForm("path")
|
||||||
// content := c.PostForm("content")
|
// content := c.PostForm("content")
|
||||||
if !file.Exists(fi.FilePath) {
|
if !file.Exists(fi.FilePath) {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//err := os.Remove(path)
|
// err := os.Remove(path)
|
||||||
err := os.RemoveAll(fi.FilePath)
|
err := os.RemoveAll(fi.FilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
err = file.CreateFileAndWriteContent(fi.FilePath, fi.FileContent)
|
err = file.CreateFileAndWriteContent(fi.FilePath, fi.FileContent)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary image thumbnail/original image
|
// @Summary image thumbnail/original image
|
||||||
@@ -607,13 +602,13 @@ func GetFileImage(c *gin.Context) {
|
|||||||
t := c.Query("type")
|
t := c.Query("type")
|
||||||
path := c.Query("path")
|
path := c.Query("path")
|
||||||
if !file.Exists(path) {
|
if !file.Exists(path) {
|
||||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if t == "thumbnail" {
|
if t == "thumbnail" {
|
||||||
f, err := file.GetImage(path, 100, 0)
|
f, err := file.GetImage(path, 100, 0)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Writer.WriteString(string(f))
|
c.Writer.WriteString(string(f))
|
||||||
@@ -621,13 +616,13 @@ func GetFileImage(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
f, err := os.Open(path)
|
f, err := os.Open(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer f.Close()
|
defer f.Close()
|
||||||
data, err := ioutil.ReadAll(f)
|
data, err := ioutil.ReadAll(f)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.Writer.WriteString(string(data))
|
c.Writer.WriteString(string(data))
|
||||||
@@ -652,5 +647,5 @@ func DeleteOperateFileOrDir(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
go service.MyService.Notify().SendFileOperateNotify(true)
|
go service.MyService.Notify().SendFileOperateNotify(true)
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|||||||
56
route/v1/notify.go
Normal file
56
route/v1/notify.go
Normal file
@@ -0,0 +1,56 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/model/notify"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PostNotifyMessage(c *gin.Context) {
|
||||||
|
path := c.Param("path")
|
||||||
|
message := make(map[string]interface{})
|
||||||
|
if err := c.ShouldBind(&message); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
service.MyService.Notify().SendNotify(path, message)
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostSystemStatusNotify(c *gin.Context) {
|
||||||
|
message := make(map[string]interface{})
|
||||||
|
if err := c.ShouldBind(&message); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
service.MyService.Notify().SettingSystemTempData(message)
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostInstallAppNotify(c *gin.Context) {
|
||||||
|
app := notify.Application{}
|
||||||
|
if err := c.ShouldBind(&app); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
service.MyService.Notify().SendInstallAppBySocket(app)
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostUninstallAppNotify(c *gin.Context) {
|
||||||
|
app := notify.Application{}
|
||||||
|
if err := c.ShouldBind(&app); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
service.MyService.Notify().SendUninstallAppBySocket(app)
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
|
}
|
||||||
@@ -1,804 +0,0 @@
|
|||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"bytes"
|
|
||||||
"encoding/base64"
|
|
||||||
"encoding/gob"
|
|
||||||
"encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"net"
|
|
||||||
"net/http"
|
|
||||||
"os"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
natType "github.com/Curtis-Milo/nat-type-identifier-go"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
"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/IceWhaleTech/CasaOS/types"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
uuid "github.com/satori/go.uuid"
|
|
||||||
)
|
|
||||||
|
|
||||||
// @Summary Retry the file that failed to download
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Param uui path string true "download uuid"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/refile/{uuid} [get]
|
|
||||||
func GetPersonReFile(c *gin.Context) {
|
|
||||||
|
|
||||||
uid := c.Param("uuid")
|
|
||||||
_, err := uuid.FromString(uid)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
task := service.MyService.Download().GetDownloadById(uid)
|
|
||||||
if reflect.DeepEqual(task, model2.PersonDownloadDBModel{}) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_REMOTE_ERROR, Message: common_err.GetMsg(common_err.PERSON_REMOTE_ERROR)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
token := task.From
|
|
||||||
if _, ok := service.UDPAddressMap[token]; !ok {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_REMOTE_ERROR, Message: common_err.GetMsg(common_err.PERSON_REMOTE_ERROR)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
m := model.MessageModel{}
|
|
||||||
m.Data = task.Path
|
|
||||||
m.From = config.ServerInfo.Token
|
|
||||||
m.To = token
|
|
||||||
m.Type = types.PERSONDOWNLOAD
|
|
||||||
m.UUId = uid
|
|
||||||
go service.Dial(m, false)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary download file
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Param share_id query string true "opponent share_id"
|
|
||||||
// @Param path query string true "file path"
|
|
||||||
// @Param file_name query string true "file name"
|
|
||||||
// @Param local_path query string true "local_path"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/file [get]
|
|
||||||
func GetPersonFile(c *gin.Context) {
|
|
||||||
|
|
||||||
path := c.Query("path")
|
|
||||||
localPath := c.Query("local_path")
|
|
||||||
token := c.Query("share_id")
|
|
||||||
fileName := c.Query("file_name")
|
|
||||||
_, err := uuid.FromString(token)
|
|
||||||
if len(path) == 0 || err != nil || len(localPath) == 0 || len(fileName) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if file.CheckNotExist(localPath) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, ok := service.UDPAddressMap[token]; !ok {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_REMOTE_ERROR, Message: common_err.GetMsg(common_err.PERSON_REMOTE_ERROR)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := service.UDPAddressMap[token]; !ok {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_REMOTE_ERROR, Message: common_err.GetMsg(common_err.PERSON_REMOTE_ERROR)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// task id
|
|
||||||
uuid := uuid.NewV4().String()
|
|
||||||
|
|
||||||
task := model2.PersonDownloadDBModel{}
|
|
||||||
task.UUID = uuid
|
|
||||||
task.Name = fileName
|
|
||||||
task.Length = 0
|
|
||||||
task.From = token
|
|
||||||
task.Path = path
|
|
||||||
task.Size = 0
|
|
||||||
task.State = types.DOWNLOADAWAIT
|
|
||||||
task.Created = time.Now().Unix()
|
|
||||||
task.Type = types.PERSONFILEDOWNLOAD
|
|
||||||
task.LocalPath = localPath
|
|
||||||
if service.MyService.Download().GetDownloadListByPath(task) > 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_EXIST_DOWNLOAD, Message: common_err.GetMsg(common_err.PERSON_EXIST_DOWNLOAD)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
service.MyService.Download().AddDownloadTask(task)
|
|
||||||
|
|
||||||
m := model.MessageModel{}
|
|
||||||
m.Data = path
|
|
||||||
m.From = config.ServerInfo.Token
|
|
||||||
m.To = token
|
|
||||||
m.Type = types.PERSONDOWNLOAD
|
|
||||||
m.UUId = uuid
|
|
||||||
go service.Dial(m, false)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary delete download file records
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Param uuid path string true "download uuid"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/file/{uuid} [delete]
|
|
||||||
func DeletePersonDownloadFile(c *gin.Context) {
|
|
||||||
|
|
||||||
id := c.Param("uuid")
|
|
||||||
_, err := uuid.FromString(id)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
task := service.MyService.Download().GetDownloadById(id)
|
|
||||||
if task.State == types.DOWNLOADING {
|
|
||||||
m := model.MessageModel{}
|
|
||||||
m.Data = ""
|
|
||||||
m.From = config.ServerInfo.Token
|
|
||||||
m.To = task.From
|
|
||||||
m.Type = types.PERSONCANCEL
|
|
||||||
m.UUId = task.UUID
|
|
||||||
service.CancelList[task.UUID] = task.UUID
|
|
||||||
service.Dial(m, false)
|
|
||||||
}
|
|
||||||
service.MyService.Download().DelDownload(id)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Get file download list
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Param state query int false "wait:0,downloading:1,pause:2,finish:3,error:4,finished:5" Enums(0,1,2,3,4,5)
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {object} []model2.PersonDownloadDBModel
|
|
||||||
// @Router /person/list [get]
|
|
||||||
func GetPersonDownloadList(c *gin.Context) {
|
|
||||||
state := c.DefaultQuery("state", "")
|
|
||||||
list := service.MyService.Download().GetDownloadListByState(state, types.PERSONFILEDOWNLOAD)
|
|
||||||
//if it is downloading, it need to add 'already'
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
if list[i].State == types.DOWNLOADING {
|
|
||||||
tempDir := config.AppInfo.TempPath + "/" + list[i].UUID
|
|
||||||
files, err := ioutil.ReadDir(tempDir)
|
|
||||||
if err == nil {
|
|
||||||
list[i].Already = len(files)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
list[i].Duration = time.Now().Unix() - list[i].Created
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary edit friend's remarks
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Param remarks formData string true "remarks name"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/remarks/{shareid} [put]
|
|
||||||
func PutPersonRemarks(c *gin.Context) {
|
|
||||||
token := c.Param("shareid")
|
|
||||||
_, err := uuid.FromString(token)
|
|
||||||
mark := c.PostForm("remarks")
|
|
||||||
if err != nil || len(mark) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
friend := model2.FriendModel{}
|
|
||||||
friend.Token = token
|
|
||||||
friend.Mark = mark
|
|
||||||
service.MyService.Friend().EditFriendMark(friend)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary edit friend's
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Param write formData bool true "write"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/write/{shareid} [put]
|
|
||||||
func PutPersonWrite(c *gin.Context) {
|
|
||||||
token := c.Param("shareid")
|
|
||||||
_, err := uuid.FromString(token)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
write, _ := strconv.ParseBool(c.PostForm("write"))
|
|
||||||
friend := model2.FriendModel{}
|
|
||||||
friend.Token = token
|
|
||||||
friend.Write = write
|
|
||||||
service.MyService.Friend().EditFriendMark(friend)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary image thumbnail
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Param write formData bool true "write"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/image/thumbnail/{shareid} [get]
|
|
||||||
func GetPersonImageThumbnail(c *gin.Context) {
|
|
||||||
token := c.Param("shareid")
|
|
||||||
path := c.Query("path")
|
|
||||||
_, err := uuid.FromString(token)
|
|
||||||
if err != nil || len(path) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uuid := uuid.NewV4().String()
|
|
||||||
m := model.MessageModel{}
|
|
||||||
m.Data = path
|
|
||||||
m.From = config.ServerInfo.Token
|
|
||||||
m.To = token
|
|
||||||
m.Type = types.PERSONIMAGETHUMBNAIL
|
|
||||||
m.UUId = uuid
|
|
||||||
|
|
||||||
img, err := service.Dial(m, false)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
// var buf bytes.Buffer
|
|
||||||
//err = gob.NewEncoder(&buf).Encode(img.Data)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
var buf bytes.Buffer
|
|
||||||
err = gob.NewEncoder(&buf).Encode(img.Data)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
imageBuffer, _ := base64.StdEncoding.DecodeString(img.Data.(string))
|
|
||||||
c.Writer.WriteString(string(imageBuffer))
|
|
||||||
// c.String(http.StatusOK, "data:image/"+filesuffix+";base64,"+img.Data.(string))
|
|
||||||
//c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: img.Data.(string)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary get my friend list
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {object} []model2.FriendModel
|
|
||||||
// @Router /person/users [get]
|
|
||||||
func GetPersonFriend(c *gin.Context) {
|
|
||||||
list := service.MyService.Friend().GetFriendList()
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
if v, ok := service.UDPAddressMap[list[i].Token]; ok && len(v) > 0 {
|
|
||||||
list[i].OnLine = true
|
|
||||||
if ip_helper.HasLocalIP(net.ParseIP(strings.Split(v, ":")[0])) {
|
|
||||||
list[i].LocalIP = strings.Split(v, ":")[0]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary network type detection
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/detection [get]
|
|
||||||
func GetPersonDetection(c *gin.Context) {
|
|
||||||
// - Blocked
|
|
||||||
// - Open Internet
|
|
||||||
// - Full Cone
|
|
||||||
// - Symmetric UDP Firewall
|
|
||||||
// - Restric NAT
|
|
||||||
// - Restric Port NAT
|
|
||||||
// - Symmetric NAT
|
|
||||||
|
|
||||||
result, err := natType.GetDeterminedNatType(true, 5, "stun.l.google.com")
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
//result := service.MyService.Person().GetPersionNetWorkTypeDetection()
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: result})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary add friend
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/user/{shareids} [post]
|
|
||||||
func PostAddPersonFriend(c *gin.Context) {
|
|
||||||
token := c.Param("shareids")
|
|
||||||
tokenList := strings.Split(token, ",")
|
|
||||||
|
|
||||||
for _, v := range tokenList {
|
|
||||||
_, err := uuid.FromString(v)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if v == config.ServerInfo.Token {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_MYSELF, Message: common_err.GetMsg(common_err.PERSON_MYSELF)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
udb := service.MyService.Friend().GetFriendById(model2.FriendModel{Token: v})
|
|
||||||
if !reflect.DeepEqual(udb, model2.FriendModel{Token: v}) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_EXIST_FRIEND, Message: common_err.GetMsg(common_err.PERSON_EXIST_FRIEND)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user := service.MyService.Casa().GetUserInfoByShareId(v)
|
|
||||||
if reflect.DeepEqual(user, model.UserInfo{}) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_NOT_EXIST_USER, Message: common_err.GetMsg(common_err.PERSON_NOT_EXIST_USER)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
message := model.MessageModel{}
|
|
||||||
message.Type = types.PERSONCONNECTION
|
|
||||||
message.Data = v
|
|
||||||
message.From = config.ServerInfo.Token
|
|
||||||
message.To = v
|
|
||||||
message.UUId = uuid.NewV4().String()
|
|
||||||
|
|
||||||
go service.Dial(message, true)
|
|
||||||
|
|
||||||
msg := model.MessageModel{}
|
|
||||||
msg.Type = types.PERSONGETIP
|
|
||||||
msg.Data = ""
|
|
||||||
msg.From = config.ServerInfo.Token
|
|
||||||
msg.To = v
|
|
||||||
msg.UUId = uuid.NewV4().String()
|
|
||||||
|
|
||||||
service.Dial(msg, true)
|
|
||||||
|
|
||||||
friend := model2.FriendModel{}
|
|
||||||
friend.Token = v
|
|
||||||
friend.Avatar = user.Avatar
|
|
||||||
friend.Block = false
|
|
||||||
friend.State = types.FRIENDSTATEWAIT
|
|
||||||
friend.NickName = user.NickName
|
|
||||||
friend.Profile = user.Desc
|
|
||||||
friend.Version = user.Version
|
|
||||||
service.MyService.Friend().AddFriend(friend)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Get a list of directories
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Param share_id query string true "Opponent share_id"
|
|
||||||
// @Param path query string true "dir path"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {object} []model.Path
|
|
||||||
// @Router /person/directory [get]
|
|
||||||
func GetPersonDirectory(c *gin.Context) {
|
|
||||||
path := c.Query("path")
|
|
||||||
token := c.Query("share_id")
|
|
||||||
_, err := uuid.FromString(token)
|
|
||||||
if len(path) == 0 || err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, ok := service.UDPAddressMap[token]; !ok {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_REMOTE_ERROR, Message: common_err.GetMsg(common_err.PERSON_REMOTE_ERROR)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uuid := uuid.NewV4().String()
|
|
||||||
m := model.MessageModel{}
|
|
||||||
m.Data = path
|
|
||||||
m.From = config.ServerInfo.Token
|
|
||||||
m.To = token
|
|
||||||
m.Type = types.PERSONDIRECTORY
|
|
||||||
m.UUId = uuid
|
|
||||||
result, err := service.Dial(m, false)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
dataModel := []model.Path{}
|
|
||||||
if uuid == m.UUId {
|
|
||||||
dataModelByte, _ := json.Marshal(result.Data)
|
|
||||||
err := json.Unmarshal(dataModelByte, &dataModel)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: dataModel})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Modify the download storage directory
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "path"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/down/dir [post]
|
|
||||||
func PostPersonDownDir(c *gin.Context) {
|
|
||||||
|
|
||||||
downPath := c.PostForm("path")
|
|
||||||
|
|
||||||
if len(downPath) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if file.CheckNotExist(downPath) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
config.Cfg.Section("file").Key("DownloadDir").SetValue(downPath)
|
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
config.FileSettingInfo.DownloadDir = downPath
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Get the download storage directory
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/down/dir [get]
|
|
||||||
func GetPersonDownDir(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: config.FileSettingInfo.DownloadDir})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Modify the shared directory
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param share formData string true "share"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/share [post]
|
|
||||||
func PostPersonShare(c *gin.Context) {
|
|
||||||
|
|
||||||
share := c.PostForm("share")
|
|
||||||
|
|
||||||
if len(share) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
var list []string
|
|
||||||
json.Unmarshal([]byte(share), &list)
|
|
||||||
|
|
||||||
if len(list) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
for _, v := range list {
|
|
||||||
if !file.Exists(v) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
config.Cfg.Section("file").Key("ShareDir").SetValue(strings.Join(list, "|"))
|
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
config.FileSettingInfo.ShareDir = list
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Get the shared directory
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/share [get]
|
|
||||||
func GetPersonShare(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: config.FileSettingInfo.ShareDir})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Get the shareid
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/shareid [get]
|
|
||||||
func GetPersonShareId(c *gin.Context) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: config.ServerInfo.Token})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Modify disabled status
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Param block formData bool false "Disable or not,Default:false "
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/block/{shareid} [put]
|
|
||||||
func PutPersonBlock(c *gin.Context) {
|
|
||||||
token := c.Param("shareid")
|
|
||||||
_, err := uuid.FromString(token)
|
|
||||||
block, _ := strconv.ParseBool(c.PostForm("block"))
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
friend := model2.FriendModel{}
|
|
||||||
friend.Token = token
|
|
||||||
friend.Block = block
|
|
||||||
service.MyService.Friend().EditFriendBlock(friend)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Delete my friend
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/user/{shareid} [delete]
|
|
||||||
func DeletePersonFriend(c *gin.Context) {
|
|
||||||
token := c.Param("shareid")
|
|
||||||
_, err := uuid.FromString(token)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
friend := model2.FriendModel{}
|
|
||||||
friend.Token = token
|
|
||||||
|
|
||||||
service.MyService.Friend().DeleteFriend(friend)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary Get public person
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/public [get]
|
|
||||||
func GetPersonPublic(c *gin.Context) {
|
|
||||||
list := service.MyService.Casa().GetPersonPublic()
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary upload file to friend
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "Destination path"
|
|
||||||
// @Param local_path formData string true "Full path of the file to be uploaded"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/file/{shareid} [post]
|
|
||||||
func PostPersonFile(c *gin.Context) {
|
|
||||||
token := c.Param("shareid")
|
|
||||||
_, err := uuid.FromString(token)
|
|
||||||
path := c.PostForm("path")
|
|
||||||
localPath := c.PostForm("local_path")
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !file.Exists(localPath) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
uuid := uuid.NewV4().String()
|
|
||||||
m := model.MessageModel{}
|
|
||||||
m.Data = path
|
|
||||||
m.From = config.ServerInfo.Token
|
|
||||||
m.To = token
|
|
||||||
m.Type = types.PERSONUPLOAD
|
|
||||||
m.UUId = uuid
|
|
||||||
go service.UDPSendData(m, localPath)
|
|
||||||
|
|
||||||
f, _ := os.Stat(localPath)
|
|
||||||
|
|
||||||
task := model2.PersonDownloadDBModel{}
|
|
||||||
task.UUID = uuid
|
|
||||||
task.Name = f.Name()
|
|
||||||
task.Length = 0
|
|
||||||
task.From = token
|
|
||||||
task.Path = path
|
|
||||||
task.Size = f.Size()
|
|
||||||
task.State = types.DOWNLOADFINISHED
|
|
||||||
task.Created = time.Now().Unix()
|
|
||||||
task.Type = types.PERSONFILEUPLOAD
|
|
||||||
task.LocalPath = localPath
|
|
||||||
if service.MyService.Download().GetDownloadListByPath(task) > 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.PERSON_EXIST_DOWNLOAD, Message: common_err.GetMsg(common_err.PERSON_EXIST_DOWNLOAD)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
service.MyService.Download().AddDownloadTask(task)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary agree add friend
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags person
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /person/friend/{shareid} [put]
|
|
||||||
func PutPersonAgreeFriend(c *gin.Context) {
|
|
||||||
token := c.Param("shareid")
|
|
||||||
_, err := uuid.FromString(token)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user := service.MyService.Friend().GetFriendById(model2.FriendModel{Token: token})
|
|
||||||
|
|
||||||
if user.State != types.FRIENDSTATEREQUEST {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.COMMAND_ERROR_INVALID_OPERATION, Message: common_err.GetMsg(common_err.COMMAND_ERROR_INVALID_OPERATION)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
service.MyService.Friend().AgreeFrined(user.Token)
|
|
||||||
|
|
||||||
uuid := uuid.NewV4().String()
|
|
||||||
m := model.MessageModel{}
|
|
||||||
m.Data = ""
|
|
||||||
m.From = config.ServerInfo.Token
|
|
||||||
m.To = token
|
|
||||||
m.Type = types.PERSONAGREEFRIEND
|
|
||||||
m.UUId = uuid
|
|
||||||
go service.Dial(m, true)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// // @Summary upload file
|
|
||||||
// // @Produce application/json
|
|
||||||
// // @Accept multipart/form-data
|
|
||||||
// // @Tags person
|
|
||||||
// // @Security ApiKeyAuth
|
|
||||||
// // @Param path formData string false "file path"
|
|
||||||
// // @Param file formData file true "file"
|
|
||||||
// // @Success 200 {string} string "ok"
|
|
||||||
// // @Router /person/upload/{shareid} [get]
|
|
||||||
// func GetPersonFileUpload(c *gin.Context) {
|
|
||||||
|
|
||||||
// token := c.Param("shareid")
|
|
||||||
// _, err := uuid.FromString(token)
|
|
||||||
// path := c.Query("path")
|
|
||||||
// if err != nil {
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// relative := c.Query("relativePath")
|
|
||||||
// fileName := c.Query("filename")
|
|
||||||
// chunkNumber := c.Query("chunkNumber")
|
|
||||||
// totalChunks, _ := strconv.Atoi(c.DefaultQuery("totalChunks", "0"))
|
|
||||||
// dirPath := ""
|
|
||||||
// hash := file.GetHashByContent([]byte(fileName))
|
|
||||||
// tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
|
|
||||||
// if fileName != relative {
|
|
||||||
// dirPath = strings.TrimSuffix(relative, fileName)
|
|
||||||
// tempDir += dirPath
|
|
||||||
// file.MkDir(path + "/" + dirPath)
|
|
||||||
// }
|
|
||||||
// tempDir += chunkNumber
|
|
||||||
// if !file.CheckNotExist(tempDir) {
|
|
||||||
// c.JSON(200, model.Result{Success: 200, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// c.JSON(204, model.Result{Success: 204, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
// }
|
|
||||||
|
|
||||||
// // @Summary upload file
|
|
||||||
// // @Produce application/json
|
|
||||||
// // @Accept multipart/form-data
|
|
||||||
// // @Tags person
|
|
||||||
// // @Security ApiKeyAuth
|
|
||||||
// // @Param path formData string false "file path"
|
|
||||||
// // @Param file formData file true "file"
|
|
||||||
// // @Success 200 {string} string "ok"
|
|
||||||
// // @Router /person/upload [post]
|
|
||||||
// func PostPersonFileUpload(c *gin.Context) {
|
|
||||||
// token := c.Param("shareid")
|
|
||||||
// _, err := uuid.FromString(token)
|
|
||||||
// if err != nil {
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// f, _, _ := c.Request.FormFile("file")
|
|
||||||
// relative := c.PostForm("relativePath")
|
|
||||||
// fileName := c.PostForm("filename")
|
|
||||||
// totalChunks, _ := strconv.Atoi(c.DefaultPostForm("totalChunks", "0"))
|
|
||||||
// chunkNumber := c.PostForm("chunkNumber")
|
|
||||||
// dirPath := ""
|
|
||||||
// path := c.PostForm("path")
|
|
||||||
|
|
||||||
// hash := file.GetHashByContent([]byte(fileName))
|
|
||||||
|
|
||||||
// if len(path) == 0 {
|
|
||||||
// c.JSON(common_err.INVALID_PARAMS, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
|
|
||||||
|
|
||||||
// if fileName != relative {
|
|
||||||
// dirPath = strings.TrimSuffix(relative, fileName)
|
|
||||||
// tempDir += dirPath
|
|
||||||
// file.MkDir(path + "/" + dirPath)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// path += "/" + relative
|
|
||||||
|
|
||||||
// if !file.CheckNotExist(tempDir + chunkNumber) {
|
|
||||||
// file.RMDir(tempDir + chunkNumber)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// if totalChunks > 1 {
|
|
||||||
// file.IsNotExistMkDir(tempDir)
|
|
||||||
|
|
||||||
// out, _ := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0644)
|
|
||||||
// defer out.Close()
|
|
||||||
// _, err := io.Copy(out, f)
|
|
||||||
// if err != nil {
|
|
||||||
// c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// } else {
|
|
||||||
// out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
|
|
||||||
// defer out.Close()
|
|
||||||
// _, err := io.Copy(out, f)
|
|
||||||
// if err != nil {
|
|
||||||
// c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
|
|
||||||
// fileNum, err := ioutil.ReadDir(tempDir)
|
|
||||||
// if err != nil {
|
|
||||||
// c.JSON(common_err.ERROR, model.Result{Success: common_err.ERROR, Message: common_err.GetMsg(common_err.ERROR), Data: err.Error()})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
// if totalChunks == len(fileNum) {
|
|
||||||
// file.RMDir(tempDir)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
// }
|
|
||||||
201
route/v1/samba.go
Normal file
201
route/v1/samba.go
Normal file
@@ -0,0 +1,201 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.com
|
||||||
|
* @Date: 2022-07-26 11:08:48
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-17 18:25:42
|
||||||
|
* @FilePath: /CasaOS/route/v1/samba.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"regexp"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"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"
|
||||||
|
)
|
||||||
|
|
||||||
|
// service
|
||||||
|
|
||||||
|
func GetSambaStatus(c *gin.Context) {
|
||||||
|
status := service.MyService.System().IsServiceRunning("smbd")
|
||||||
|
|
||||||
|
if !status {
|
||||||
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_NOT_RUNNING, Message: common_err.GetMsg(common_err.SERVICE_NOT_RUNNING)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
needInit := true
|
||||||
|
if file.Exists("/etc/samba/smb.conf") {
|
||||||
|
str := file.ReadLine(1, "/etc/samba/smb.conf")
|
||||||
|
if strings.Contains(str, "# Copyright (c) 2021-2022 CasaOS Inc. All rights reserved.") {
|
||||||
|
needInit = false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
data := make(map[string]string, 1)
|
||||||
|
data["need_init"] = fmt.Sprintf("%v", needInit)
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSambaSharesList(c *gin.Context) {
|
||||||
|
shares := service.MyService.Shares().GetSharesList()
|
||||||
|
shareList := []model.Shares{}
|
||||||
|
for _, v := range shares {
|
||||||
|
shareList = append(shareList, model.Shares{
|
||||||
|
Anonymous: v.Anonymous,
|
||||||
|
Path: v.Path,
|
||||||
|
ID: v.ID,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: shareList})
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostSambaSharesCreate(c *gin.Context) {
|
||||||
|
shares := []model.Shares{}
|
||||||
|
c.ShouldBindJSON(&shares)
|
||||||
|
for _, v := range shares {
|
||||||
|
if v.Path == "" {
|
||||||
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !file.Exists(v.Path) {
|
||||||
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(service.MyService.Shares().GetSharesByPath(v.Path)) > 0 {
|
||||||
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.SHARE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.SHARE_ALREADY_EXISTS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(service.MyService.Shares().GetSharesByPath(filepath.Base(v.Path))) > 0 {
|
||||||
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.SHARE_NAME_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.SHARE_NAME_ALREADY_EXISTS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
for _, v := range shares {
|
||||||
|
shareDBModel := model2.SharesDBModel{}
|
||||||
|
shareDBModel.Anonymous = true
|
||||||
|
shareDBModel.Path = v.Path
|
||||||
|
shareDBModel.Name = filepath.Base(v.Path)
|
||||||
|
os.Chmod(v.Path, 0777)
|
||||||
|
service.MyService.Shares().CreateShare(shareDBModel)
|
||||||
|
}
|
||||||
|
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: shares})
|
||||||
|
}
|
||||||
|
func DeleteSambaShares(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
if id == "" {
|
||||||
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
service.MyService.Shares().DeleteShare(id)
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
|
||||||
|
}
|
||||||
|
|
||||||
|
//client
|
||||||
|
|
||||||
|
func GetSambaConnectionsList(c *gin.Context) {
|
||||||
|
connections := service.MyService.Connections().GetConnectionsList()
|
||||||
|
connectionList := []model.Connections{}
|
||||||
|
for _, v := range connections {
|
||||||
|
connectionList = append(connectionList, model.Connections{
|
||||||
|
ID: v.ID,
|
||||||
|
Username: v.Username,
|
||||||
|
Port: v.Port,
|
||||||
|
Host: v.Host,
|
||||||
|
MountPoint: v.MountPoint,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connectionList})
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostSambaConnectionsCreate(c *gin.Context) {
|
||||||
|
connection := model.Connections{}
|
||||||
|
c.ShouldBindJSON(&connection)
|
||||||
|
if connection.Port == "" {
|
||||||
|
connection.Port = "445"
|
||||||
|
}
|
||||||
|
if connection.Username == "" || connection.Host == "" {
|
||||||
|
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("^[a-zA-Z0-9]{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("^[a-zA-Z0-9]{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
|
||||||
|
connections := service.MyService.Connections().GetConnectionByHost(connection.Host)
|
||||||
|
if len(connections) > 0 {
|
||||||
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.Record_ALREADY_EXIST, Message: common_err.GetMsg(common_err.Record_ALREADY_EXIST), Data: common_err.GetMsg(common_err.Record_ALREADY_EXIST)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
// check connect is ok
|
||||||
|
directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
connectionDBModel := model2.ConnectionsDBModel{}
|
||||||
|
connectionDBModel.Username = connection.Username
|
||||||
|
connectionDBModel.Password = connection.Password
|
||||||
|
connectionDBModel.Host = connection.Host
|
||||||
|
connectionDBModel.Port = connection.Port
|
||||||
|
connectionDBModel.Directories = strings.Join(directories, ",")
|
||||||
|
baseHostPath := "/mnt/" + connection.Host
|
||||||
|
connectionDBModel.MountPoint = baseHostPath
|
||||||
|
connection.MountPoint = baseHostPath
|
||||||
|
file.IsNotExistMkDir(baseHostPath)
|
||||||
|
for _, v := range directories {
|
||||||
|
mountPoint := baseHostPath + "/" + v
|
||||||
|
file.IsNotExistMkDir(mountPoint)
|
||||||
|
service.MyService.Connections().MountSmaba(connectionDBModel.Username, connectionDBModel.Host, v, connectionDBModel.Port, mountPoint, connectionDBModel.Password)
|
||||||
|
}
|
||||||
|
|
||||||
|
service.MyService.Connections().CreateConnection(&connectionDBModel)
|
||||||
|
|
||||||
|
connection.ID = connectionDBModel.ID
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connection})
|
||||||
|
}
|
||||||
|
|
||||||
|
func DeleteSambaConnections(c *gin.Context) {
|
||||||
|
id := c.Param("id")
|
||||||
|
connection := service.MyService.Connections().GetConnectionByID(id)
|
||||||
|
if connection.Username == "" {
|
||||||
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.Record_NOT_EXIST, Message: common_err.GetMsg(common_err.Record_NOT_EXIST)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
mountPointList := service.MyService.System().GetDirPath(connection.MountPoint)
|
||||||
|
for _, v := range mountPointList {
|
||||||
|
service.MyService.Connections().UnmountSmaba(v.Path)
|
||||||
|
}
|
||||||
|
os.RemoveAll(connection.MountPoint)
|
||||||
|
service.MyService.Connections().DeleteConnection(id)
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
|
||||||
|
}
|
||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user