Compare commits

...

110 Commits

Author SHA1 Message Date
Tiger Wang
50d68f3f76 update goreleaser configuration 2022-09-28 12:21:44 -04:00
Tiger Wang
d9c6a5c875 remove /DATA directory initialization - moved to local-storage (#578) 2022-09-28 11:14:19 -04:00
LinkLeong
4bace9b16a remove temp path 2022-09-28 16:13:42 +01:00
LinkLeong
84dfa7f5bf add share function to common 2022-09-19 10:09:04 +01:00
LinkLeong
582f85c3ba update http status 2022-09-16 04:47:42 +01:00
LinkLeong
7f4562629a remove disk and test common package 2022-09-15 08:13:07 +01:00
LinkLeong
4776b76b16 add system notiry 2022-09-13 07:22:24 +01:00
a624669980@163.com
9f938f65b1 Merge branch 'main' into v0.3.7 2022-09-09 12:02:19 +08:00
a624669980@163.com
314dbdab57 add shell script 2022-09-09 11:28:30 +08:00
LinkLeong
4ccae3f67f add shell script 2022-09-09 04:12:34 +01:00
LinkLeong
9f2e8dae6f add send notify function 2022-09-08 10:55:20 +01:00
John Guan
727aca564b Update CHANGELOG.md
Signed-off-by: John Guan <Guan.Ningchuan@gmail.com>
2022-09-06 20:40:14 +08:00
link
70ba4d5e3d 0.3.6 (#519)
* Add registration route

* add route registration

* remove ui

* 0.3.6 build scaffold (#473)

* wip

* wip

* wip

* Merge Branches

* Update helper.sh

* add goreleaser

* fix migration not working for LEGACY_WITHOUT_VERSION (#479)

* wip

* wip

* add error handling to migration script

* add migration tool

* Adjusting shell script location

* update disk user authentication method

* delayed port modification

* Update system.go

Co-authored-by: Tiger Wang (王豫) <tigerwang@outlook.com>
2022-09-06 14:28:49 +08:00
a624669980@163.com
8d088afcc5 update system version 2022-08-25 10:50:11 +08:00
link
34f35bbf20 0.3.5 (#470)
* initial completion of the sharing function

* Adjusting multi-partition disk mounts

* Add file sharing function

* update usb auto mount shell

* update samba config

* add umount disk function

* update change log

* update usb auto mount \

* update usb auto mount

* Update periodical.go

* Update periodical.go

* resolve alpha.1 issues

* Update UI

* update usb show name

* update web

* update image version
2022-08-22 18:22:12 +08:00
link
b6f413b9e9 0.3.5 (#464)
* initial completion of the sharing function

* Adjusting multi-partition disk mounts

* Add file sharing function

* update usb auto mount shell

* update samba config

* add umount disk function

* update change log

* update usb auto mount \

* update usb auto mount

* Update periodical.go

* Update periodical.go

* resolve alpha.1 issues

* Update UI
2022-08-18 11:18:27 +08:00
John Guan
091be6d12e Update push_events_to_discord.yml 2022-08-17 15:49:44 +08:00
John Guan
aefa68d8f8 Merge branch 'main' of https://github.com/IceWhaleTech/CasaOS 2022-08-16 14:23:28 +08:00
John Guan
9aed323d8d Update push_events_to_discord.yml 2022-08-16 14:23:25 +08:00
John Guan
eba607fc53 Revert "Update push_events_to_discord.yml"
This reverts commit d064f20a04.
2022-08-15 15:52:20 +08:00
John Guan
d064f20a04 Update push_events_to_discord.yml 2022-08-15 15:46:56 +08:00
link
079e431d33 0.3.5 (#452)
* initial completion of the sharing function

* Adjusting multi-partition disk mounts

* Add file sharing function

* update usb auto mount shell

* update samba config

* add umount disk function

* update change log

* update usb auto mount \

* update usb auto mount

* Update periodical.go

* Update periodical.go
2022-08-15 11:51:29 +08:00
link
cee34ec1c2 0.3.5 (#451)
* initial completion of the sharing function

* Adjusting multi-partition disk mounts

* Add file sharing function

* update usb auto mount shell

* update samba config

* add umount disk function

* update change log

* update usb auto mount \

* update usb auto mount

* Update periodical.go
2022-08-15 11:37:21 +08:00
John Guan
848ee63386 Update app_request.yaml 2022-08-12 11:40:37 +08:00
John Guan
c12c6cc940 Update app_request.yaml 2022-08-12 11:27:20 +08:00
John Guan
f31fb22039 Update alpha_bug_report.yaml 2022-08-12 11:27:17 +08:00
John Guan
a5133bdbfa Merge branch 'main' of https://github.com/IceWhaleTech/CasaOS 2022-08-10 14:44:32 +08:00
John Guan
1902b2d4f2 Update bug_report.md 2022-08-10 14:44:29 +08:00
John Guan
fc5e351f0b Update push_events_to_discord.yml 2022-08-10 11:18:14 +08:00
John Guan
7f642a7a4c Update push_events_to_discord.yml 2022-08-10 10:31:46 +08:00
John Guan
c36a046a15 Update and rename move_issues_to_projects.yml to add_issues_to_projects.yml 2022-08-08 17:31:38 +08:00
John Guan
8b2c9486da Update push_events_to_discord.yml 2022-08-08 17:30:30 +08:00
John Guan
ce5ecfcf84 Rename move_issue_to_project.yml to move_issues_to_projects.yml 2022-08-08 15:41:00 +08:00
John Guan
bd1a2f5751 Update move_issue_to_project.yml 2022-08-08 15:40:43 +08:00
John Guan
d2e0695d73 Create push_events_to_discord.yml 2022-08-08 15:40:05 +08:00
John Guan
8cd18c3218 Create move_issue_to_project.yml 2022-08-05 16:37:46 +08:00
John Guan
cc0ba82c92 Update config.yml 2022-08-05 15:58:43 +08:00
John Guan
ddca242d23 Update app_request.yaml 2022-08-05 15:49:42 +08:00
John Guan
eaa07ba95a Update app_request.yaml 2022-08-05 12:21:54 +08:00
John Guan
39a4c29680 Update app_request.yaml 2022-08-04 20:55:03 +08:00
John Guan
af6900b1c7 Create app_request.yaml 2022-08-04 20:53:30 +08:00
John Guan
9ec43a7691 Update config.yml 2022-08-04 17:37:19 +08:00
a624669980@163.com
bd85cda9fa update check version 2022-07-29 16:23:53 +08:00
a624669980@163.com
94eaba6ecb Update jwt_helper.go 2022-07-29 16:14:50 +08:00
a624669980@163.com
e207c9c75f Update CHANGELOG.md 2022-07-29 15:50:31 +08:00
a624669980@163.com
81d3293991 Update route.go 2022-07-29 15:47:43 +08:00
link
364fbf01f5 0.3.4 (#412)
* delete connect

* update user

* change branch

* API feedback (#341)

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* change branch

* update route

* change branch

* Update route.go

* 0.3.4 Function development completed

* Update system.go

* update ui

* Completed v0.3.4 and released alpha

* Update gin.go

* fix the problem of docker environment variables being displayed more than once

* update update shell

Co-authored-by: Tiger Wang (王豫) <tigerwang@outlook.com>
2022-07-27 18:37:22 +08:00
link
87e66aae8a 0.3.4 (#408)
* delete connect

* update user

* change branch

* API feedback (#341)

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* change branch

* update route

* change branch

* Update route.go

* 0.3.4 Function development completed

* Update system.go

* update ui

* Completed v0.3.4 and released alpha

* Update gin.go

* fix the problem of docker environment variables being displayed more than once

Co-authored-by: Tiger Wang (王豫) <tigerwang@outlook.com>
2022-07-26 11:03:45 +08:00
a624669980@163.com
3a60db3729 solve the first time app store opening failure problem 2022-07-22 15:24:13 +08:00
a624669980@163.com
d3f78b52fa Delete alpha.md 2022-07-22 11:27:05 +08:00
a624669980@163.com
7d67a66d6b update change log 2022-07-22 11:19:25 +08:00
a624669980@163.com
cb9e1b9dd9 Merge branch 'main' of ssh://github.com/IceWhaleTech/CasaOS 2022-07-22 11:18:05 +08:00
a624669980@163.com
dc8282acbb update chage log 2022-07-22 11:17:33 +08:00
link
cf6103a2b5 0.3.4 (#386)
* delete connect

* update user

* change branch

* API feedback (#341)

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* change branch

* update route

* change branch

* Update route.go

* 0.3.4 Function development completed

* Update system.go

* update ui

* Completed v0.3.4 and released alpha

* Update gin.go

Co-authored-by: Tiger Wang (王豫) <tigerwang@outlook.com>
2022-07-22 11:09:05 +08:00
link
6f98995e7d 0.3.4 (#385)
* delete connect

* update user

* change branch

* API feedback (#341)

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* wip

* change branch

* update route

* change branch

* Update route.go

* 0.3.4 Function development completed

* Update system.go

* update ui

* Completed v0.3.4 and released alpha

Co-authored-by: Tiger Wang (王豫) <tigerwang@outlook.com>
2022-07-22 11:02:11 +08:00
link
5cc41fa040 Update demo.yml 2022-07-21 19:17:46 +08:00
John Guan
cb289f5b8a Update move_alpha_bug_to_project.yml 2022-07-21 00:07:19 +08:00
John Guan
1377d55407 Create move_alpha_bug_to_project.yml 2022-07-21 00:06:03 +08:00
John Guan
06eca38022 Update alpha_bug_report.yaml 2022-07-20 19:14:33 +08:00
John Guan
c47c1e548c Update alpha_bug_report.yaml 2022-07-20 19:12:57 +08:00
John Guan
552ec4849d Update alpha_bug_report.yaml 2022-07-20 19:11:10 +08:00
John Guan
7386a9dce3 Update alpha_bug_report.yaml 2022-07-20 19:07:50 +08:00
John Guan
b2b1daf5ab Update alpha_bug_report.yaml 2022-07-20 19:06:56 +08:00
John Guan
bbc0181e23 Create alpha_bug_report.yaml 2022-07-20 19:04:47 +08:00
allcontributors[bot]
c23bd3f3a3 docs: add llwaini as a contributor for projectManagement, test, tutorial (#379)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-19 18:10:25 +08:00
allcontributors[bot]
8a1839c02e docs: add Protektor-Desura as a contributor for bug, ideas, question (#378)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-19 12:09:20 +08:00
allcontributors[bot]
164bf66190 docs: add bearfrieze as a contributor for ideas (#377)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-19 12:03:18 +08:00
allcontributors[bot]
a4c2a4b992 docs: add sio as a contributor for ideas (#376)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-19 12:01:47 +08:00
allcontributors[bot]
e7e82e6ca3 docs: add Joooost as a contributor for ideas (#375)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-19 12:00:06 +08:00
allcontributors[bot]
574295470e docs: add DrMxrcy as a contributor for test, ideas, question (#374)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-19 11:58:08 +08:00
allcontributors[bot]
b1061f19ad docs: add baptiste313 as a contributor for translation (#372)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-19 00:03:57 +08:00
John Guan
bdd9eaca9f Update .all-contributorsrc 2022-07-19 00:01:26 +08:00
allcontributors[bot]
ec4c672924 docs: add AuthorShin as a contributor for test, bug, question, test, ideas (#371)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-18 23:58:25 +08:00
allcontributors[bot]
5d4717de4d docs: add zarevskaya as a contributor for mentoring, question, tutorial, translation (#370)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-18 23:49:58 +08:00
allcontributors[bot]
e2de783152 docs: add dtaivpp as a contributor for doc, ideas, question (#369)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-18 23:22:09 +08:00
allcontributors[bot]
09f68f4034 docs: add JohnGuan as a contributor for bug, blog, content, doc, ideas, eventOrganizing, mentoring, question, translation, review, video (#368)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-18 23:19:31 +08:00
allcontributors[bot]
cec83fc048 docs: add Lauren-ED209 as a contributor for ideas, fundingFinding, projectManagement, question, test (#367)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-18 23:15:26 +08:00
allcontributors[bot]
33e1d8a806 docs: add tigerinus as a contributor for code, doc, ideas, infra, maintenance, mentoring, security, question, review (#366)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-18 23:13:01 +08:00
allcontributors[bot]
2a8dafae28 docs: add LinkLeong as a contributor for code, doc, ideas, infra, maintenance, question, review (#365)
* docs: update README.md [skip ci]

* docs: update .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-18 23:09:06 +08:00
John Guan
a426b56306 Update README.md 2022-07-18 23:04:47 +08:00
John Guan
6202d38bdb Update .all-contributorsrc 2022-07-18 23:04:46 +08:00
allcontributors[bot]
4626ceb048 docs: add jerrykuku as a contributor for code, doc, ideas, infra, maintenance, platform, question, review (#364)
* docs: update README.md [skip ci]

* docs: create .all-contributorsrc [skip ci]

Co-authored-by: allcontributors[bot] <46447321+allcontributors[bot]@users.noreply.github.com>
2022-07-18 22:39:00 +08:00
John Guan
1e7333118c Revert "Create .all-contributorsrc"
This reverts commit 9758436a1e.
2022-07-18 22:29:59 +08:00
John Guan
9758436a1e Create .all-contributorsrc 2022-07-18 22:25:49 +08:00
John Guan
ed67e977b7 Update README.md 2022-07-18 22:02:00 +08:00
John Guan
b0b1b5e262 Update README.md 2022-07-18 18:56:21 +08:00
John Guan
2796c37bf6 Update README.md 2022-07-18 18:52:54 +08:00
John Guan
d48e24f652 Create snapshot-dark.jpg 2022-07-18 18:52:50 +08:00
John Guan
3a8cf593d9 Create snapshot-light.jpg 2022-07-18 18:52:48 +08:00
a624669980@163.com
0ffa2f901a update readme 2022-07-08 14:12:23 +08:00
a624669980@163.com
bd73141ddf Fix file cut failure 2022-07-04 18:07:06 +08:00
a624669980@163.com
346b0f5d97 Update .gitignore 2022-07-01 15:54:02 +08:00
a624669980@163.com
d4b4b75012 delete conf.con 2022-07-01 15:53:04 +08:00
a624669980@163.com
cb33ffbb46 Update alpha.md 2022-07-01 15:51:33 +08:00
a624669980@163.com
85188d0b05 Merge branch 'main' of ssh://github.com/IceWhaleTech/CasaOS 2022-07-01 15:51:08 +08:00
a624669980@163.com
1e60c26920 Update .gitignore 2022-07-01 15:50:33 +08:00
link
752134942a V0.3.3 (#334)
* switch branches

* update user interface

* switch branch

* switch branch

* change branch

* submit 0.3.3

* Update UI

* update version function

* Update UI

* Update user.go

* update disk

* update person info interface

* Update main.go

* Update UI

* update alpha

* updata ui

* Update assist.sh

* Update assist.sh

* update update function

* add upload sh

* Update init.go

* upload shell script

* Update system.go

* update update.sh

* Update init.go

* update update.sh

* update update.sh

* Update update.sh

* Update system.go

* Update system.go

* update UI

* Update CHANGELOG.md
2022-07-01 15:19:16 +08:00
link
faf683a02c V0.3.3 (#331)
* switch branches

* update user interface

* switch branch

* switch branch

* change branch

* submit 0.3.3

* Update UI
2022-06-29 11:22:12 +08:00
link
f99f49dd7e V0.3.3 (#330)
* switch branches

* update user interface

* switch branch

* switch branch

* change branch

* submit 0.3.3
2022-06-29 11:09:58 +08:00
David Tippett
b0dc30277b Adding simple Developing file (#311)
* Adding developing guide with env setup

Signed-off-by: David Tippett <dtaivpp@gmail.com>

* Fixing formatting on developing guide

Signed-off-by: David Tippett <dtaivpp@gmail.com>

* Switching nav to bulleted list

Signed-off-by: David Tippett <dtaivpp@gmail.com>

* Forgot a word o_o

Signed-off-by: David Tippett <dtaivpp@gmail.com>
2022-06-21 08:57:55 +08:00
a624669980@163.com
d91fef0a19 Update route.go 2022-06-16 21:20:10 +08:00
a624669980@163.com
6bb044ab04 Update version.go 2022-06-16 20:11:11 +08:00
a624669980@163.com
78479f9604 Update file.go 2022-06-16 16:57:13 +08:00
a624669980@163.com
8fe893847f Update CHANGELOG.md 2022-06-16 15:52:50 +08:00
link
f506d6ce49 Dev (#298)
* fix bug

* updata UI

* 0.3.2

### Added

- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))

### Changed

- [Apps] Hide the display of non-essential environment variables in the application.
- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
### Fixed

- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))

* Modify log help class

* Fix some bugs in 0.3.2

* Solve the operation file queue problem

* Exclude web folders

* update UI

* add cancel file operate

* Update UI

* Merge sockets to transfer data

* Conflict Resolution

* Update send data interval

* Update UI

* fixed bug

- Fix the problem of application opening failure on non-80 ports
- Modify port failure problem
- Modify environment variables disappearing problem

* update version function

* Fix version update issues

* fixed bug

- [System] Fixed the issue of widgets displaying wrongly on mobile devices.
- [App] Fix the problem of application opening failure on non-80 ports ([#283](https://github.com/IceWhaleTech/CasaOS/issues/283) [#280](https://github.com/IceWhaleTech/CasaOS/issues/280))
- [System] Modify port failure problem ([#282](https://github.com/IceWhaleTech/CasaOS/issues/282))
- [App]Modify environment variables disappearing problem([#284](https://github.com/IceWhaleTech/CasaOS/issues/284))
- [System]Fix no update alert([#278](https://github.com/IceWhaleTech/CasaOS/issues/278))
- [System] Fixed some bugs of application cpu usage and memory staging([#272]https://github.com/IceWhaleTech/CasaOS/issues/272)

* update UI

* Update CHANGELOG.md

* update app service

* update ui

* Fix application installation host mode error

* update ui

* Update UI
2022-06-15 19:01:26 +08:00
link
5d7c5ba120 Dev (#296)
* fix bug

* updata UI

* 0.3.2

### Added

- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))

### Changed

- [Apps] Hide the display of non-essential environment variables in the application.
- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
### Fixed

- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))

* Modify log help class

* Fix some bugs in 0.3.2

* Solve the operation file queue problem

* Exclude web folders

* update UI

* add cancel file operate

* Update UI

* Merge sockets to transfer data

* Conflict Resolution

* Update send data interval

* Update UI

* fixed bug

- Fix the problem of application opening failure on non-80 ports
- Modify port failure problem
- Modify environment variables disappearing problem

* update version function

* Fix version update issues

* fixed bug

- [System] Fixed the issue of widgets displaying wrongly on mobile devices.
- [App] Fix the problem of application opening failure on non-80 ports ([#283](https://github.com/IceWhaleTech/CasaOS/issues/283) [#280](https://github.com/IceWhaleTech/CasaOS/issues/280))
- [System] Modify port failure problem ([#282](https://github.com/IceWhaleTech/CasaOS/issues/282))
- [App]Modify environment variables disappearing problem([#284](https://github.com/IceWhaleTech/CasaOS/issues/284))
- [System]Fix no update alert([#278](https://github.com/IceWhaleTech/CasaOS/issues/278))
- [System] Fixed some bugs of application cpu usage and memory staging([#272]https://github.com/IceWhaleTech/CasaOS/issues/272)

* update UI

* Update CHANGELOG.md

* update app service

* update ui
2022-06-15 10:22:27 +08:00
link
eedffd7c19 Dev (#292)
* fix bug

* updata UI

* 0.3.2

### Added

- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))

### Changed

- [Apps] Hide the display of non-essential environment variables in the application.
- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
### Fixed

- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))

* Modify log help class

* Fix some bugs in 0.3.2

* Solve the operation file queue problem

* Exclude web folders

* update UI

* add cancel file operate

* Update UI

* Merge sockets to transfer data

* Conflict Resolution

* Update send data interval

* Update UI

* fixed bug

- Fix the problem of application opening failure on non-80 ports
- Modify port failure problem
- Modify environment variables disappearing problem

* update version function

* Fix version update issues

* fixed bug

- [System] Fixed the issue of widgets displaying wrongly on mobile devices.
- [App] Fix the problem of application opening failure on non-80 ports ([#283](https://github.com/IceWhaleTech/CasaOS/issues/283) [#280](https://github.com/IceWhaleTech/CasaOS/issues/280))
- [System] Modify port failure problem ([#282](https://github.com/IceWhaleTech/CasaOS/issues/282))
- [App]Modify environment variables disappearing problem([#284](https://github.com/IceWhaleTech/CasaOS/issues/284))
- [System]Fix no update alert([#278](https://github.com/IceWhaleTech/CasaOS/issues/278))
- [System] Fixed some bugs of application cpu usage and memory staging([#272]https://github.com/IceWhaleTech/CasaOS/issues/272)

* update UI

* Update CHANGELOG.md
2022-06-14 18:22:02 +08:00
link
0885c1386d Dev (#291)
* fix bug

* updata UI

* 0.3.2

### Added

- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))

### Changed

- [Apps] Hide the display of non-essential environment variables in the application.
- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
### Fixed

- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))

* Modify log help class

* Fix some bugs in 0.3.2

* Solve the operation file queue problem

* Exclude web folders

* update UI

* add cancel file operate

* Update UI

* Merge sockets to transfer data

* Conflict Resolution

* Update send data interval

* Update UI

* fixed bug

- Fix the problem of application opening failure on non-80 ports
- Modify port failure problem
- Modify environment variables disappearing problem

* update version function

* Fix version update issues

* fixed bug

- [System] Fixed the issue of widgets displaying wrongly on mobile devices.
- [App] Fix the problem of application opening failure on non-80 ports ([#283](https://github.com/IceWhaleTech/CasaOS/issues/283) [#280](https://github.com/IceWhaleTech/CasaOS/issues/280))
- [System] Modify port failure problem ([#282](https://github.com/IceWhaleTech/CasaOS/issues/282))
- [App]Modify environment variables disappearing problem([#284](https://github.com/IceWhaleTech/CasaOS/issues/284))
- [System]Fix no update alert([#278](https://github.com/IceWhaleTech/CasaOS/issues/278))
- [System] Fixed some bugs of application cpu usage and memory staging([#272]https://github.com/IceWhaleTech/CasaOS/issues/272)

* update UI
2022-06-14 18:11:15 +08:00
link
0297fe67af Dev (#290)
* fix bug

* updata UI

* 0.3.2

### Added

- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))

### Changed

- [Apps] Hide the display of non-essential environment variables in the application.
- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
### Fixed

- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))

* Modify log help class

* Fix some bugs in 0.3.2

* Solve the operation file queue problem

* Exclude web folders

* update UI

* add cancel file operate

* Update UI

* Merge sockets to transfer data

* Conflict Resolution

* Update send data interval

* Update UI

* fixed bug

- Fix the problem of application opening failure on non-80 ports
- Modify port failure problem
- Modify environment variables disappearing problem

* update version function

* Fix version update issues

* fixed bug

- [System] Fixed the issue of widgets displaying wrongly on mobile devices.
- [App] Fix the problem of application opening failure on non-80 ports ([#283](https://github.com/IceWhaleTech/CasaOS/issues/283) [#280](https://github.com/IceWhaleTech/CasaOS/issues/280))
- [System] Modify port failure problem ([#282](https://github.com/IceWhaleTech/CasaOS/issues/282))
- [App]Modify environment variables disappearing problem([#284](https://github.com/IceWhaleTech/CasaOS/issues/284))
- [System]Fix no update alert([#278](https://github.com/IceWhaleTech/CasaOS/issues/278))
- [System] Fixed some bugs of application cpu usage and memory staging([#272]https://github.com/IceWhaleTech/CasaOS/issues/272)

* update UI
2022-06-14 18:10:22 +08:00
link
3f53e6f33b Dev (#288)
* fix bug

* updata UI

* 0.3.2

### Added

- [Files] Files can now be selected multiple files and downloaded, deleted, moved, etc.
- [Apps] Support to modify the application opening address.([#204](https://github.com/IceWhaleTech/CasaOS/issues/204))

### Changed

- [Apps] Hide the display of non-essential environment variables in the application.
- [System] Network, disk, cpu, memory, etc. information is modified to be pushed via socket.
- [System] Optimize opening speed.([#214](https://github.com/IceWhaleTech/CasaOS/issues/214))
### Fixed

- [System] Fixed the problem that sync data cannot submit the device ID ([#68](https://github.com/IceWhaleTech/CasaOS/issues/68))
- [Files] Fixed the code editor center alignment display problem.([#210](https://github.com/IceWhaleTech/CasaOS/issues/210))
- [Files] Fixed the problem of wrong name when downloading files.([#240](https://github.com/IceWhaleTech/CasaOS/issues/240))
- [System] Fixed the network display as a negative number problem.([#224](https://github.com/IceWhaleTech/CasaOS/issues/224))

* Modify log help class

* Fix some bugs in 0.3.2

* Solve the operation file queue problem

* Exclude web folders

* update UI

* add cancel file operate

* Update UI

* Merge sockets to transfer data

* Conflict Resolution

* Update send data interval

* Update UI

* fixed bug

- Fix the problem of application opening failure on non-80 ports
- Modify port failure problem
- Modify environment variables disappearing problem

* update version function

* Fix version update issues
2022-06-14 13:24:53 +08:00
238 changed files with 5417 additions and 16377 deletions

197
.all-contributorsrc Normal file
View 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
}

View 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.yaml vendored Normal file
View 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.

View File

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

View File

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

View 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

View File

@@ -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": "0.3.3-demo-1658402149' | 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

View 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

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

47
.github/workflows/release.yml vendored Normal file
View File

@@ -0,0 +1,47 @@
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: 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 }}

8
.gitignore vendored
View File

@@ -28,10 +28,12 @@ gen
/sql/ /sql/
/out/ /out/
/db/ /db/
/docs/
/web/
/conf/conf.ini /conf/conf.ini
/conf/conf.conf
/conf/conf.json
__debug_bin __debug_bin
main main
CasaOS
github.com github.com
.all-contributorsrc
dist
CasaOS

167
.goreleaser.yaml Normal file
View 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:
- CGO_ENABLED=1
- CC=x86_64-linux-gnu-gcc
ldflags:
- -s
- -w
- -extldflags "-static"
tags:
- musl
- netgo
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:
- CGO_ENABLED=1
- CC=aarch64-linux-gnu-gcc
ldflags:
- -s
- -w
- -extldflags "-static"
tags:
- musl
- netgo
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:
- CGO_ENABLED=1
- CC=arm-linux-gnueabihf-gcc
ldflags:
- -s
- -w
- -extldflags "-static"
tags:
- musl
- netgo
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:
- CGO_ENABLED=1
- CC=x86_64-linux-gnu-gcc
ldflags:
- -s
- -w
- -extldflags "-static"
tags:
- musl
- netgo
goos:
- linux
goarch:
- amd64
- id: casaos-migration-tool-arm64
binary: build/sysroot/usr/bin/casaos-migration-tool
main: ./cmd/migration-tool
env:
- CGO_ENABLED=1
- CC=aarch64-linux-gnu-gcc
ldflags:
- -s
- -w
- -extldflags "-static"
tags:
- musl
- netgo
goos:
- linux
goarch:
- arm64
- id: casaos-migration-tool-arm-7
binary: build/sysroot/usr/bin/casaos-migration-tool
main: ./cmd/migration-tool
env:
- CGO_ENABLED=1
- CC=arm-linux-gnueabihf-gcc
ldflags:
- -s
- -w
- -extldflags "-static"
tags:
- musl
- netgo
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 }}"

View File

@@ -18,13 +18,107 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Fixed ### Fixed
## [0.3.2.1] - 2022-06-13
## [0.3.6-alpha.1] - 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 ### Fixed
- Fix the problem of application opening failure on non-80 ports ([#283](https://github.com/IceWhaleTech/CasaOS/issues/283) [#280](https://github.com/IceWhaleTech/CasaOS/issues/280)) - [App] fixed uninstalling imported docker container apps results in wiping ALL your config data from them ([#360](https://github.com/IceWhaleTech/CasaOS/issues/360))
- Modify port failure problem ([#282](https://github.com/IceWhaleTech/CasaOS/issues/282))
- Modify environment variables disappearing problem([#284](https://github.com/IceWhaleTech/CasaOS/issues/284)) ## [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
- [System]Add interface call log
- Adding Developing file ([#311](https://github.com/IceWhaleTech/CasaOS/pull/311))
- [App] add new tips for app section.
- [System] UI Configurable function modules: support turning off the search bar and recommended apps module in the settings.
- [System] Custom wallpapers: two new preset wallpapers, support for custom uploads, support for setting images from Files as wallpapers, Also support right click on dashboard to change wallpaper.
### Changed
- [App] Cache app store index and category data
- [System] casaos master program adapted to FHS standards
- [App] Update casaos icons.
- [System] Update translation.
### Removed
- [System] Remove upnp function module
- [System] Remove ddns function module
- [System] Remove search function module
- [System] Remove zerotier function module
- [System] Remove task function module
- [System] Remove file share function module
### Fixed
- [Disk] Fixed hard drive won't hibernate problem ([#202](https://github.com/IceWhaleTech/CasaOS/issues/202))
- [File] Fixed the backspace key that causes the folder to rewind ([#252](https://github.com/IceWhaleTech/CasaOS/issues/252))
- [App] Fixed app logo is not loading when imported. ([#320](https://github.com/IceWhaleTech/CasaOS/issues/320))
## [0.3.2.1] - 2022-06-16(UTC)
### Changed
- [System] Adjusted the display style.
### Fixed
- [System] Fixed the issue of widgets displaying wrongly on mobile devices.
- [App] Fix the problem of application opening failure on non-80 ports ([#283](https://github.com/IceWhaleTech/CasaOS/issues/283) [#280](https://github.com/IceWhaleTech/CasaOS/issues/280))
- [System] Modify port failure problem ([#282](https://github.com/IceWhaleTech/CasaOS/issues/282))
- [App]Modify environment variables disappearing problem([#284](https://github.com/IceWhaleTech/CasaOS/issues/284))
- [System]Fix no update alert([#278](https://github.com/IceWhaleTech/CasaOS/issues/278))
- [System] Fixed some bugs of application cpu usage and memory staging([#272](https://github.com/IceWhaleTech/CasaOS/issues/272))
- [App] Fixed plex and HA network mode error issues ([#299](https://github.com/IceWhaleTech/CasaOS/issues/299))
- [App] Fix application terminal not working ([#266](https://github.com/IceWhaleTech/CasaOS/issues/266))
## [0.3.2] - 2022-06-10 ## [0.3.2] - 2022-06-10
### Added ### Added

33
DEVELOPING.md Normal file
View File

@@ -0,0 +1,33 @@
# CasaOS Development
Here we will describe the steps required to setup a development environment with CasaOS.
- [Setting up development environment](#setting-up-development-environment)
- [Pre-requisites](#pre-requisites)
- [1. Fork the Repo](#1.-fork-the-repo)
- [2. Clone the repo down](#2.-clone-the-repo-down)
- [3. Install dependencies](#3.-install-dependencies)
## Setting up a development environment
In this section we will walk you through the general process of setting up your development environment to get started.
### Pre-requisites
The following must be installed in order to get started. The details of how to install them is outside the scope of this doc, but generally they should be able to be installed with your systems package manager (apt, yum, brew, choco, etc).
- Go > v1.17.0
- yarn
- node.js
### 1. Fork the Repo
[Fork the repo](https://docs.github.com/en/get-started/quickstart/fork-a-repo) onto your own GitHub account for developing.
### 2. Clone the repo down
1. Navigate into your go workspace (check with `go env GOPATH`).
2. Navigate to the appropriate path for github. It should look something like this: `<path from GOPATH>/github.com/<GitHub Username>/`. If it doesn't exist create it.
3. Clone down the repo with the following: `git clone --recurse-submodules --remote-submodules https://github.com/<your GitHub Username>/CasaOS.git`
### 3. Install dependencies
1. `cd UI`
2. `yarn install`
3. `yarn build`
4. `cd ..`
5. `go get`

261
README.md
View File

@@ -1,72 +1,150 @@
# CasaOS - A simple, easy-to-use, elegant open-source Home Cloud system. # CasaOS - Your Home Cloud OS
![CasaOS](https://raw.githubusercontent.com/IceWhaleTech/logo/main/casaos/casaos_banner_aldeyjarfoss.png)
[![Version](https://img.shields.io/github/v/release/IceWhaleTech/CasaOS?color=162453&label=CasaOS&style=flat-square)](https://github.com/IceWhaleTech/CasaOS) <!-- Readme i18n links -->
[![Pull Requests](https://img.shields.io/github/issues-pr/IceWhaleTech/CasaOS?color=162453&style=flat-square)](https://github.com/IceWhaleTech/CasaOS/pulls) <!-- > English | [中文](#) | [Français](#) -->
[![Issues](https://img.shields.io/github/issues/IceWhaleTech/CasaOS?color=162453&style=flat-square)](https://github.com/IceWhaleTech/CasaOS/issues)
[![GitHub Stars](https://img.shields.io/github/stars/IceWhaleTech/CasaOS?color=162453&logo=github&style=flat-square)](https://github.com/IceWhaleTech/CasaOS/stargazers)
[![Discord](https://img.shields.io/discord/884667213326463016?color=162453&label=Chat&logo=discord&logoColor=fff&style=flat-square)](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?
![CasaOS Snapshot](snapshot.png) Think about it seriously. Is control of our data, smart devices and digital assets now only in the hands of some big company?
![CasaOS Snapshot Mobile](snapshot-mobile.png)
- 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)
### 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 | bash
``` ```
or or
```sh ```sh
curl -fsSL https://get.icewhale.io/casaos.sh | bash curl -fsSL https://get.casaos.io | bash
``` ```
### Uninstall CasaOS ### Uninstall CasaOS
v0.3.3 or newer
```sh
casaos-uninstall
```
Before v0.3.3
```sh ```sh
curl -fsSL https://get.icewhale.io/casaos-uninstall.sh | bash curl -fsSL https://get.icewhale.io/casaos-uninstall.sh | bash
``` ```
### System Compatibility ## Community
- Ubuntu Server 20.04 amd64 (✅ Recommend, Tested)
- Armbian 22.02 armhf/arm64/amd64 (✅ Recommend, Tested)
- 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)
## 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 +152,97 @@ 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)!**
[![Discord Card](https://discordapp.com/api/guilds/884667213326463016/widget.png?style=banner2)](https://discord.gg/knqAbbBbeX) [![Discord Card](https://discordapp.com/api/guilds/884667213326463016/widget.png?style=banner2)](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 <details>
- Jerry Liu <summary><b>How can I get involved? 🧐</b></summary>
- Link Liang <p>
- Ober Zhang
- Zyaire Ann ### Coding 💻 (WIP)
- John Guan
- Right here, waiting for YOU! We are refining documentation that can be used for effective community collaboration. Feel free to start a discussion if you have a good idea.
### Helping Users 💬
If you have extensive knowledge of CasaOS and related areas. We highly encourage you to help others as much as you can in Discord and Discussions.
Discord: [https://discord.gg/knqAbbBbeX](https://discord.gg/knqAbbBbeX)
GitHub Discussions: [https://github.com/IceWhaleTech/CasaOS/discussions](https://github.com/IceWhaleTech/CasaOS/discussions)
### Helping with Translations 🌍 (WIP)
CasaOS officially supports English and Chinese. You are welcome to help make CasaOS available in more languages.
### Performing Alpha Testing ⚠️
Alpha testing is quality assurance testing that is engaged and driven by the community. It's a great way to get involved in contributing and experiencing the latest features before a new release.
The documentation is being refined and you can contact @JohnGuan via [Discord](https://discord.gg/knqAbbBbeX). Ask to join the #casaos-alpha channel.
### Writing Documentation 📖 (WIP)
Help make our documentation better by writing new content for the CasaOS Wiki, correcting existing material, or translating content into new languages.
</p>
</details>
## Credits
Many thanks to everyone who has helped CasaOS so far!
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

Submodule UI deleted from 62a6bd44d5

View File

@@ -0,0 +1,181 @@
#!/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"
APP_NAME_FORMAL="CasaOS"
#APP_NAME_FORMAL="casaos-alpha"
# 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
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 v0.3.6-alpha2"
#
# - "v0.3.5" is the current version installed on this host
# - "v0.3.6-alpha2" is the version of the migration tool from GitHub
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 "v0.3.6-alpha2" from "v0.3.5 v0.3.6-alpha2"
VER2=$(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+=("${VER2// /}")
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
ARCH="unknown"
case $(uname -m) in
x86_64)
ARCH="amd64"
;;
aarch64)
ARCH="arm64"
;;
armv7l)
ARCH="arm-7"
;;
*)
__error "Unsupported architecture"
;;
esac
pushd "${MIGRATION_SERVICE_DIR}"
{ for VER2 in "${MIGRATION_PATH[@]}"; do
MIGRATION_TOOL_FILE=linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz
if [ -f "${MIGRATION_TOOL_FILE}" ]; then
__info "Migration tool ${MIGRATION_TOOL_FILE} exists. Skip downloading."
continue
fi
# MIGRATION_TOOL_URL=http://192.168.2.197:8000/v1/package/migration?type=release&name="${APP_NAME_FORMAL}"&version=${VER2}&arch=${ARCH}
MIGRATION_TOOL_URL=https://github.com/IceWhaleTech/"${APP_NAME_FORMAL}"/releases/download/"${VER2}"/linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz
echo "Dowloading ${MIGRATION_TOOL_URL}..."
curl -sL -O "${MIGRATION_TOOL_URL}"
done
} || {
popd
__error "Failed to download migration tools"
}
{
for VER2 in "${MIGRATION_PATH[@]}"; do
MIGRATION_TOOL_FILE=linux-"${ARCH}"-"${APP_NAME}"-migration-tool-"${VER2}".tar.gz
__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

View File

@@ -0,0 +1,4 @@
LEGACY_WITHOUT_VERSION v0.3.6
v0.3.5 v0.3.6
v0.3.5.1 v0.3.6
v0.3.6 v0.3.7

View 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}..."
$SHELL "${SETUP_SCRIPT_FILEPATH}" "${BUILD_PATH}"
} || {
echo "🟥 ${SETUP_SCRIPT_FILENAME} failed."
exit 1
}
echo "${SETUP_SCRIPT_FILENAME} finished."

View File

@@ -0,0 +1 @@
../setup-casaos.sh

View File

@@ -0,0 +1,45 @@
#!/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
if systemctl is-active "${APP_NAME}.service" &>/dev/null ;then
echo "server started"
else
# enable and start service
systemctl daemon-reload
echo "Enabling service..."
systemctl enable --force --no-ask-password "${APP_NAME}.service"
echo "Starting service..."
systemctl start --force --no-ask-password "${APP_NAME}.service"
fi

View File

@@ -0,0 +1 @@
../setup-casaos.sh

View File

@@ -0,0 +1 @@
../debian/setup-casaos.sh

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

View File

@@ -0,0 +1,12 @@
[Unit]
After=casaos-gateway.service
ConditionFileNotEmpty=/etc/casaos/casaos.conf
Description=CasaOS Service
[Service]
ExecStart=/usr/bin/casaos -c /etc/casaos/casaos.conf
PIDFile=/var/run/casaos/casaos.pid
Restart=always
[Install]
WantedBy=multi-user.target

View File

@@ -0,0 +1,3 @@
#!/bin/bash

View File

@@ -0,0 +1,105 @@
#!/bin/bash
###
# @Author: LinkLeong link@icewhale.com
# @Date: 2022-06-30 10:08:33
# @LastEditors: LinkLeong
# @LastEditTime: 2022-07-01 11:17:54
# @FilePath: /CasaOS/shell/delete-old-service.sh
# @Description:
###
((EUID)) && sudo_cmd="sudo"
# SYSTEM INFO
readonly UNAME_M="$(uname -m)"
# CasaOS PATHS
readonly CASA_REPO=IceWhaleTech/CasaOS
readonly CASA_UNZIP_TEMP_FOLDER=/tmp/casaos
readonly CASA_BIN=casaos
readonly CASA_BIN_PATH=/usr/bin/casaos
readonly CASA_CONF_PATH=/etc/casaos.conf
readonly CASA_SERVICE_PATH=/etc/systemd/system/casaos.service
readonly CASA_HELPER_PATH=/usr/share/casaos/shell/
readonly CASA_USER_CONF_PATH=/var/lib/casaos/conf/
readonly CASA_DB_PATH=/var/lib/casaos/db/
readonly CASA_TEMP_PATH=/var/lib/casaos/temp/
readonly CASA_LOGS_PATH=/var/log/casaos/
readonly CASA_PACKAGE_EXT=".tar.gz"
readonly CASA_RELEASE_API="https://api.github.com/repos/${CASA_REPO}/releases"
readonly CASA_OPENWRT_DOCS="https://github.com/IceWhaleTech/CasaOS-OpenWrt"
readonly COLOUR_RESET='\e[0m'
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
)
Target_Arch=""
Target_Distro="debian"
Target_OS="linux"
Casa_Tag=""
#######################################
# Custom printing function
# Globals:
# None
# Arguments:
# $1 0:OK 1:FAILED 2:INFO 3:NOTICE
# message
# Returns:
# None
#######################################
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"
}
# 0 Check_exist
Check_Exist() {
#Create Dir
Show 2 "Create Folders."
${sudo_cmd} mkdir -p ${CASA_HELPER_PATH}
${sudo_cmd} mkdir -p ${CASA_LOGS_PATH}
${sudo_cmd} mkdir -p ${CASA_USER_CONF_PATH}
${sudo_cmd} mkdir -p ${CASA_DB_PATH}
${sudo_cmd} mkdir -p ${CASA_TEMP_PATH}
Show 2 "Start cleaning up the old version."
${sudo_cmd} rm -rf /usr/lib/systemd/system/casaos.service
${sudo_cmd} rm -rf /lib/systemd/system/casaos.service
${sudo_cmd} rm -rf /usr/local/bin/${CASA_BIN}
#Clean
if [[ -d "/casaOS" ]]; then
${sudo_cmd} rm -rf /casaOS
fi
Show 0 "Clearance completed."
$sudo_cmd systemctl restart ${CASA_BIN}
}
Check_Exist

View File

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

View 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/LinkLeong/casaos-alpha/main/new.update.sh | bash

37
cmd/migration-tool/log.go Normal file
View 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...)
}

122
cmd/migration-tool/main.go Normal file
View File

@@ -0,0 +1,122 @@
/*
* @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{
NewMigrationToolFor_035(),
NewMigrationToolFor_036(),
}
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)
}
selectedMigrationTool.PostMigrate()
_logger.Info("casaos migration ok")
// panic(err)
}

View File

@@ -0,0 +1,182 @@
/*
* @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 (
"io"
"io/ioutil"
"os"
"path"
"strings"
interfaces "github.com/IceWhaleTech/CasaOS-Common"
"github.com/IceWhaleTech/CasaOS-Common/utils/version"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/service"
)
type migrationTool036 struct{}
func (u *migrationTool036) 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 *migrationTool036) PreMigrate() error {
return nil
}
func (u *migrationTool036) Migrate() error {
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")
}
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)
}
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 ;")
}
service.MyService.App().ImportApplications(true)
src := "/casaOS/server/conf/conf.ini"
if file.Exists(src) {
dst := "/etc/casaos/casaos.conf"
source, err := os.Open(src)
if err != nil {
return err
}
defer source.Close()
destination, err := os.Create(dst)
if err != nil {
return err
}
defer destination.Close()
_, err = io.Copy(destination, source)
if err != nil {
return err
}
}
if file.Exists("/casaOS/server/db") {
var fds []os.FileInfo
var err error
to := "/var/lib/casaos/db"
file.IsNotExistMkDir(to)
from := "/casaOS/server/db"
if fds, err = ioutil.ReadDir(from); err != nil {
return err
}
for _, fd := range fds {
srcfp := path.Join(from, fd.Name())
dstfp := path.Join(to, fd.Name())
source, err := os.Open(srcfp)
if err != nil {
return err
}
defer source.Close()
destination, err := os.Create(dstfp)
if err != nil {
return err
}
defer destination.Close()
_, err = io.Copy(destination, source)
if err != nil {
return err
}
}
}
if file.Exists("/casaOS/server/conf") {
var fds []os.FileInfo
var err error
to := "/var/lib/casaos/conf"
file.IsNotExistMkDir(to)
from := "/casaOS/server/conf"
if fds, err = ioutil.ReadDir(from); err != nil {
return err
}
for _, fd := range fds {
fExt := path.Ext(fd.Name())
if fExt != ".json" {
continue
}
srcfp := path.Join(from, fd.Name())
dstfp := path.Join(to, fd.Name())
source, err := os.Open(srcfp)
if err != nil {
return err
}
defer source.Close()
destination, err := os.Create(dstfp)
if err != nil {
return err
}
defer destination.Close()
_, err = io.Copy(destination, source)
if err != nil {
return err
}
}
}
_logger.Info("update done")
return nil
}
func (u *migrationTool036) PostMigrate() error {
return nil
}
func NewMigrationToolFor_035() interfaces.MigrationTool {
return &migrationTool{}
}

View File

@@ -0,0 +1,74 @@
/*
* @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 (
"strings"
interfaces "github.com/IceWhaleTech/CasaOS-Common"
"github.com/IceWhaleTech/CasaOS-Common/utils/version"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/service"
)
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 {
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")
}
_logger.Info("update done")
return nil
}
func (u *migrationTool) PostMigrate() error {
return nil
}
func NewMigrationToolFor_036() interfaces.MigrationTool {
return &migrationTool{}
}

89
common/notify.go Normal file
View File

@@ -0,0 +1,89 @@
package common
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
)
const (
CasaOSURLFilename = "casaos.url"
APICasaOSNotify = "/v1/notify"
)
type NotifyService interface {
SendNotify(path string, message map[string]interface{}) error
SendSystemStatusNotify(message map[string]interface{}) error
}
type notifyService struct {
address string
}
func (n *notifyService) SendNotify(path string, message map[string]interface{}) error {
url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/" + path
body, err := json.Marshal(message)
if err != nil {
return err
}
response, err := http.Post(url, "application/json", bytes.NewBuffer(body))
if err != nil {
return err
}
if response.StatusCode != http.StatusOK {
return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")")
}
return nil
}
// disk: "sys_disk":{"size":56866869248,"avail":5855485952,"health":true,"used":48099700736}
// usb: "sys_usb":[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}]
func (n *notifyService) SendSystemStatusNotify(message map[string]interface{}) error {
url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/system_status"
fmt.Println(url)
body, err := json.Marshal(message)
if err != nil {
return err
}
response, err := http.Post(url, "application/json", bytes.NewBuffer(body))
if err != nil {
return err
}
if response.StatusCode != http.StatusOK {
return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")")
}
return nil
}
func NewNotifyService(runtimePath string) (NotifyService, error) {
casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename)
buf, err := os.ReadFile(casaosAddressFile)
if err != nil {
return nil, err
}
address := string(buf)
response, err := http.Get(address + "/ping")
if err != nil {
return nil, err
}
if response.StatusCode != 200 {
return nil, errors.New("failed to ping casaos service")
}
return &notifyService{
address: address,
}, nil
}

29
common/notify_test.go Normal file
View File

@@ -0,0 +1,29 @@
package common
import "testing"
func TestSendNotify(t *testing.T) {
notify, err := NewNotifyService("/var/run/casaos")
if err != nil {
t.Fatal(err)
}
err = notify.SendNotify("test", map[string]interface{}{
"test": "test",
})
if err != nil {
t.Fatal(err)
}
}
func TestSendSystemStatusNotify(t *testing.T) {
notify, err := NewNotifyService("/var/run/casaos")
if err != nil {
t.Fatal(err)
}
err = notify.SendSystemStatusNotify(map[string]interface{}{
"sys_usb": `[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}]`,
})
if err != nil {
t.Fatal(err)
}
}

78
common/share.go Normal file
View File

@@ -0,0 +1,78 @@
package common
import (
"bytes"
"encoding/json"
"errors"
"fmt"
"net/http"
"os"
"path/filepath"
"strings"
)
const (
APICasaOSShare = "/v1/samba/shares"
)
type ShareService interface {
DeleteShare(id string) error
}
type shareService struct {
address string
}
func (n *shareService) DeleteShare(id string) error {
url := strings.TrimSuffix(n.address, "/") + APICasaOSShare + "/" + id
fmt.Println(url)
message := "{}"
body, err := json.Marshal(message)
if err != nil {
return err
}
client := &http.Client{}
// Create request
req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(body))
if err != nil {
return err
}
// Fetch Request
response, err := client.Do(req)
if err != nil {
return err
}
defer response.Body.Close()
if response.StatusCode != http.StatusOK {
return errors.New("failed to send share (status code: " + fmt.Sprint(response.StatusCode) + ")")
}
return nil
}
func NewShareService(runtimePath string) (ShareService, error) {
casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename)
buf, err := os.ReadFile(casaosAddressFile)
if err != nil {
return nil, err
}
address := string(buf)
response, err := http.Get(address + "/ping")
if err != nil {
return nil, err
}
if response.StatusCode != 200 {
return nil, errors.New("failed to ping casaos service")
}
return &shareService{
address: address,
}, nil
}

14
common/share_test.go Normal file
View File

@@ -0,0 +1,14 @@
package common
import "testing"
func TestDeleteShare(t *testing.T) {
share, err := NewShareService("/var/run/casaos")
if err != nil {
t.Fatal(err)
}
err = share.DeleteShare("1")
if err != nil {
t.Fatal(err)
}
}

View File

@@ -1,32 +1,25 @@
[app] [app]
PAGE_SIZE = 10 PAGE_SIZE = 10
RuntimeRootPath = runtime/ RuntimeRootPath = runtime/
LogSavePath = /casaOS/logs/server/ LogPath = /var/log/casaos/
LogSaveName = log LogSaveName = log
LogFileExt = log LogFileExt = log
DateStrFormat = 20060102 DateStrFormat = 20060102
DateTimeFormat = 2006-01-02 15:04:05 DateTimeFormat = 2006-01-02 15:04:05
TimeFormat = 15:04:05 TimeFormat = 15:04:05
DateFormat = 2006-01-02 DateFormat = 2006-01-02
ProjectPath = /casaOS/server DBPath = /var/lib/casaos
RootPath = /casaOS ShellPath = /usr/share/casaos/shell
UserDataPath = /var/lib/casaos/conf
[server] [server]
HttpPort = 8089
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]
ConfigStr =
WidgetList =
[common]
[file] RuntimePath=/var/run/casaos
ShareDir =
DownloadDir =

54
go.mod
View File

@@ -4,82 +4,52 @@ 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/IceWhaleTech/CasaOS-Common v0.0.0-20220901034123-ca130f6b5ce9
github.com/IceWhaleTech/CasaOS-Gateway v0.3.6
github.com/Microsoft/go-winio v0.5.0 // indirect github.com/Microsoft/go-winio v0.5.0 // indirect
github.com/Microsoft/hcsshim v0.8.22 // indirect
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/containerd/containerd v1.5.7 // indirect
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/distribution v2.8.0+incompatible // indirect
github.com/docker/docker v20.10.7+incompatible github.com/docker/docker v20.10.7+incompatible
github.com/docker/go-connections v0.4.0 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/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 v3.2.2+incompatible
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/mux v1.8.0 // indirect
github.com/gorilla/websocket v1.4.2 github.com/gorilla/websocket v1.4.2
github.com/hirochachacha/go-smb2 v1.1.0
github.com/jinzhu/copier v0.3.2 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/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
github.com/morikuni/aec v1.0.0 // indirect github.com/morikuni/aec v1.0.0 // indirect
github.com/opencontainers/image-spec v1.0.2 // 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/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/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/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
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/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/driver/sqlite v1.2.6
gorm.io/gorm v1.22.5 gorm.io/gorm v1.22.5
) )

583
go.sum

File diff suppressed because it is too large Load Diff

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

136
main.go
View File

@@ -3,54 +3,64 @@ package main
import ( import (
"flag" "flag"
"fmt" "fmt"
"net"
"net/http" "net/http"
"path/filepath"
"time" "time"
"github.com/IceWhaleTech/CasaOS-Gateway/common"
"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/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"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"
"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")
versionFlag = flag.Bool("v", false, "version")
)
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() loger.LogInit()
if len(*dbFlag) == 0 { if len(*dbFlag) == 0 {
*dbFlag = config.AppInfo.ProjectPath + "/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()
go service.UDPService() service.GetToken()
fmt.Println("t", service.GetToken())
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) service.NewVersionApp = make(map[string]string)
route.InitFunction() route.InitFunction()
go service.SendIPToServer()
// go service.LoopFriend() // go service.LoopFriend()
// go service.MyService.App().CheckNewImage() // go service.MyService.App().CheckNewImage()
} }
// @title casaOS API // @title casaOS API
@@ -66,41 +76,19 @@ 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
} }
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()
@@ -114,18 +102,58 @@ 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", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "samba", "notify"}
for _, v := range routers {
err = service.MyService.Gateway().CreateRoute(&common.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 := common.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)
}
}
}()
// s := &http.Server{
// Addr: listener.Addr().String(), //fmt.Sprintf(":%v", config.ServerInfo.HttpPort),
// Handler: r,
// ReadTimeout: 60 * time.Second,
// WriteTimeout: 60 * time.Second,
// MaxHeaderBytes: 1 << 20,
// }
// s.ListenAndServe()
urlFilePath := filepath.Join(config.CommonInfo.RuntimePath, "casaos.url")
err = file.CreateFileAndWriteContent(urlFilePath, "http://"+listener.Addr().String())
if err != nil {
loger.Error("Management service is listening...",
zap.Any("address", listener.Addr().String()),
zap.Any("filepath", urlFilePath),
)
} }
s.ListenAndServe() err = http.Serve(listener, r)
if err != nil {
// if err := r.Run(fmt.Sprintf(":%v", config.ServerInfo.HttpPort)); err != nil { panic(err)
// fmt.Println("failed run app: ", err) }
// }
} }

View File

@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com * @Author: LinkLeong link@icewhale.com
* @Date: 2021-10-08 10:29:08 * @Date: 2021-10-08 10:29:08
* @LastEditors: LinkLeong * @LastEditors: LinkLeong
* @LastEditTime: 2022-05-25 19:17:45 * @LastEditTime: 2022-07-22 11:06:07
* @FilePath: /CasaOS/middleware/gin.go * @FilePath: /CasaOS/middleware/gin.go
* @Description: * @Description:
* @Website: https://www.casaos.io * @Website: https://www.casaos.io
@@ -13,8 +13,11 @@ package middleware
import ( import (
"fmt" "fmt"
"net/http" "net/http"
"strings"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"go.uber.org/zap"
) )
func Cors() gin.HandlerFunc { func Cors() gin.HandlerFunc {
@@ -24,14 +27,14 @@ func Cors() gin.HandlerFunc {
c.Header("Access-Control-Allow-Origin", "*") c.Header("Access-Control-Allow-Origin", "*")
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE") 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-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language,Content-Type,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods,Connection,Host,Origin,Referer,User-Agent,X-Requested-With")
// 允许浏览器(客户端)可以解析的头部 (重要) // 允许浏览器(客户端)可以解析的头部 (重要)
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers") 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.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-Max-Age", "172800")
c.Header("Access-Control-Allow-Credentials", "true") c.Header("Access-Control-Allow-Credentials", "true")
c.Set("content-type", "application/json") c.Set("Content-Type", "application/json")
//} //}
//允许类型校验 //允许类型校验
@@ -48,3 +51,12 @@ func Cors() gin.HandlerFunc {
c.Next() c.Next()
} }
} }
func WriteLog() gin.HandlerFunc {
return func(c *gin.Context) {
if !strings.Contains(c.Request.URL.String(), "password") {
loger.Info("request:", zap.Any("path", c.Request.URL.String()), zap.Any("param", c.Params), zap.Any("query", c.Request.URL.Query()), zap.Any("method", c.Request.Method))
c.Next()
}
}
}

View File

@@ -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"`
}

View File

@@ -6,6 +6,22 @@ import (
"time" "time"
) )
type ServerAppListCollection struct {
List []ServerAppList `json:"list"`
Recommend []ServerAppList `json:"recommend"`
Community []ServerAppList `json:"community"`
Version string `json:"version"`
}
// @tiger - 对于用于出参的数据结构,静态信息(例如 title
// 动态信息(例如 state、query_count应该划分到不同的数据结构中
//
// 这样的好处是
// 1 - 多次获取动态信息时可以减少出参复杂度,因为静态信息只获取一次就好
// 2 - 在未来的迭代中,可以降低维护成本(所有字段都展开放在一个层级维护成本略高)
//
// 另外,一些针对性字段,例如 Docker 相关的,可以用 map 来保存。
// 这样在未来增加多态 App例如 Snap不需要维护多个结构或者一个结构保存不必要的字段
type ServerAppList struct { type ServerAppList struct {
Id uint `gorm:"column:id;primary_key" json:"id"` Id uint `gorm:"column:id;primary_key" json:"id"`
Title string `json:"title"` Title string `json:"title"`
@@ -15,6 +31,7 @@ type ServerAppList struct {
Icon string `json:"icon"` Icon string `json:"icon"`
ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"` ScreenshotLink Strings `gorm:"type:json" json:"screenshot_link"`
Category string `json:"category"` Category string `json:"category"`
CategoryId int `json:"category_id"`
CategoryFont string `json:"category_font"` CategoryFont string `json:"category_font"`
PortMap string `json:"port_map"` PortMap string `json:"port_map"`
ImageVersion string `json:"image_version"` ImageVersion string `json:"image_version"`
@@ -28,7 +45,7 @@ type ServerAppList struct {
Index string `json:"index"` Index string `json:"index"`
CreatedAt time.Time `json:"created_at"` CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"` UpdatedAt time.Time `json:"updated_at"`
State string `json:"state"` State int `json:"state"`
Author string `json:"author"` Author string `json:"author"`
MinMemory int `json:"min_memory"` MinMemory int `json:"min_memory"`
MinDisk int `json:"min_disk"` MinDisk int `json:"min_disk"`
@@ -38,6 +55,7 @@ type ServerAppList struct {
Plugins Strings `json:"plugins"` Plugins Strings `json:"plugins"`
Origin string `json:"origin"` Origin string `json:"origin"`
Type int `json:"type"` Type int `json:"type"`
QueryCount int `json:"query_count"`
Developer string `json:"developer"` Developer string `json:"developer"`
HostName string `json:"host_name"` HostName string `json:"host_name"`
Privileged bool `json:"privileged"` Privileged bool `json:"privileged"`

View File

@@ -1,24 +1,23 @@
/* /*
* @Author: link a624669980@163.com * @Author: link a624669980@163.com
* @Date: 2022-05-16 17:37:08 * @Date: 2022-05-16 17:37:08
* @LastEditors: link a624669980@163.com * @LastEditors: LinkLeong
* @LastEditTime: 2022-06-07 17:12:30 * @LastEditTime: 2022-07-13 10:46:38
* @FilePath: \CasaOS\model\category.go * @FilePath: /CasaOS/model/category.go
* @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE * @Description:
*/ */
package model package model
// type ServerCategoryList struct {
// Version string `json:"version"`
// Item []CategoryList `json:"item"`
// }
type ServerCategoryList struct { type ServerCategoryList struct {
Version string `json:"version"`
Item []CategoryList `json:"item"`
}
type CategoryList struct {
Id uint `gorm:"column:id;primary_key" json:"id"` Id uint `gorm:"column:id;primary_key" json:"id"`
//CreatedAt time.Time `json:"created_at"` //CreatedAt time.Time `json:"created_at"`
// //
//UpdatedAt time.Time `json:"updated_at"` //UpdatedAt time.Time `json:"updated_at"`
Font string `json:"font"` Font string `json:"font"` // @tiger - 如果这个和前端有关,应该不属于后端的出参范围,而是前端去界定
Name string `json:"name"` Name string `json:"name"`
Count uint `json:"count"` Count uint `json:"count"` // @tiger - count 属于动态信息,应该单独放在一个出参结构中(原因见另外一个关于 静态/动态 出参的注释)
} }

20
model/connections.go Normal file
View 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"`
}

View File

@@ -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"`
}

View File

@@ -1,8 +1,22 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2021-12-08 18:10:25
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-13 10:49:16
* @FilePath: /CasaOS/model/docker.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model package model
type DockerStatsModel struct { type DockerStatsModel struct {
Icon string `json:"icon"` Icon string `json:"icon"`
Title string `json:"title"` Title string `json:"title"`
Data interface{} `json:"data"` Data interface{} `json:"data"`
Pre interface{} `json:"pre"` Previous interface{} `json:"previous"`
}
type DeckerDaemonModel struct {
Graph string `json:"graph"`
} }

View File

@@ -104,16 +104,17 @@ func (p *PathArray) Scan(input interface{}) error {
//} //}
type CustomizationPostData struct { type CustomizationPostData struct {
CustomId string `json:"custom_id"` ContainerName string `json:"container_name"`
Origin string `json:"origin"` CustomId string `json:"custom_id"`
NetworkModel string `json:"network_model"` Origin string `json:"origin"`
Index string `json:"index"` NetworkModel string `json:"network_model"`
Icon string `json:"icon"` Index string `json:"index"`
Image string `json:"image"` Icon string `json:"icon"`
Envs EnvArray `json:"envs"` Image string `json:"image"`
Ports PortArray `json:"ports"` Envs EnvArray `json:"envs"`
Volumes PathArray `json:"volumes"` Ports PortArray `json:"ports"`
Devices PathArray `json:"devices"` Volumes PathArray `json:"volumes"`
Devices PathArray `json:"devices"`
//Port string `json:"port,omitempty"` //Port string `json:"port,omitempty"`
PortMap string `json:"port_map"` PortMap string `json:"port_map"`
CpuShares int64 `json:"cpu_shares"` CpuShares int64 `json:"cpu_shares"`

View File

@@ -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
View 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"`
}

View File

@@ -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"`
}

View File

@@ -1 +0,0 @@
package receive

17
model/share.go Normal file
View 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"`
}

View File

@@ -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-05-30 16:43:59 * @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,59 +12,47 @@ 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
} }
//服务配置 // 服务配置
type APPModel struct { type APPModel struct {
LogSavePath string LogPath string
LogSaveName string LogSaveName string
LogFileExt string LogFileExt string
DateStrFormat string DateStrFormat string
DateTimeFormat string DateTimeFormat string
UserDataPath string
TimeFormat string TimeFormat string
DateFormat string DateFormat string
ProjectPath string DBPath string
RootPath string ShellPath 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
@@ -74,12 +62,7 @@ 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 { type CasaOSGlobalVariables struct {

View File

@@ -1 +0,0 @@
package model

View File

@@ -0,0 +1,17 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-06-15 11:30:47
* @LastEditors: LinkLeong
* @LastEditTime: 2022-06-23 18:40:40
* @FilePath: /CasaOS/model/system_model/verify_information.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package system_model
type VerifyInformation struct {
RefreshToken string `json:"refresh_token"`
AccessToken string `json:"access_token"`
ExpiresAt int64 `json:"expires_at"`
}

View File

@@ -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"`
} }

View File

@@ -1,5 +1,15 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2021-09-30 18:18:14
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-31 17:04:02
* @FilePath: /CasaOS/pkg/config/config.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package config package config
const ( const (
USERCONFIGURL = "conf/conf.ini" USERCONFIGURL = "/etc/casaos/casaos.conf"
) )

View File

@@ -1,3 +1,13 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-09-05 11:58:02
* @FilePath: /CasaOS/pkg/config/init.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package config package config
import ( import (
@@ -13,18 +23,17 @@ 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 CommonInfo = &model.CommonModel{}
//var RedisInfo = &model.RedisModel{} //var RedisInfo = &model.RedisModel{}
//server相关 // server相关
var ServerInfo = &model.ServerModel{} var ServerInfo = &model.ServerModel{}
var SystemConfigInfo = &model.SystemConfig{} var SystemConfigInfo = &model.SystemConfig{}
@@ -35,33 +44,57 @@ var FileSettingInfo = &model.FileSetting{}
var Cfg *ini.File var Cfg *ini.File
//初始化设置,获取系统的部分信息。 // 初始化设置,获取系统的部分信息。
func InitSetup(config string) { func InitSetup(config string) {
var configDir = USERCONFIGURL var configDir = USERCONFIGURL
if len(config) > 0 { if len(config) > 0 {
configDir = config configDir = config
} }
if runtime.GOOS == "darwin" {
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 {
AppInfo.DBPath = "/var/lib/casaos"
}
if len(AppInfo.LogPath) == 0 {
AppInfo.LogPath = "/var/log/casaos/"
}
if len(AppInfo.ShellPath) == 0 {
AppInfo.ShellPath = "/usr/share/casaos/shell"
}
if len(AppInfo.UserDataPath) == 0 {
AppInfo.UserDataPath = "/var/lib/casaos/conf"
}
if len(CommonInfo.RuntimePath) == 0 {
CommonInfo.RuntimePath = "/var/run/casaos"
}
Cfg.SaveTo(configDir)
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd() // 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 {

View File

@@ -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()
}

View File

@@ -6,7 +6,6 @@ import (
"fmt" "fmt"
"io" "io"
"regexp" "regexp"
"strconv"
"sync" "sync"
"time" "time"
@@ -15,7 +14,7 @@ import (
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
) )
func NewSshClient(user, password string) (*ssh.Client, error) { func NewSshClient(user, password string, port string) (*ssh.Client, error) {
// connet to ssh // connet to ssh
// addr = fmt.Sprintf("%s:%d", host, port) // addr = fmt.Sprintf("%s:%d", host, port)
@@ -32,7 +31,7 @@ func NewSshClient(user, password string) (*ssh.Client, error) {
//} else { //} else {
// config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)} // config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)}
//} //}
addr := fmt.Sprintf("%s:%d", "127.0.0.1", 22) addr := fmt.Sprintf("%s:%s", "127.0.0.1", port)
c, err := ssh.Dial("tcp", addr, config) c, err := ssh.Dial("tcp", addr, config)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -396,7 +395,7 @@ func WsReaderCopy(reader *websocket.Conn, writer io.Writer) {
if err = json2.Unmarshal(p, &msgObj); err != nil { if err = json2.Unmarshal(p, &msgObj); err != nil {
writer.Write(p) writer.Write(p)
} else if msgObj.Type == wsMsgResize { } else if msgObj.Type == wsMsgResize {
writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r")) //writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
} }
} }
} }

75
pkg/samba/smaba.go Normal file
View 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
}

View File

@@ -1,11 +1,22 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-08-31 13:39:24
* @FilePath: /CasaOS/pkg/sqlite/db.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package sqlite package sqlite
import ( import (
"fmt"
"time" "time"
"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"
"go.uber.org/zap"
"gorm.io/driver/sqlite" "gorm.io/driver/sqlite"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -16,7 +27,7 @@ func GetDb(dbPath string) *gorm.DB {
if gdb != nil { if gdb != nil {
return gdb return gdb
} }
// 参考 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)
@@ -26,14 +37,19 @@ func GetDb(dbPath string) *gorm.DB {
c.SetMaxOpenConns(100) c.SetMaxOpenConns(100)
c.SetConnMaxIdleTime(time.Second * 1000) c.SetConnMaxIdleTime(time.Second * 1000)
if err != nil { if err != nil {
fmt.Println("连接数据失败!") loger.Error("sqlite connect error", zap.Any("db connect error", err))
panic("数据库连接失败") panic("sqlite connect error")
return nil return nil
} }
gdb = db gdb = db
err = db.AutoMigrate(&model2.TaskDBModel{}, &model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.PersonDownloadDBModel{}, model2.FriendModel{}, model2.PersonDownRecordDBModel{}, model2.ApplicationModel{})
err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{})
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 {
fmt.Println("检查和创建数据库出错", err) loger.Error("check or create db error", zap.Any("error", err))
} }
return db return db
} }

View File

@@ -1,89 +0,0 @@
package upnp
import (
"encoding/xml"
"io/ioutil"
"net/http"
"strings"
)
func GetCtrlUrl(host, device string) string {
request := ctrlUrlRequest(host, device)
response, _ := http.DefaultClient.Do(request)
resultBody, _ := ioutil.ReadAll(response.Body)
defer response.Body.Close()
if response.StatusCode == 200 {
return resolve(string(resultBody))
}
return ""
}
func ctrlUrlRequest(host string, deviceDescUrl string) *http.Request {
//请求头
header := http.Header{}
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
header.Set("User-Agent", "preston")
header.Set("Host", host)
header.Set("Connection", "keep-alive")
request, _ := http.NewRequest("GET", "http://"+host+deviceDescUrl, nil)
request.Header = header
return request
}
func resolve(resultStr string) string {
inputReader := strings.NewReader(resultStr)
// 从文件读取,如可以如下:
// content, err := ioutil.ReadFile("studygolang.xml")
// decoder := xml.NewDecoder(bytes.NewBuffer(content))
lastLabel := ""
ISUpnpServer := false
IScontrolURL := false
var controlURL string //`controlURL`
// var eventSubURL string //`eventSubURL`
// var SCPDURL string //`SCPDURL`
decoder := xml.NewDecoder(inputReader)
for t, err := decoder.Token(); err == nil && !IScontrolURL; t, err = decoder.Token() {
switch token := t.(type) {
// 处理元素开始(标签)
case xml.StartElement:
if ISUpnpServer {
name := token.Name.Local
lastLabel = name
}
// 处理元素结束(标签)
case xml.EndElement:
// log.Println("结束标记:", token.Name.Local)
// 处理字符数据(这里就是元素的文本)
case xml.CharData:
//得到url后其他标记就不处理了
content := string([]byte(token))
//找到提供端口映射的服务
if content == "urn:schemas-upnp-org:service:WANIPConnection:1" {
ISUpnpServer = true
continue
}
if ISUpnpServer {
switch lastLabel {
case "controlURL":
controlURL = content
IScontrolURL = true
case "eventSubURL":
// eventSubURL = content
case "SCPDURL":
// SCPDURL = content
}
}
default:
// ...
}
}
return controlURL
}

View File

@@ -1,17 +0,0 @@
package upnp
import (
"testing"
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
)
func TestGetCtrlUrl(t *testing.T) {
upnp, err := Gateway()
if err == nil {
upnp.CtrlUrl = GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
upnp.LocalHost = ip_helper2.GetLoclIp()
upnp.AddPortMapping(8090, 8090, "TCP")
//upnp.DelPortMapping(9999, "TCP")
}
}

View File

@@ -1,76 +0,0 @@
package upnp
import (
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
"github.com/pkg/errors"
"net"
"strings"
)
func Gateway() (*Upnp, error) {
result, error := send()
if result == "" || error != nil {
return nil, error
}
upnp := resolvesss(result)
return upnp, nil
}
func send() (string, error) {
var str = "M-SEARCH * HTTP/1.1\r\n" +
"HOST: 239.255.255.250:1900\r\n" +
"ST: urn:schemas-upnp-org:service:WANIPConnection:1\r\n" +
"MAN: \"ssdp:discover\"\r\n" + "MX: 3\r\n\r\n"
var conn *net.UDPConn
remoteAddr, err := net.ResolveUDPAddr("udp", "239.255.255.250:1900")
if err != nil {
return "", errors.New("组播地址格式不正确")
}
localAddr, err := net.ResolveUDPAddr("udp", ip_helper2.GetLoclIp()+":")
if err != nil {
return "", errors.New("本地ip地址格式不正确")
}
conn, err = net.ListenUDP("udp", localAddr)
defer conn.Close()
if err != nil {
return "", errors.New("监听udp出错")
}
_, err = conn.WriteToUDP([]byte(str), remoteAddr)
if err != nil {
return "", errors.New("发送msg到组播地址出错")
}
buf := make([]byte, 1024)
n, _, err := conn.ReadFromUDP(buf)
if err != nil {
return "", errors.New("从组播地址接搜消息出错")
}
result := string(buf[:n])
return result, nil
}
func resolvesss(result string) *Upnp {
var upnp = &Upnp{}
lines := strings.Split(result, "\r\n")
for _, line := range lines {
//按照第一个冒号分为两个字符串
nameValues := strings.SplitAfterN(line, ":", 2)
if len(nameValues) < 2 {
continue
}
switch strings.ToUpper(strings.Trim(strings.Split(nameValues[0], ":")[0], " ")) {
case "ST":
//fmt.Println(nameValues[1])
case "CACHE-CONTROL":
//fmt.Println(nameValues[1])
case "LOCATION":
urls := strings.Split(strings.Split(nameValues[1], "//")[1], "/")
upnp.GatewayHost = (urls[0])
upnp.DeviceDescUrl = ("/" + urls[1])
case "SERVER":
upnp.GatewayName = (nameValues[1])
default:
}
}
return upnp
}

View File

@@ -1,8 +0,0 @@
package upnp
import "testing"
func TestGateway(t *testing.T) {
Gateway()
}

View File

@@ -1,158 +0,0 @@
package upnp
import (
"bytes"
"net/http"
"strconv"
"strings"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/pkg/errors"
)
//
////添加一个端口映射
func (n *Upnp) AddPortMapping(localPort, remotePort int, protocol string) (err error) {
defer func() {
if errTemp := recover(); errTemp != nil {
loger2.NewOLoger().Error("upnp模块报错了", errTemp)
}
}()
if isSuccess := addSend(localPort, remotePort, protocol, n.GatewayHost, n.CtrlUrl, n.LocalHost); isSuccess {
return nil
} else {
return errors.New("添加一个端口映射失败")
}
}
func addSend(localPort, remotePort int, protocol, host, ctrUrl, localHost string) bool {
request := addRequest(localPort, remotePort, protocol, host, ctrUrl, localHost)
response, _ := http.DefaultClient.Do(request)
defer response.Body.Close()
//resultBody, _ := ioutil.ReadAll(response.Body)
//fmt.Println(string(resultBody))
return response.StatusCode == 200
}
type Node struct {
Name string
Content string
Attr map[string]string
Child []Node
}
func addRequest(localPort, remotePort int, protocol string, gatewayHost, ctlUrl, localHost string) *http.Request {
//请求头
header := http.Header{}
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
header.Set("SOAPAction", `"urn:schemas-upnp-org:service:WANIPConnection:1#AddPortMapping"`)
header.Set("Content-Type", "text/xml")
header.Set("Connection", "Close")
header.Set("Content-Length", "")
//请求体
body := Node{Name: "SOAP-ENV:Envelope",
Attr: map[string]string{"xmlns:SOAP-ENV": `"http://schemas.xmlsoap.org/soap/envelope/"`,
"SOAP-ENV:encodingStyle": `"http://schemas.xmlsoap.org/soap/encoding/"`}}
childOne := Node{Name: `SOAP-ENV:Body`}
childTwo := Node{Name: `m:AddPortMapping`,
Attr: map[string]string{"xmlns:m": `"urn:schemas-upnp-org:service:WANIPConnection:1"`}}
childList1 := Node{Name: "NewExternalPort", Content: strconv.Itoa(remotePort)}
childList2 := Node{Name: "NewInternalPort", Content: strconv.Itoa(localPort)}
childList3 := Node{Name: "NewProtocol", Content: protocol}
childList4 := Node{Name: "NewEnabled", Content: "1"}
childList5 := Node{Name: "NewInternalClient", Content: localHost}
childList6 := Node{Name: "NewLeaseDuration", Content: "0"}
childList7 := Node{Name: "NewPortMappingDescription", Content: "Oasis"}
childList8 := Node{Name: "NewRemoteHost"}
childTwo.AddChild(childList1)
childTwo.AddChild(childList2)
childTwo.AddChild(childList3)
childTwo.AddChild(childList4)
childTwo.AddChild(childList5)
childTwo.AddChild(childList6)
childTwo.AddChild(childList7)
childTwo.AddChild(childList8)
childOne.AddChild(childTwo)
body.AddChild(childOne)
bodyStr := body.BuildXML()
//请求
request, _ := http.NewRequest("POST", "http://"+gatewayHost+ctlUrl,
strings.NewReader(bodyStr))
request.Header = header
request.Header.Set("Content-Length", strconv.Itoa(len([]byte(bodyStr))))
return request
}
func (n *Node) AddChild(node Node) {
n.Child = append(n.Child, node)
}
func (n *Node) BuildXML() string {
buf := bytes.NewBufferString("<")
buf.WriteString(n.Name)
for key, value := range n.Attr {
buf.WriteString(" ")
buf.WriteString(key + "=" + value)
}
buf.WriteString(">" + n.Content)
for _, node := range n.Child {
buf.WriteString(node.BuildXML())
}
buf.WriteString("</" + n.Name + ">")
return buf.String()
}
func (n *Upnp) DelPortMapping(remotePort int, protocol string) bool {
isSuccess := delSendSend(remotePort, protocol, n.GatewayHost, n.CtrlUrl)
if isSuccess {
//this.MappingPort.delMapping(remotePort, protocol)
//fmt.Println("删除了一个端口映射: remote:", remotePort)
}
return isSuccess
}
func delSendSend(remotePort int, protocol, host, ctlUrl string) bool {
delrequest := delbuildRequest(remotePort, protocol, host, ctlUrl)
response, _ := http.DefaultClient.Do(delrequest)
//resultBody, _ := ioutil.ReadAll(response.Body)
defer response.Body.Close()
return response.StatusCode == 200
}
func delbuildRequest(remotePort int, protocol, host, ctlUrl string) *http.Request {
//请求头
header := http.Header{}
header.Set("Accept", "text/html, image/gif, image/jpeg, *; q=.2, */*; q=.2")
header.Set("SOAPAction", `"urn:schemas-upnp-org:service:WANIPConnection:1#DeletePortMapping"`)
header.Set("Content-Type", "text/xml")
header.Set("Connection", "Close")
header.Set("Content-Length", "")
//请求体
body := Node{Name: "SOAP-ENV:Envelope",
Attr: map[string]string{"xmlns:SOAP-ENV": `"http://schemas.xmlsoap.org/soap/envelope/"`,
"SOAP-ENV:encodingStyle": `"http://schemas.xmlsoap.org/soap/encoding/"`}}
childOne := Node{Name: `SOAP-ENV:Body`}
childTwo := Node{Name: `m:DeletePortMapping`,
Attr: map[string]string{"xmlns:m": `"urn:schemas-upnp-org:service:WANIPConnection:1"`}}
childList1 := Node{Name: "NewExternalPort", Content: strconv.Itoa(remotePort)}
childList2 := Node{Name: "NewProtocol", Content: protocol}
childList3 := Node{Name: "NewRemoteHost"}
childTwo.AddChild(childList1)
childTwo.AddChild(childList2)
childTwo.AddChild(childList3)
childOne.AddChild(childTwo)
body.AddChild(childOne)
bodyStr := body.BuildXML()
//请求
request, _ := http.NewRequest("POST", "http://"+host+ctlUrl,
strings.NewReader(bodyStr))
request.Header = header
request.Header.Set("Content-Length", strconv.Itoa(len([]byte(bodyStr))))
return request
}

View File

@@ -1,7 +0,0 @@
package upnp
import "testing"
func TestAddPortMapping(t *testing.T) {
//AddPortMapping(6666,6666,"TCP","192.168.2.15000",)
}

View File

@@ -1,25 +0,0 @@
package upnp
import (
"fmt"
"github.com/prestonTao/upnp"
)
type Upnp struct {
LocalHost string `json:"local_host"`
GatewayName string `json:"gateway_name"` //网关名称
GatewayHost string `json:"gateway_host"` //网关ip和端口
DeviceDescUrl string `json:"device_desc_url"` //设备描述url
CtrlUrl string `json:"ctrl_url"` //控制请求url
}
func Testaaa() {
upnpMan := new(upnp.Upnp)
err := upnpMan.SearchGateway()
if err != nil {
fmt.Println(err.Error())
} else {
fmt.Println("local ip address: ", upnpMan.LocalHost)
fmt.Println("gateway ip address: ", upnpMan.Gateway.Host)
}
}

View File

@@ -1,9 +0,0 @@
package upnp
import (
"testing"
)
func TestTestaaa(t *testing.T) {
(Testaaa())
}

123
pkg/utils/common_err/e.go Normal file
View File

@@ -0,0 +1,123 @@
package common_err
const (
SUCCESS = 200
SERVICE_ERROR = 500
CLIENT_ERROR = 400
ERROR_AUTH_TOKEN = 401
INVALID_PARAMS = 4000
//user
PWD_INVALID = 10001
PWD_IS_EMPTY = 10002
PWD_INVALID_OLD = 10003
ACCOUNT_LOCK = 10004
PWD_IS_TOO_SIMPLE = 10005
USER_NOT_EXIST = 10006
USER_EXIST = 10007
KEY_NOT_EXIST = 10008
NOT_IMAGE = 10009
IMAGE_TOO_LARGE = 10010
INSUFFICIENT_PERMISSIONS = 10011
//system
DIR_ALREADY_EXISTS = 20001
FILE_ALREADY_EXISTS = 20002
FILE_OR_DIR_EXISTS = 20003
PORT_IS_OCCUPIED = 20004
COMMAND_ERROR_INVALID_OPERATION = 20005
VERIFICATION_FAILURE = 20006
Record_NOT_EXIST = 20007
Record_ALREADY_EXIST = 20008
SERVICE_NOT_RUNNING = 20009
//disk
NAME_NOT_AVAILABLE = 40001
DISK_NEEDS_FORMAT = 40002
DISK_BUSYING = 40003
REMOVE_MOUNT_POINT_ERROR = 40004
FORMAT_ERROR = 40005
//app
UNINSTALL_APP_ERROR = 50001
PULL_IMAGE_ERROR = 50002
DEVICE_NOT_EXIST = 50003
ERROR_APP_NAME_EXIST = 50004
//file
FILE_DOES_NOT_EXIST = 60001
FILE_READ_ERROR = 60002
FILE_DELETE_ERROR = 60003
DIR_NOT_EXISTS = 60004
SOURCE_DES_SAME = 60005
//share
SHARE_ALREADY_EXISTS = 70001
SHARE_NAME_ALREADY_EXISTS = 70002
)
var MsgFlags = map[int]string{
SUCCESS: "ok",
SERVICE_ERROR: "Fail",
CLIENT_ERROR: "Fail",
INVALID_PARAMS: "Parameters Error",
ERROR_AUTH_TOKEN: "Error auth token",
//user
PWD_INVALID: "Invalid password",
PWD_IS_EMPTY: "Password is empty",
PWD_INVALID_OLD: "Invalid old password",
ACCOUNT_LOCK: "Account is locked",
PWD_IS_TOO_SIMPLE: "Password is too simple",
USER_NOT_EXIST: "User does not exist",
USER_EXIST: "User already exists",
KEY_NOT_EXIST: "Key does not exist",
IMAGE_TOO_LARGE: "Image is too large",
NOT_IMAGE: "Not an image",
INSUFFICIENT_PERMISSIONS: "Insufficient permissions",
//system
DIR_ALREADY_EXISTS: "Folder already exists",
FILE_ALREADY_EXISTS: "File already exists",
FILE_OR_DIR_EXISTS: "File or folder already exists",
PORT_IS_OCCUPIED: "Port is occupied",
VERIFICATION_FAILURE: "Verification failure",
Record_ALREADY_EXIST: "Record already exists",
Record_NOT_EXIST: "Record does not exist",
SERVICE_NOT_RUNNING: "Service is not running",
//app
UNINSTALL_APP_ERROR: "Error uninstalling app",
PULL_IMAGE_ERROR: "Error pulling image",
DEVICE_NOT_EXIST: "Device does not exist",
ERROR_APP_NAME_EXIST: "App name already exists",
//disk
NAME_NOT_AVAILABLE: "Name not available",
DISK_NEEDS_FORMAT: "Drive needs to be formatted",
REMOVE_MOUNT_POINT_ERROR: "Failed to remove mount point",
DISK_BUSYING: "Drive is busy",
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.",
FILE_DOES_NOT_EXIST: "File does not exist",
DIR_NOT_EXISTS: "Directory does not exist",
FILE_READ_ERROR: "File read error",
FILE_DELETE_ERROR: "Delete error",
COMMAND_ERROR_INVALID_OPERATION: "invalid operation",
}
//获取错误信息
func GetMsg(code int) string {
msg, ok := MsgFlags[code]
if ok {
return msg
}
return MsgFlags[SERVICE_ERROR]
}

View File

@@ -0,0 +1,22 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-06-14 14:33:25
* @LastEditors: LinkLeong
* @LastEditTime: 2022-06-14 14:33:49
* @FilePath: /CasaOS/pkg/utils/encryption/md5_helper.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package encryption
import (
"crypto/md5"
"encoding/hex"
)
func GetMD5ByStr(str string) string {
h := md5.New()
h.Write([]byte(str))
return hex.EncodeToString(h.Sum(nil))
}

View File

@@ -225,6 +225,48 @@ func CopyFile(src, dst, style string) error {
return os.Chmod(dst, srcinfo.Mode()) return os.Chmod(dst, srcinfo.Mode())
} }
/**
* @description:
* @param {*} src
* @param {*} dst
* @param {string} style
* @return {*}
* @method:
* @router:
*/
func CopySingleFile(src, dst, style string) error {
var err error
var srcfd *os.File
var dstfd *os.File
var srcinfo os.FileInfo
if Exists(dst) {
if style == "skip" {
return nil
} else {
os.Remove(dst)
}
}
if srcfd, err = os.Open(src); err != nil {
return err
}
defer srcfd.Close()
if dstfd, err = os.Create(dst); err != nil {
return err
}
defer dstfd.Close()
if _, err = io.Copy(dstfd, srcfd); err != nil {
return err
}
if srcinfo, err = os.Stat(src); err != nil {
return err
}
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)
@@ -482,3 +524,43 @@ func DirSizeB(path string) (int64, error) {
}) })
return size, err return size, err
} }
func MoveFile(sourcePath, destPath string) error {
inputFile, err := os.Open(sourcePath)
if err != nil {
return fmt.Errorf("Couldn't open source file: %s", err)
}
outputFile, err := os.Create(destPath)
if err != nil {
inputFile.Close()
return fmt.Errorf("Couldn't open dest file: %s", err)
}
defer outputFile.Close()
_, err = io.Copy(outputFile, inputFile)
inputFile.Close()
if err != nil {
return fmt.Errorf("Writing to output file failed: %s", err)
}
err = os.Remove(sourcePath)
if err != nil {
return fmt.Errorf("Failed removing original file: %s", err)
}
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 ""
}

View File

@@ -2,9 +2,13 @@ package file
import ( import (
"bytes" "bytes"
"errors"
"fmt" "fmt"
"io" "io"
"net/http"
"os" "os"
"path/filepath"
"strings"
"github.com/disintegration/imaging" "github.com/disintegration/imaging"
"github.com/dsoprea/go-exif/v3" "github.com/dsoprea/go-exif/v3"
@@ -82,3 +86,176 @@ func GetThumbnailByWebPhoto(path string, width, height int) ([]byte, error) {
imaging.Encode(&buf, img, f) imaging.Encode(&buf, img, f)
return buf.Bytes(), nil return buf.Bytes(), nil
} }
func ImageExtArray() []string {
ext := []string{
"ase",
"art",
"bmp",
"blp",
"cd5",
"cit",
"cpt",
"cr2",
"cut",
"dds",
"dib",
"djvu",
"egt",
"exif",
"gif",
"gpl",
"grf",
"icns",
"ico",
"iff",
"jng",
"jpeg",
"jpg",
"jfif",
"jp2",
"jps",
"lbm",
"max",
"miff",
"mng",
"msp",
"nitf",
"ota",
"pbm",
"pc1",
"pc2",
"pc3",
"pcf",
"pcx",
"pdn",
"pgm",
"PI1",
"PI2",
"PI3",
"pict",
"pct",
"pnm",
"pns",
"ppm",
"psb",
"psd",
"pdd",
"psp",
"px",
"pxm",
"pxr",
"qfx",
"raw",
"rle",
"sct",
"sgi",
"rgb",
"int",
"bw",
"tga",
"tiff",
"tif",
"vtf",
"xbm",
"xcf",
"xpm",
"3dv",
"amf",
"ai",
"awg",
"cgm",
"cdr",
"cmx",
"dxf",
"e2d",
"egt",
"eps",
"fs",
"gbr",
"odg",
"svg",
"stl",
"vrml",
"x3d",
"sxd",
"v2d",
"vnd",
"wmf",
"emf",
"art",
"xar",
"png",
"webp",
"jxr",
"hdp",
"wdp",
"cur",
"ecw",
"iff",
"lbm",
"liff",
"nrrd",
"pam",
"pcx",
"pgf",
"sgi",
"rgb",
"rgba",
"bw",
"int",
"inta",
"sid",
"ras",
"sun",
"tga",
}
return ext
}
/**
* @description:get a image's ext
* @param {string} path "file path"
* @return {string} ext "file ext"
* @return {error} err "error info"
*/
func GetImageExt(p string) (string, error) {
file, err := os.Open(p)
if err != nil {
return "", err
}
buff := make([]byte, 512)
_, err = file.Read(buff)
if err != nil {
return "", err
}
filetype := http.DetectContentType(buff)
ext := ImageExtArray()
for i := 0; i < len(ext); i++ {
if strings.Contains(ext[i], filetype[6:]) {
return ext[i], nil
}
}
return "", errors.New("invalid image type")
}
func GetImageExtByName(p string) (string, error) {
extArr := ImageExtArray()
ext := filepath.Ext(p)
for i := 0; i < len(extArr); i++ {
if strings.Contains(ext, extArr[i]) {
return extArr[i], nil
}
}
return "", errors.New("invalid image type")
}

View File

@@ -1,46 +0,0 @@
package jwt
import (
"time"
jwt "github.com/golang-jwt/jwt"
)
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
}

View File

@@ -1,54 +0,0 @@
package jwt
import (
"fmt"
"net/http"
"github.com/IceWhaleTech/CasaOS/model"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/gin-gonic/gin"
)
func JWT(swagHandler gin.HandlerFunc) gin.HandlerFunc {
return func(c *gin.Context) {
var code int
code = oasis_err2.SUCCESS
token := c.GetHeader("Authorization")
if len(token) == 0 {
token = c.Query("token")
}
if token == "" {
code = oasis_err2.INVALID_PARAMS
}
if swagHandler == nil {
//claims, err := ParseToken(token)
_, err := ParseToken(token)
if err != nil {
code = oasis_err2.ERROR_AUTH_TOKEN
}
//else if time.Now().Unix() > claims.ExpiresAt {
// code = oasis_err2.ERROR_AUTH_TOKEN
//}
}
if code != oasis_err2.SUCCESS {
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.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 ""
}
}

View File

@@ -2,7 +2,7 @@
* @Author: LinkLeong link@icewhale.com * @Author: LinkLeong link@icewhale.com
* @Date: 2022-06-02 15:09:38 * @Date: 2022-06-02 15:09:38
* @LastEditors: LinkLeong * @LastEditors: LinkLeong
* @LastEditTime: 2022-06-02 17:43:38 * @LastEditTime: 2022-06-27 15:47:49
* @FilePath: /CasaOS/pkg/utils/loger/log.go * @FilePath: /CasaOS/pkg/utils/loger/log.go
* @Description: * @Description:
* @Website: https://www.casaos.io * @Website: https://www.casaos.io
@@ -28,11 +28,11 @@ var loggers *zap.Logger
func getFileLogWriter() (writeSyncer zapcore.WriteSyncer) { func getFileLogWriter() (writeSyncer zapcore.WriteSyncer) {
// 使用 lumberjack 实现 log rotate // 使用 lumberjack 实现 log rotate
lumberJackLogger := &lumberjack.Logger{ lumberJackLogger := &lumberjack.Logger{
Filename: filepath.Join(config.AppInfo.LogSavePath, fmt.Sprintf("%s.%s", Filename: filepath.Join(config.AppInfo.LogPath, fmt.Sprintf("%s.%s",
config.AppInfo.LogSaveName, config.AppInfo.LogSaveName,
config.AppInfo.LogFileExt, config.AppInfo.LogFileExt,
)), )),
MaxSize: 100, MaxSize: 10,
MaxBackups: 60, MaxBackups: 60,
MaxAge: 1, MaxAge: 1,
Compress: true, Compress: true,
@@ -47,8 +47,8 @@ func LogInit() {
encoder := zapcore.NewJSONEncoder(encoderConfig) encoder := zapcore.NewJSONEncoder(encoderConfig)
fileWriteSyncer := getFileLogWriter() fileWriteSyncer := getFileLogWriter()
core := zapcore.NewTee( core := zapcore.NewTee(
zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), zapcore.DebugLevel), zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), zapcore.InfoLevel),
zapcore.NewCore(encoder, fileWriteSyncer, zapcore.DebugLevel), zapcore.NewCore(encoder, fileWriteSyncer, zapcore.InfoLevel),
) )
loggers = zap.New(core) loggers = zap.New(core)

View File

@@ -1,109 +0,0 @@
package loger
import (
"fmt"
"log"
"os"
"path/filepath"
"runtime"
"github.com/IceWhaleTech/CasaOS/pkg/config"
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
)
//定义一个int的别名
type Level int
type OLog interface {
Debug(v ...interface{})
Info(v ...interface{})
Warn(v ...interface{})
Error(v ...interface{})
Fatal(v ...interface{})
Path() string
}
type oLog struct {
}
var (
F *os.File
DefaultPrefix = ""
DefaultCallerDepth = 2
logger *log.Logger
logPrefix = ""
levelFlags = []string{"DEBUG", "INFO", "WARN", "ERROR", "FATAL"}
)
//iota在const关键字出现时将被重置为0(const内部的第一行之前)const中每新增一行常量声明将使iota计数一次(iota可理解为const语句块中的行索引)。
const (
DEBUG Level = iota
INFO
WARN
ERROR
FATAL
)
//日志初始化
func LogSetupOld() {
var err error
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath)
fileName := fmt.Sprintf("%s.%s",
config.AppInfo.LogSaveName,
config.AppInfo.LogFileExt,
)
F, err = file2.MustOpen(fileName, filePath)
if err != nil {
log.Fatalf("logging.Setup err: %v", err)
}
logger = log.New(F, DefaultPrefix, log.LstdFlags)
}
func (o *oLog) Path() string {
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath)
fileName := fmt.Sprintf("%s.%s",
config.AppInfo.LogSaveName,
config.AppInfo.LogFileExt,
)
return filePath + fileName
}
func (o *oLog) Debug(v ...interface{}) {
setPrefix(DEBUG)
logger.Println(v)
}
func (o *oLog) Info(v ...interface{}) {
setPrefix(INFO)
logger.Println(v)
}
func (o *oLog) Warn(v ...interface{}) {
setPrefix(WARN)
logger.Println(v)
}
func (o *oLog) Error(v ...interface{}) {
setPrefix(ERROR)
logger.Println(v)
}
func (o *oLog) Fatal(v ...interface{}) {
setPrefix(FATAL)
logger.Println(v)
}
func setPrefix(level Level) {
_, file, line, ok := runtime.Caller(DefaultCallerDepth)
if ok {
logPrefix = fmt.Sprintf("[%s][%s:%d]", levelFlags[level], filepath.Base(file), line)
} else {
logPrefix = fmt.Sprintf("[%s]", levelFlags[level])
}
logger.SetPrefix(logPrefix)
}
func NewOLoger() OLog {
return &oLog{}
}

View File

@@ -1,117 +0,0 @@
package oasis_err
const (
SUCCESS = 200
ERROR = 500
INVALID_PARAMS = 400
ERROR_AUTH_TOKEN = 401
//user
PWD_INVALID = 10001
PWD_IS_EMPTY = 10002
PWD_INVALID_OLD = 10003
ACCOUNT_LOCK = 10004
//system
DIR_ALREADY_EXISTS = 20001
FILE_ALREADY_EXISTS = 20002
FILE_OR_DIR_EXISTS = 20003
PORT_IS_OCCUPIED = 20004
COMMAND_ERROR_INVALID_OPERATION = 20005
//zerotier
GET_TOKEN_ERROR = 30001
//disk
NAME_NOT_AVAILABLE = 40001
DISK_NEEDS_FORMAT = 40002
DISK_BUSYING = 40003
REMOVE_MOUNT_POINT_ERROR = 40004
FORMAT_ERROR = 40005
//app
UNINSTALL_APP_ERROR = 50001
PULL_IMAGE_ERROR = 50002
DEVICE_NOT_EXIST = 50003
ERROR_APP_NAME_EXIST = 50004
//file
FILE_DOES_NOT_EXIST = 60001
FILE_READ_ERROR = 60002
FILE_DELETE_ERROR = 60003
DIR_NOT_EXISTS = 60004
SOURCE_DES_SAME = 60005
//shortcuts
SHORTCUTS_URL_ERROR = 70001
//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{
SUCCESS: "ok",
ERROR: "fail",
INVALID_PARAMS: "Parameters Error",
ERROR_AUTH_TOKEN: "Error auth token",
//user
PWD_INVALID: "Invalid password",
PWD_IS_EMPTY: "Password is empty",
PWD_INVALID_OLD: "Invalid old password",
ACCOUNT_LOCK: "Account is locked",
//system
DIR_ALREADY_EXISTS: "Folder already exists",
FILE_ALREADY_EXISTS: "File already exists",
FILE_OR_DIR_EXISTS: "File or folder already exists",
PORT_IS_OCCUPIED: "Port is occupied",
//zerotier
GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available",
//app
UNINSTALL_APP_ERROR: "Error uninstalling app",
PULL_IMAGE_ERROR: "Error pulling image",
DEVICE_NOT_EXIST: "Device does not exist",
ERROR_APP_NAME_EXIST: "App name already exists",
//disk
NAME_NOT_AVAILABLE: "Name not available",
DISK_NEEDS_FORMAT: "Drive needs to be formatted",
REMOVE_MOUNT_POINT_ERROR: "Failed to remove mount point",
DISK_BUSYING: "Drive is busy",
FORMAT_ERROR: "Formatting failed, please check if the directory is occupied",
//
SOURCE_DES_SAME: "Source and destination cannot be the same.",
FILE_DOES_NOT_EXIST: "File does not exist",
DIR_NOT_EXISTS: "Directory does not exist",
FILE_READ_ERROR: "File read 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",
}
//获取错误信息
func GetMsg(code int) string {
msg, ok := MsgFlags[code]
if ok {
return msg
}
return MsgFlags[ERROR]
}

33
pkg/utils/udev_helper.go Normal file
View 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
// }

View File

@@ -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-02 17:41:47 * @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
@@ -11,24 +11,17 @@
package version package version
import ( import (
json2 "encoding/json"
"strconv" "strconv"
"strings" "strings"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
"github.com/IceWhaleTech/CasaOS/types" "github.com/IceWhaleTech/CasaOS/types"
"github.com/tidwall/gjson"
) )
func IsNeedUpdate() (bool, model.Version) { func IsNeedUpdate(version model.Version) (bool, model.Version) {
var version model.Version
v := httper.OasisGet(config.ServerInfo.ServerApi + "/v1/sys/version")
data := gjson.Get(v, "data")
json2.Unmarshal([]byte(data.String()), &version)
v1 := strings.Split(version.Version, ".") v1 := strings.Split(version.Version, ".")
v2 := strings.Split(types.CURRENTVERSION, ".") v2 := strings.Split(types.CURRENTVERSION, ".")
for len(v1) < len(v2) { for len(v1) < len(v2) {
@@ -42,29 +35,10 @@ func IsNeedUpdate() (bool, model.Version) {
b, _ := strconv.Atoi(v2[i]) b, _ := strconv.Atoi(v2[i])
if a > b { if a > b {
return true, version return true, version
} else { }
if a < b {
return false, version return false, version
} }
} }
return false, version return false, version
} }
//a版本大于b版本
func VersionCompared(a string, b string) bool {
v1 := strings.Split(a, ".")
v2 := strings.Split(b, ".")
for len(v1) < len(v2) {
v1 = append(v1, "0")
}
for len(v2) < len(v1) {
v2 = append(v2, "0")
}
for i := 0; i < len(v1); i++ {
a, _ := strconv.Atoi(v1[i])
b, _ := strconv.Atoi(v2[i])
if a > b {
return true
}
}
return false
}

25
route/darwin.go Normal file
View 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() {
}

View File

@@ -1,15 +0,0 @@
//go:build doc
// +build doc
package route
import (
_ "github.com/IceWhaleTech/CasaOS/docs"
ginSwagger "github.com/swaggo/gin-swagger"
swaggerFiles "github.com/swaggo/gin-swagger/swaggerFiles"
)
func init() {
// swagHandler = ginSwagger.WrapHandler(swaggerFiles.Handler)
swagHandler = ginSwagger.WrapHandler(swaggerFiles.Handler)
}

View File

@@ -1,296 +1,48 @@
package route package route
import ( import (
"encoding/xml"
"fmt" "fmt"
"path/filepath" "os"
"runtime"
"strconv"
"strings" "strings"
"time" "time"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/pkg/samba"
"github.com/IceWhaleTech/CasaOS/model/system_app"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"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/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model" "go.uber.org/zap"
uuid "github.com/satori/go.uuid"
) )
func InitFunction() { func InitFunction() {
go checkSystemApp() go InitNetworkMount()
Update2_3()
CheckSerialDiskMount()
CheckToken2_11()
ImportApplications()
ChangeAPIUrl()
InitSystemApplication()
} }
func InitNetworkMount() {
var syncIsExistence = false time.Sleep(time.Second * 10)
connections := service.MyService.Connections().GetConnectionsList()
func installSyncthing(appId string) { for _, v := range connections {
connection := service.MyService.Connections().GetConnectionByID(fmt.Sprint(v.ID))
var appInfo model.ServerAppList directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
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 >> 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.Label = id
m.CustomId = id
containerId, err := service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m, appInfo.NetworkModel)
if err != nil {
fmt.Println("container create error", err)
// create container error
return
}
//stepstart 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 {
service.MyService.Connections().DeleteConnection(fmt.Sprint(connection.ID))
loger.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" {
//stepstart 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) os.RemoveAll(baseHostPath)
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)
}
} 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.Disk().RemoveLSBLKCache() service.MyService.Connections().UpdateConnection(&connection)
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AutoRemoveUnuseDir")
}
func Update2_3() {
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.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)
}
if len(config.AppInfo.RootPath) == 0 {
config.Cfg.Section("app").Key("RootPath").SetValue("/casaOS")
config.AppInfo.RootPath = "/casaOS"
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
// if len(config.ServerInfo.Handshake) == 0 {
// config.Cfg.Section("app").Key("RootPath").SetValue("/casaOS")
// config.AppInfo.RootPath = "/casaOS"
// 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.ZiMa().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.ZiMa().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.1
func InitSystemApplication() {
list := service.MyService.App().GetApplicationList()
if len(list) != 2 {
application := model2.ApplicationModel{}
application.Name = "Files"
application.Icon = "/ui/img/Files.svg"
application.Type = "system"
application.Order = 0
service.MyService.App().CreateApplication(application)
application.Name = "CasaConnect"
application.Icon = "/ui/img/CasaConnect.svg"
application.Type = "system"
application.Order = 0
service.MyService.App().CreateApplication(application)
} }
} }

View File

@@ -1,8 +1,11 @@
//go:build !darwin
// +build !darwin
/* /*
* @Author: LinkLeong link@icewhale.com * @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-27 15:55:36 * @Date: 2022-07-01 15:11:36
* @LastEditors: LinkLeong * @LastEditors: LinkLeong
* @LastEditTime: 2022-06-10 12:17:59 * @LastEditTime: 2022-09-05 16:28:46
* @FilePath: /CasaOS/route/periodical.go * @FilePath: /CasaOS/route/periodical.go
* @Description: * @Description:
* @Website: https://www.casaos.io * @Website: https://www.casaos.io
@@ -11,8 +14,6 @@
package route package route
import ( import (
"reflect"
"strconv"
"strings" "strings"
"time" "time"
"unsafe" "unsafe"
@@ -29,7 +30,7 @@ func SendNetINfoBySocket() {
for _, netCardName := range nets { for _, netCardName := range nets {
if n.Name == netCardName { if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n)) item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name)) item.State = strings.TrimSpace(service.MyService.System().GetNetState(n.Name))
item.Time = time.Now().Unix() item.Time = time.Now().Unix()
newNet = append(newNet, item) newNet = append(newNet, item)
break break
@@ -52,108 +53,6 @@ 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" {
temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
continue
}
//list[i].Temperature = temp.Temperature.Current
if !temp.SmartStatus.Passed {
healthy = false
}
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()
@@ -163,123 +62,59 @@ func SendAllHardwareStatusBySocket() {
for _, netCardName := range nets { for _, netCardName := range nets {
if n.Name == netCardName { if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n)) item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name)) item.State = strings.TrimSpace(service.MyService.System().GetNetState(n.Name))
item.Time = time.Now().Unix() item.Time = time.Now().Unix()
newNet = append(newNet, item) newNet = append(newNet, item)
break break
} }
} }
} }
cpu := service.MyService.System().GetCpuPercent() cpu := service.MyService.System().GetCpuPercent()
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()
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" {
temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
continue
}
//list[i].Temperature = temp.Temperature.Current
if !temp.SmartStatus.Passed {
healthy = false
}
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()
memData := make(map[string]interface{})
memData["total"] = memInfo.Total
memData["available"] = memInfo.Available
memData["used"] = memInfo.Used
memData["free"] = memInfo.Free
memData["usedPercent"] = memInfo.UsedPercent
service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memData, 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 {
// loger.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:
// loger.Error("udev err", zap.Any("err", err))
// }
// }
// }

View File

@@ -1,244 +1,219 @@
package route package route
import ( import (
"net/http" "github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
"github.com/IceWhaleTech/CasaOS/middleware" "github.com/IceWhaleTech/CasaOS/middleware"
"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 swagHandler gin.HandlerFunc
var OnlineDemo bool = false
func InitRouter() *gin.Engine { func InitRouter() *gin.Engine {
r := gin.Default() r := gin.Default()
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) gin.SetMode(config.ServerInfo.RunMode)
r.StaticFS("/ui", http.FS(web.Static)) // r.StaticFS("/ui", http.FS(web.Static))
r.GET("/", WebUIHome) // r.GET("/", WebUIHome)
// r.StaticFS("/assets", http.Dir("./static/assets"))
// 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/")
//}) //})
if swagHandler != nil {
r.GET("/swagger/*any", swagHandler)
}
r.POST("/v1/user/login", v1.Login)
r.GET("/v1/guide/check", v1.GetGuideCheck) // r.POST("/v1/users/register", v1.PostUserRegister)
// r.POST("/v1/users/login", v1.PostUserLogin)
// 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/debug", v1.GetSystemConfigDebug) // r.GET("/v1/users/status", v1.GetUserStatus) //init/check
//set user //r.GET("/v1/guide/check", v1.GetGuideCheck) // /v1/sys/guide_check
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd) r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug
//get user info
r.GET("/v1/user/info", v1.GetUserInfo) r.GET("/v1/sys/socket-port", v1.GetSystemSocketPort) //sys/socket_port
//get user info r.GET("/v1/sys/version/check", v1.GetSystemCheckVersion)
r.GET("/v1/person/shareid", v1.GetPersonShareId) r.GET("/ping", func(ctx *gin.Context) {
r.GET("/v1/sys/socket/port", v1.GetSystemSocketPort) ctx.String(200, "pong")
})
v1Group := r.Group("/v1") v1Group := r.Group("/v1")
v1Group.Use(jwt2.JWT(swagHandler)) v1Group.Use(jwt.ExceptLocalhost())
{ {
v1UserGroup := v1Group.Group("/user") // v1UsersGroup := v1Group.Group("/users")
v1UserGroup.Use() // v1UsersGroup.Use()
// {
// v1UsersGroup.GET("/current", v1.GetUserInfo)
// v1UsersGroup.PUT("/current", v1.PutUserInfo)
// v1UsersGroup.PUT("/current/password", v1.PutUserPassword)
// v1UsersGroup.GET("/current/custom/:key", v1.GetUserCustomConf)
// v1UsersGroup.POST("/current/custom/:key", v1.PostUserCustomConf)
// v1UsersGroup.DELETE("/current/custom/:key", v1.DeleteUserCustomConf)
// v1UsersGroup.POST("/current/image/:key", v1.PostUserUploadImage)
// v1UsersGroup.PUT("/current/image/:key", v1.PutUserImage)
// //v1UserGroup.POST("/file/image/:key", v1.PostUserFileImage)
// v1UsersGroup.DELETE("/current/image", v1.DeleteUserImage)
// //v1UserGroup.PUT("/avatar", v1.PutUserAvatar)
// //v1UserGroup.GET("/avatar", v1.GetUserAvatar)
// v1UsersGroup.DELETE("/:id", v1.DeleteUser)
// v1UsersGroup.GET("/:username", v1.GetUserInfoByUsername)
// v1UsersGroup.DELETE("", v1.DeleteUserAll)
// }
v1AppsGroup := v1Group.Group("/apps")
v1AppsGroup.Use()
{
v1AppsGroup.GET("", v1.AppList) //list
v1AppsGroup.GET("/:id", v1.AppInfo)
}
v1ContainerGroup := v1Group.Group("/container")
v1ContainerGroup.Use()
{ {
//chang head v1ContainerGroup.GET("", v1.MyAppList) ///my/list
v1UserGroup.POST("/head", v1.PostUserHead) v1ContainerGroup.GET("/usage", v1.AppUsageList)
//chang user name v1ContainerGroup.GET("/:id", v1.ContainerUpdateInfo) ///update/:id/info
v1UserGroup.PUT("/username", v1.PutUserName) v1ContainerGroup.GET("/:id/logs", v1.ContainerLog) // /app/logs/:id
//chang pwd v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) //app/install/config
v1UserGroup.PUT("/password", v1.PutUserPwd)
//edit user info
v1UserGroup.POST("/info", v1.PostUserChangeInfo)
v1UserGroup.PUT("/nick", v1.PutUserChangeNick)
v1UserGroup.PUT("/desc", v1.PutUserChangeDesc)
v1UserGroup.POST("/person/info", v1.PostUserPersonInfo)
v1UserGroup.GET("/shareid", v1.GetUserShareID) v1ContainerGroup.GET("/:id/state", v1.GetContainerState) //app/state/:id ?state=install_progress
// v1UserGroup.GET("/custom/:name") // there are problems, temporarily do not deal with
// v1UserGroup.POST("/custom/:name") v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) //app/terminal/:id
v1ContainerGroup.POST("", v1.InstallApp) //app/install
//v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id
v1ContainerGroup.PUT("/:id", v1.UpdateSetting) ///update/:id/setting
v1ContainerGroup.PUT("/:id/state", v1.ChangAppState) // /app/state/:id
v1ContainerGroup.DELETE("/:id", v1.UnInstallApp) //app/uninstall/:id
//Not used
v1ContainerGroup.PUT("/:id/latest", v1.PutAppUpdate)
//Not used
v1ContainerGroup.POST("/share", v1.ShareAppFile)
v1ContainerGroup.GET("/info", v1.GetcontainerInfo)
v1ContainerGroup.PUT("/info", v1.PutcontainerInfo)
} }
v1AppGroup := v1Group.Group("/app") v1AppCategoriesGroup := v1Group.Group("/app-categories")
v1AppGroup.Use() v1AppCategoriesGroup.Use()
{ {
//获取我的已安装的列表 v1AppCategoriesGroup.GET("", v1.CategoryList)
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)
v1AppGroup.GET("/order", v1.GetAppOrder)
v1AppGroup.POST("/order", v1.PostAppOrder)
//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.GET("/wsssh", v1.WsSsh)
v1SysGroup.GET("/config", v1.GetSystemConfig)
v1SysGroup.GET("/error/logs", v1.GetCasaOSErrorLogs)
v1SysGroup.POST("/config", v1.PostSetSystemConfig)
v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)
v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)
v1SysGroup.GET("/port", v1.GetCasaOSPort)
v1SysGroup.PUT("/port", v1.PutCasaOSPort)
v1SysGroup.POST("/stop", v1.PostKillCasaOS)
v1SysGroup.GET("/utilization", v1.GetSystemUtilization)
v1SysGroup.PUT("/usb/:status", v1.PutSystemUSBAutoMount)
v1SysGroup.GET("/usb/status", v1.GetSystemUSBAutoMount)
v1SysGroup.GET("/cpu", v1.GetSystemCupInfo)
v1SysGroup.GET("/mem", v1.GetSystemMemInfo)
v1SysGroup.GET("/disk", v1.GetSystemDiskInfo)
v1SysGroup.GET("/network", v1.GetSystemNetInfo)
v1SysGroup.POST("/update", v1.SystemUpdate)
v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) //hardware/info
v1SysGroup.GET("/wsssh", v1.WsSsh)
v1SysGroup.POST("/ssh-login", v1.PostSshLogin)
//v1SysGroup.GET("/config", v1.GetSystemConfig) //delete
//v1SysGroup.POST("/config", v1.PostSetSystemConfig)
v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) //error/logs
//v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete
//v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)//delete
v1SysGroup.POST("/stop", v1.PostKillCasaOS)
v1SysGroup.GET("/utilization", v1.GetSystemUtilization)
// v1SysGroup.GET("/cpu", v1.GetSystemCupInfo)
// v1SysGroup.GET("/mem", v1.GetSystemMemInfo)
// v1SysGroup.GET("/disk", v1.GetSystemDiskInfo)
// v1SysGroup.GET("/network", v1.GetSystemNetInfo)
v1SysGroup.PUT("/usb-auto-mount", v1.PutSystemUSBAutoMount) ///sys/usb/:status
v1SysGroup.GET("/usb-auto-mount", v1.GetSystemUSBAutoMount) ///sys/usb/status
v1SysGroup.GET("/server-info", nil)
v1SysGroup.PUT("/server-info", nil)
v1SysGroup.GET("/apps-state", v1.GetSystemAppsStatus)
//v1SysGroup.GET("/port", v1.GetCasaOSPort)
//v1SysGroup.PUT("/port", v1.PutCasaOSPort)
v1SysGroup.GET("/proxy", v1.GetSystemProxy)
} }
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)
//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) //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.FormatDisk)
// add storage
v1DiskGroup.POST("/storage", v1.AddPartition)
//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)
} }
v1ShareGroup := v1Group.Group("/share") v1BatchGroup := v1Group.Group("/batch")
v1ShareGroup.Use() v1BatchGroup.Use()
{ {
v1ShareGroup.POST("/add", v1.PostShareDirAdd)
v1ShareGroup.DELETE("/del/:id", v1.DeleteShareDirDel) v1BatchGroup.DELETE("", v1.DeleteFile) //file/delete
v1ShareGroup.GET("/list", v1.GetShareDirList) v1BatchGroup.DELETE("/:id/task", v1.DeleteOperateFileOrDir)
v1ShareGroup.GET("/info/:id", v1.GetShareDirInfo) v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) //file/operate
v1ShareGroup.PUT("/update/:id", v1.PutShareDirEdit) v1BatchGroup.GET("", v1.GetDownloadFile)
} }
v1TaskGroup := v1Group.Group("/task") v1ImageGroup := v1Group.Group("/image")
v1TaskGroup.Use() v1ImageGroup.Use()
{ {
v1TaskGroup.GET("/list", v1.GetTaskList) v1ImageGroup.GET("", v1.GetFileImage)
v1TaskGroup.PUT("/update", v1.PutTaskUpdate)
v1TaskGroup.POST("/add", v1.PostTaskAdd)
v1TaskGroup.PUT("/completion/:id", v1.PutTaskMarkerCompletion)
} }
v1SambaGroup := v1Group.Group("/samba")
v1PersonGroup := v1Group.Group("/person") v1SambaGroup.Use()
v1PersonGroup.Use()
{ {
v1PersonGroup.GET("/detection", v1.GetPersonDetection) v1ConnectionsGroup := v1SambaGroup.Group("/connections")
v1PersonGroup.GET("/users", v1.GetPersonFriend) v1ConnectionsGroup.Use()
v1PersonGroup.POST("/user/:shareids", v1.PostAddPersonFriend) {
v1PersonGroup.DELETE("/user/:shareid", v1.DeletePersonFriend) v1ConnectionsGroup.GET("", v1.GetSambaConnectionsList)
v1PersonGroup.GET("/directory", v1.GetPersonDirectory) v1ConnectionsGroup.POST("", v1.PostSambaConnectionsCreate)
v1PersonGroup.GET("/file", v1.GetPersonFile) v1ConnectionsGroup.DELETE("/:id", v1.DeleteSambaConnections)
v1PersonGroup.GET("/refile/:uuid", v1.GetPersonReFile) }
v1PersonGroup.PUT("/remarks/:shareid", v1.PutPersonRemarks) v1SharesGroup := v1SambaGroup.Group("/shares")
v1PersonGroup.GET("/list", v1.GetPersonDownloadList) v1SharesGroup.Use()
v1PersonGroup.DELETE("/file/:uuid", v1.DeletePersonDownloadFile) {
v1SharesGroup.GET("", v1.GetSambaSharesList)
v1PersonGroup.POST("/share", v1.PostPersonShare) v1SharesGroup.POST("", v1.PostSambaSharesCreate)
v1PersonGroup.POST("/file/:shareid", v1.PostPersonFile) v1SharesGroup.DELETE("/:id", v1.DeleteSambaShares)
v1PersonGroup.GET("/share", v1.GetPersonShare) v1SharesGroup.GET("/status", v1.GetSambaStatus)
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)
} }
v1AnalyseGroup := v1Group.Group("/analyse") v1NotifyGroup := v1Group.Group("/notify")
v1AnalyseGroup.Use() v1NotifyGroup.Use()
{ {
v1AnalyseGroup.POST("/app", v1.PostAppAnalyse) v1NotifyGroup.POST("/:path", v1.PostNotifyMessage)
//merge to system
v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify)
} }
v1Group.GET("/sync/config", v1.GetSyncConfig)
v1Group.Any("/syncthing/*url", v1.SyncToSyncthing)
} }
return r return r
} }

View File

@@ -1,14 +0,0 @@
package route
import (
"github.com/IceWhaleTech/CasaOS/web"
"github.com/gin-gonic/gin"
"html/template"
)
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
}

View File

@@ -1,38 +0,0 @@
package v1
import (
"net/http"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
)
// @Summary post app analyse
// @Produce application/json
// @Accept multipart/form-data
// @Tags analyse
// @Param name formData string true "app name"
// @Param type formData string true "action" Enums(open,delete)
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /analyse/app [post]
func PostAppAnalyse(c *gin.Context) {
if config.SystemConfigInfo.Analyse == "False" {
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
return
}
name := c.PostForm("name")
t := c.PostForm("type")
language := c.GetHeader("Language")
if len(name) == 0 || len(t) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
service.MyService.Casa().PushAppAnalyse(config.ServerInfo.Token, t, name, language)
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}

View File

@@ -2,13 +2,15 @@ package v1
import ( import (
"encoding/json" "encoding/json"
"fmt"
"io/ioutil" "io/ioutil"
"net/http"
"strconv" "strconv"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port" port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@@ -35,8 +37,15 @@ func AppList(c *gin.Context) {
t := c.DefaultQuery("type", "rank") t := c.DefaultQuery("type", "rank")
categoryId := c.DefaultQuery("category_id", "0") categoryId := c.DefaultQuery("category_id", "0")
key := c.DefaultQuery("key", "") key := c.DefaultQuery("key", "")
language := c.GetHeader("Language") if len(index) == 0 || len(size) == 0 || len(t) == 0 || len(categoryId) == 0 {
recommend, list, community := service.MyService.Casa().GetServerList(index, size, t, categoryId, key, language) c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
collection, err := service.MyService.Casa().GetServerList(index, size, t, categoryId, key)
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
}
// for i := 0; i < len(recommend); i++ { // for i := 0; i < len(recommend); i++ {
// ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion) // ct, _ := service.MyService.Docker().DockerListByImage(recommend[i].Image, recommend[i].ImageVersion)
// if ct != nil { // if ct != nil {
@@ -56,11 +65,11 @@ func AppList(c *gin.Context) {
// } // }
// } // }
data := make(map[string]interface{}, 3) data := make(map[string]interface{}, 3)
data["recommend"] = recommend data["recommend"] = collection.Recommend
data["list"] = list data["list"] = collection.List
data["community"] = community data["community"] = collection.Community
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
} }
// @Summary 获取一个可用端口 // @Summary 获取一个可用端口
@@ -79,7 +88,8 @@ func GetPort(c *gin.Context) {
p, _ = port2.GetAvailablePort(t) p, _ = port2.GetAvailablePort(t)
ok = !port2.IsPortAvailable(p, t) ok = !port2.IsPortAvailable(p, t)
} }
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: p}) // @tiger 这里最好封装成 {'port': ...} 的形式,来体现出参的上下文
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: p})
} }
// @Summary 检查端口是否可用 // @Summary 检查端口是否可用
@@ -94,7 +104,7 @@ func GetPort(c *gin.Context) {
func PortCheck(c *gin.Context) { func PortCheck(c *gin.Context) {
p, _ := strconv.Atoi(c.Param("port")) p, _ := strconv.Atoi(c.Param("port"))
t := c.DefaultQuery("type", "tcp") t := c.DefaultQuery("type", "tcp")
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: port2.IsPortAvailable(p, t)}) c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port2.IsPortAvailable(p, t)})
} }
// @Summary 我的应用列表 // @Summary 我的应用列表
@@ -112,12 +122,11 @@ func MyAppList(c *gin.Context) {
size, _ := strconv.Atoi(c.DefaultQuery("size", "0")) size, _ := strconv.Atoi(c.DefaultQuery("size", "0"))
position, _ := strconv.ParseBool(c.DefaultQuery("position", "true")) position, _ := strconv.ParseBool(c.DefaultQuery("position", "true"))
list, unTranslation := service.MyService.App().GetMyList(index, size, position) list, unTranslation := service.MyService.App().GetMyList(index, size, position)
data := make(map[string]interface{}, 2) data := make(map[string]interface{}, 2)
data["list"] = list data["casaos_apps"] = list
data["local"] = unTranslation data["local_apps"] = unTranslation
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
} }
// @Summary my app hardware usage list // @Summary my app hardware usage list
@@ -129,7 +138,8 @@ func MyAppList(c *gin.Context) {
// @Router /app/usage [get] // @Router /app/usage [get]
func AppUsageList(c *gin.Context) { func AppUsageList(c *gin.Context) {
list := service.MyService.App().GetHardwareUsage() list := service.MyService.App().GetHardwareUsage()
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list}) c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
//c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: nil})
} }
// @Summary 应用详情 // @Summary 应用详情
@@ -144,7 +154,11 @@ func AppInfo(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
language := c.GetHeader("Language") language := c.GetHeader("Language")
info := service.MyService.Casa().GetServerAppInfo(id, "", language) info, err := service.MyService.Casa().GetServerAppInfo(id, "", language)
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
}
if info.NetworkModel != "host" { if info.NetworkModel != "host" {
for i := 0; i < len(info.Ports); i++ { for i := 0; i < len(info.Ports); i++ {
if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) { if p, _ := strconv.Atoi(info.Ports[i].ContainerPort); port2.IsPortAvailable(p, info.Ports[i].Protocol) {
@@ -208,10 +222,10 @@ func AppInfo(c *gin.Context) {
// sort.EnvSort(envOrder).Sort(info.Envs) // sort.EnvSort(envOrder).Sort(info.Envs)
// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap)) // sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
// sort.DevSort(devOrder).Sort(info.Devices) // sort.DevSort(devOrder).Sort(info.Devices)
info.Image += ":" + info.ImageVersion
info.MaxMemory = (service.MyService.System().GetMemInfo()["total"]).(uint64) >> 20
info.MaxMemory = service.MyService.System().GetMemInfo().Total >> 20 c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info})
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
} }
// @Summary 获取远程分类列表 // @Summary 获取远程分类列表
@@ -222,16 +236,20 @@ func AppInfo(c *gin.Context) {
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /app/category [get] // @Router /app/category [get]
func CategoryList(c *gin.Context) { func CategoryList(c *gin.Context) {
list := service.MyService.Casa().GetServerCategoryList() list, err := service.MyService.Casa().GetServerCategoryList()
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
}
var count uint = 0 var count uint = 0
for _, category := range list { for _, category := range list {
count += category.Count count += category.Count
} }
rear := append([]model.ServerCategoryList{}, list[0:]...) rear := append([]model.CategoryList{}, list[0:]...)
list = append(list[:0], model.ServerCategoryList{Count: count, Name: "All", Font: "apps"}) list = append(list[:0], model.CategoryList{Count: count, Name: "All", Font: "apps"})
list = append(list, rear...) list = append(list, rear...)
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list}) c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
} }
// @Summary 分享该应用配置 // @Summary 分享该应用配置
@@ -244,5 +262,56 @@ func CategoryList(c *gin.Context) {
func ShareAppFile(c *gin.Context) { func ShareAppFile(c *gin.Context) {
str, _ := ioutil.ReadAll(c.Request.Body) str, _ := ioutil.ReadAll(c.Request.Body)
content := service.MyService.Casa().ShareAppFile(str) content := service.MyService.Casa().ShareAppFile(str)
c.JSON(http.StatusOK, json.RawMessage(content)) c.JSON(common_err.SUCCESS, json.RawMessage(content))
}
func GetcontainerInfo(c *gin.Context) {
// info, err := service.MyService.Docker().GetDockerInfo()
// 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
// }
daemon := model.DeckerDaemonModel{}
data := make(map[string]interface{}, 1)
data["docker_root_dir"] = ""
if file.Exists("/etc/docker/daemon.json") {
byteResult := file.ReadFullFile("/etc/docker/daemon.json")
err := json.Unmarshal(byteResult, &daemon)
if err != nil {
c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()})
return
}
data["docker_root_dir"] = daemon.Graph
}
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
func PutcontainerInfo(c *gin.Context) {
js := make(map[string]interface{})
err := c.BindJSON(&js)
if err != nil {
c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()})
return
}
dockerRootDir := js["docker_root_dir"].(string)
daemon := model.DeckerDaemonModel{}
if file.Exists("/etc/docker/daemon.json") {
byteResult := file.ReadFullFile("/etc/docker/daemon.json")
err := json.Unmarshal(byteResult, &daemon)
if err != nil {
c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err.Error()})
return
}
}
if !file.Exists(dockerRootDir) {
c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS), Data: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
return
}
daemon.Graph = dockerRootDir
byteMode, _ := json.Marshal(daemon)
file.WriteToPath(byteMode, "/etc/docker", "daemon.json")
fmt.Println(command.ExecResultStr("systemctl daemon-reload"))
fmt.Println(command.ExecResultStr("systemctl restart docker"))
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: js})
} }

View File

@@ -1,174 +0,0 @@
package v1
import (
"fmt"
"github.com/IceWhaleTech/CasaOS/model"
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/forease/gotld"
"github.com/gin-gonic/gin"
"net/http"
"os/exec"
"strconv"
"strings"
)
// @Summary 获取可以设置的ddns列表
// @Produce application/json
// @Accept application/json
// @Tags ddns
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /ddns/getlist [get]
func DDNSGetDomainList(c *gin.Context) {
host, domain, tld := gotld.GetSubdomain("bbb.aaa.liru-05.com.cn", 3)
fmt.Println(strings.Replace(host, "."+domain, "", 1))
fmt.Println(domain)
fmt.Println(tld)
data := make(map[string]interface{}, 2)
t, api := service.MyService.DDNS().GetType("godaddy")
data["godaddy"] = &model.GoDaddyModel{Type: t, ApiHost: api}
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err2.SUCCESS,
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
Data: data,
})
return
}
// @Summary 添加新的ddns按给定模型返回内容
// @Produce application/json
// @Accept multipart/form-data
// @Tags ddns
// @Param type formData string true "类型"
// @Param host formData string true "host"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /ddns/set [post]
func DDNSAddConfig(c *gin.Context) {
t, _ := strconv.Atoi(c.PostForm("type"))
host := c.PostForm("host")
_, domain, _ := gotld.GetSubdomain("host", 3)
sub := strings.ReplaceAll(host, "."+domain, "")
if service.MyService.DDNS().IsExis(t, domain, sub) {
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err2.ERROR,
Message: "Repeat add",
})
return
}
var m model2.DDNSUpdateDBModel
c.Bind(&m)
if err := service.MyService.DDNS().SaveConfig(m); err != nil {
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err2.ERROR,
Message: oasis_err2.GetMsg(oasis_err2.ERROR),
Data: err.Error(),
})
return
}
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err2.SUCCESS,
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
})
}
// @Summary 获取ip,仅做展示使用
// @Produce application/json
// @Accept application/json
// @Tags ddns
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /ddns/ip [get]
func DDNSGetIP(c *gin.Context) {
ipv4, ipv6 := service.MyService.DDNS().GetExternalIP()
var ipjson = make(map[string]string, 2)
ipjson["ipv4"] = ipv4
ipjson["ipv6"] = ipv6
c.JSON(http.StatusOK, &model.Result{
Success: oasis_err2.SUCCESS,
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
Data: ipjson,
})
}
// @Summary 测试网址是否可以ping通
// @Produce application/json
// @Accept application/json
// @Tags ddns
// @Param api_host path int true "api地址"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /ddns/ping/{api_host} [get]
func DDNSPing(c *gin.Context) {
url := c.Param("api_host")
url = strings.ReplaceAll(url, "https://", "")
url = strings.ReplaceAll(url, "http://", "")
cmd := exec.Command("ping", url, "-c", "1", "-W", "5")
err := cmd.Run()
if err != nil {
c.JSON(http.StatusOK, &model.Result{
Success: oasis_err2.ERROR,
Message: err.Error(),
Data: false,
})
} else {
c.JSON(http.StatusOK, &model.Result{
Success: oasis_err2.SUCCESS,
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
Data: true,
})
}
}
// @Summary 获取已设置的列表
// @Produce application/json
// @Accept application/json
// @Tags ddns
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /ddns/list [get]
func DDNSConfigList(c *gin.Context) {
j := service.MyService.DDNS().GetConfigList()
ip4 := ip_helper2.GetExternalIPV4()
ip6 := ip_helper2.GetExternalIPV6()
for i := 0; i < len(*j); i++ {
(*j)[i].IPV6 = ip6
(*j)[i].IPV4 = ip4
cmd := exec.Command("ping", (*j)[i].Host+"."+(*j)[i].Domain, "-c", "1", "-W", "3")
err := cmd.Run()
if err != nil {
(*j)[i].State = false
} else {
(*j)[i].State = true
}
}
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: j})
}
// @Summary 删除ddns
// @Produce application/json
// @Accept application/json
// @Tags ddns
// @Param id path int true "ID"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /ddns/delete/{id} [delete]
func DDNSDelete(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil {
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
isok := service.MyService.DDNS().DeleteConfig(uint(id))
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: isok})
}

View File

@@ -1,497 +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/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"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" {
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: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_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: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_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: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
}
m := service.MyService.Disk().GetDiskInfo(path)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_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 FormatDisk(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: oasis_err.PWD_INVALID, Message: oasis_err.GetMsg(oasis_err.PWD_INVALID)})
return
}
if len(path) == 0 || len(t) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
return
}
if _, ok := diskMap[path]; ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_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: oasis_err.FORMAT_ERROR, Message: oasis_err.GetMsg(oasis_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: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_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: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_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: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_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: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_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 AddPartition(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: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
return
}
if _, ok := diskMap[path]; ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)})
return
}
if !file.CheckNotExist("/DATA/" + name) {
// /mnt/name exist
c.JSON(http.StatusOK, model.Result{Success: oasis_err.NAME_NOT_AVAILABLE, Message: oasis_err.GetMsg(oasis_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: oasis_err.DISK_NEEDS_FORMAT, Message: oasis_err.GetMsg(oasis_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: oasis_err.DISK_NEEDS_FORMAT, Message: oasis_err.GetMsg(oasis_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: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_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: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_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: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
return
}
if pwd != config.UserInfo.PWD {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.PWD_INVALID, Message: oasis_err.GetMsg(oasis_err.PWD_INVALID)})
return
}
if _, ok := diskMap[path]; ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_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: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_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: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_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: oasis_err.ERROR, Message: oasis_err.GetMsg(oasis_err.ERROR), Data: "disk undefind"})
return
}
}
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_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: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
}

View File

@@ -2,9 +2,9 @@ package v1
import ( import (
"bytes" "bytes"
"encoding/json"
json2 "encoding/json" json2 "encoding/json"
"net/http" "net/http"
"os/exec"
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
@@ -14,11 +14,9 @@ import (
"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/docker" "github.com/IceWhaleTech/CasaOS/pkg/docker"
upnp2 "github.com/IceWhaleTech/CasaOS/pkg/upnp" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port" port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/pkg/utils/random" "github.com/IceWhaleTech/CasaOS/pkg/utils/random"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
@@ -29,6 +27,7 @@ import (
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/jinzhu/copier" "github.com/jinzhu/copier"
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
"go.uber.org/zap"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
) )
@@ -39,20 +38,20 @@ var upgrader = websocket.Upgrader{
HandshakeTimeout: time.Duration(time.Second * 5), HandshakeTimeout: time.Duration(time.Second * 5),
} }
//打开docker的terminal // 打开docker的terminal
func DockerTerminal(c *gin.Context) { func DockerTerminal(c *gin.Context) {
col := c.DefaultQuery("cols", "100") col := c.DefaultQuery("cols", "100")
row := c.DefaultQuery("rows", "30") row := c.DefaultQuery("rows", "30")
conn, err := upgrader.Upgrade(c.Writer, c.Request, nil) conn, err := upgrader.Upgrade(c.Writer, c.Request, nil)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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 conn.Close() defer conn.Close()
container := c.Param("id") container := c.Param("id")
hr, err := service.Exec(container, row, col) hr, err := service.Exec(container, row, col)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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
} }
// 关闭I/O流 // 关闭I/O流
@@ -67,14 +66,41 @@ func DockerTerminal(c *gin.Context) {
docker.WsReaderCopy(conn, hr.Conn) docker.WsReaderCopy(conn, hr.Conn)
} }
//打开本机的ssh接口 func PostSshLogin(c *gin.Context) {
func WsSsh(c *gin.Context) { j := make(map[string]string)
wsConn, _ := upgrader.Upgrade(c.Writer, c.Request, nil) c.ShouldBind(&j)
userName := j["username"]
password := j["password"]
port := j["port"]
if userName == "" || password == "" || port == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "Username or password or port is empty"})
return
}
_, err := docker.NewSshClient(userName, password, port)
if err != nil {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Please check if the username and port are correct, and make sure that ssh server is installed."})
loger.Error("connect ssh error", zap.Any("error", err))
return
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
func WsSsh(c *gin.Context) {
_, e := exec.LookPath("ssh")
if e != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "ssh server not found"})
return
}
userName := c.Query("username")
password := c.Query("password")
port := c.Query("port")
wsConn, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
var logBuff = new(bytes.Buffer) var logBuff = new(bytes.Buffer)
quitChan := make(chan bool, 3) quitChan := make(chan bool, 3)
user := "" // user := ""
password := "" // password := ""
var login int = 1 var login int = 1
cols, _ := strconv.Atoi(c.DefaultQuery("cols", "200")) cols, _ := strconv.Atoi(c.DefaultQuery("cols", "200"))
rows, _ := strconv.Atoi(c.DefaultQuery("rows", "32")) rows, _ := strconv.Atoi(c.DefaultQuery("rows", "32"))
@@ -82,14 +108,16 @@ func WsSsh(c *gin.Context) {
for login != 0 { for login != 0 {
var err error var err error
if userName == "" || password == "" || port == "" {
wsConn.WriteMessage(websocket.TextMessage, []byte("login:")) wsConn.WriteMessage(websocket.TextMessage, []byte("username or password or port is empty"))
user = docker.ReceiveWsMsgUser(wsConn, logBuff) }
wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m")) // wsConn.WriteMessage(websocket.TextMessage, []byte("login:"))
wsConn.WriteMessage(websocket.TextMessage, []byte("password:")) // user = docker.ReceiveWsMsgUser(wsConn, logBuff)
password = docker.ReceiveWsMsgPassword(wsConn, logBuff) // wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m")) // wsConn.WriteMessage(websocket.TextMessage, []byte("password:"))
client, err = docker.NewSshClient(user, password) // password = docker.ReceiveWsMsgPassword(wsConn, logBuff)
// wsConn.WriteMessage(websocket.TextMessage, []byte("\r\n\x1b[0m"))
client, err = docker.NewSshClient(userName, password, port)
if err != nil && client == nil { if err != nil && client == nil {
wsConn.WriteMessage(websocket.TextMessage, []byte(err.Error())) wsConn.WriteMessage(websocket.TextMessage, []byte(err.Error()))
@@ -114,25 +142,6 @@ func WsSsh(c *gin.Context) {
} }
//安装进度推送
func SpeedPush(c *gin.Context) {
//token := c.Query("token")
//if len(token) == 0 || token != config.UserInfo.Token {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR_AUTH_TOKEN, Message: oasis_err2.GetMsg(oasis_err2.ERROR_AUTH_TOKEN)})
// return
//}
//ws, _ := upgrader.Upgrade(c.Writer, c.Request, nil)
//defer ws.Close()
//
//for {
// select {
// case msg := <-WSMSG:
// ws.WriteMessage(websocket.TextMessage, []byte(fmt.Sprintln(msg)))
// }
//}
}
// @Summary 安装app(该接口需要post json数据) // @Summary 安装app(该接口需要post json数据)
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
@@ -148,7 +157,7 @@ func SpeedPush(c *gin.Context) {
func InstallApp(c *gin.Context) { func InstallApp(c *gin.Context) {
var appInfo model.ServerAppList var appInfo model.ServerAppList
m := model.CustomizationPostData{} m := model.CustomizationPostData{}
c.BindJSON(&m) c.ShouldBind(&m)
const CUSTOM = "custom" const CUSTOM = "custom"
var dockerImage string var dockerImage string
@@ -158,19 +167,22 @@ func InstallApp(c *gin.Context) {
if len(m.Protocol) == 0 { if len(m.Protocol) == 0 {
m.Protocol = "http" m.Protocol = "http"
} }
if m.Origin != "custom" { m.ContainerName = strings.Replace(m.Label, " ", "_", -1)
oldName := m.Label if m.Origin != CUSTOM {
oldName := m.ContainerName
oldLabel := m.Label
for i := 0; true; i++ { for i := 0; true; i++ {
if i != 0 { if i != 0 {
m.Label = oldName + "-" + strconv.Itoa(i) m.ContainerName = oldName + "-" + strconv.Itoa(i)
m.Label = oldLabel + "-" + strconv.Itoa(i)
} }
if _, err := service.MyService.Docker().DockerListByName(m.Label); err != nil { if _, err := service.MyService.Docker().DockerListByName(m.ContainerName); err != nil {
break break
} }
} }
} else { } else {
if _, err := service.MyService.Docker().DockerListByName(m.Label); err == nil { if _, err := service.MyService.Docker().DockerListByName(m.ContainerName); err == nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR_APP_NAME_EXIST, Message: oasis_err2.GetMsg(oasis_err2.ERROR_APP_NAME_EXIST)}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.ERROR_APP_NAME_EXIST, Message: common_err.GetMsg(common_err.ERROR_APP_NAME_EXIST)})
return return
} }
@@ -178,10 +190,10 @@ func InstallApp(c *gin.Context) {
//check port //check port
if len(m.PortMap) > 0 && m.PortMap != "0" { if len(m.PortMap) > 0 && m.PortMap != "0" {
//c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) //c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
portMap, _ := strconv.Atoi(m.PortMap) portMap, _ := strconv.Atoi(m.PortMap)
if !port2.IsPortAvailable(portMap, "tcp") { if !port2.IsPortAvailable(portMap, "tcp") {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + m.PortMap}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + m.PortMap})
return return
} }
} }
@@ -197,40 +209,39 @@ func InstallApp(c *gin.Context) {
dockerImage = m.Image dockerImage = m.Image
dockerImageVersion = "latest" dockerImageVersion = "latest"
} }
m.Image = dockerImage + ":" + dockerImageVersion
for _, u := range m.Ports { for _, u := range m.Ports {
if u.Protocol == "udp" { if u.Protocol == "udp" {
t, _ := strconv.Atoi(u.CommendPort) t, _ := strconv.Atoi(u.CommendPort)
if !port2.IsPortAvailable(t, "udp") { if !port2.IsPortAvailable(t, "udp") {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
return return
} }
} else if u.Protocol == "tcp" { } else if u.Protocol == "tcp" {
te, _ := strconv.Atoi(u.CommendPort) te, _ := strconv.Atoi(u.CommendPort)
if !port2.IsPortAvailable(te, "tcp") { if !port2.IsPortAvailable(te, "tcp") {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
return return
} }
} else if u.Protocol == "both" { } else if u.Protocol == "both" {
t, _ := strconv.Atoi(u.CommendPort) t, _ := strconv.Atoi(u.CommendPort)
if !port2.IsPortAvailable(t, "udp") { if !port2.IsPortAvailable(t, "udp") {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
return return
} }
te, _ := strconv.Atoi(u.CommendPort) te, _ := strconv.Atoi(u.CommendPort)
if !port2.IsPortAvailable(te, "tcp") { if !port2.IsPortAvailable(te, "tcp") {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
return return
} }
} }
} }
if m.Origin == "custom" { if m.Origin == CUSTOM {
for _, device := range m.Devices { for _, device := range m.Devices {
if file.CheckNotExist(device.Path) { if file.CheckNotExist(device.Path) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DEVICE_NOT_EXIST, Message: device.Path + "," + oasis_err2.GetMsg(oasis_err2.DEVICE_NOT_EXIST)}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DEVICE_NOT_EXIST, Message: device.Path + "," + common_err.GetMsg(common_err.DEVICE_NOT_EXIST)})
return return
} }
@@ -268,7 +279,7 @@ func InstallApp(c *gin.Context) {
// installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10) // installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
// installLog.Id = uuid.NewV4().String() // installLog.Id = uuid.NewV4().String()
// service.MyService.Notify().AddLog(installLog) // service.MyService.Notify().AddLog(installLog)
if m.Origin != "custom" { if m.Origin != CUSTOM {
for _, plugin := range appInfo.Plugins { for _, plugin := range appInfo.Plugins {
if plugin == "mysql" { if plugin == "mysql" {
mid := uuid.NewV4().String() mid := uuid.NewV4().String()
@@ -323,11 +334,11 @@ func InstallApp(c *gin.Context) {
return return
} }
for !service.MyService.Docker().IsExistImage(dockerImage + ":" + dockerImageVersion) { for !service.MyService.Docker().IsExistImage(m.Image) {
time.Sleep(time.Second) time.Sleep(time.Second)
} }
_, err = service.MyService.Docker().DockerContainerCreate(dockerImage+":"+dockerImageVersion, m, appInfo.NetworkModel) _, err = service.MyService.Docker().DockerContainerCreate(m, "")
if err != nil { if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100) //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":80}", 100)
notify := notify.Application{} notify := notify.Application{}
@@ -354,7 +365,7 @@ func InstallApp(c *gin.Context) {
// echo -e "hellow\nworld" >> // echo -e "hellow\nworld" >>
//step启动容器 //step启动容器
err = service.MyService.Docker().DockerContainerStart(m.Label) err = service.MyService.Docker().DockerContainerStart(m.ContainerName)
if err != nil { if err != nil {
//service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100) //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":90}", 100)
notify := notify.Application{} notify := notify.Application{}
@@ -376,55 +387,8 @@ func InstallApp(c *gin.Context) {
// service.MyService.Notify().UpdateLog(installLog) // service.MyService.Notify().UpdateLog(installLog)
} }
if m.Origin != CUSTOM {
//step:enable upnp
if m.EnableUPNP {
upnp, err := upnp2.Gateway()
if err == nil {
for _, p := range m.Ports {
if p.Protocol == "udp" {
upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
upnp.LocalHost = ip_helper2.GetLoclIp()
tComment, _ := strconv.Atoi(p.CommendPort)
upnp.AddPortMapping(tComment, tComment, "UDP")
time.Sleep(time.Millisecond * 200)
} else if p.Protocol == "tcp" {
upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
upnp.LocalHost = ip_helper2.GetLoclIp()
tComment, _ := strconv.Atoi(p.CommendPort)
upnp.AddPortMapping(tComment, tComment, "TCP")
time.Sleep(time.Millisecond * 200)
} else if p.Protocol == "both" {
upnp.CtrlUrl = upnp2.GetCtrlUrl(upnp.GatewayHost, upnp.DeviceDescUrl)
upnp.LocalHost = ip_helper2.GetLoclIp()
tComment, _ := strconv.Atoi(p.CommendPort)
upnp.AddPortMapping(tComment, tComment, "UDP")
time.Sleep(time.Millisecond * 200)
upnp.AddPortMapping(tComment, tComment, "TCP")
time.Sleep(time.Millisecond * 200)
}
}
}
// if err != nil {
// //service.MyService.Redis().Set(id, "{\"id\"\""+id+"\",\"state\":false,\"message\":\""+err.Error()+"\",\"speed\":95}", 100)
// installLog.State = 0
// installLog.Type = types.NOTIFY_TYPE_ERROR
// installLog.Message = err.Error()
// service.MyService.Notify().UpdateLog(installLog)
// } else {
// //service.MyService.Redis().Set(id, "{\"id\":\""+id+"\",\"state\":true,\"message\":\"checking\",\"speed\":95}", 100)
// installLog.Message = "checking"
// service.MyService.Notify().UpdateLog(installLog)
// }
}
}
//step: 启动成功 检查容器状态确认启动成功 //step: 启动成功 检查容器状态确认启动成功
container, err := service.MyService.Docker().DockerContainerInfo(m.Label) container, err := service.MyService.Docker().DockerContainerInfo(m.ContainerName)
if err != nil && container.ContainerJSONBase.State.Running { if err != nil && container.ContainerJSONBase.State.Running {
notify := notify.Application{} notify := notify.Application{}
notify.Icon = m.Icon notify.Icon = m.Icon
@@ -457,7 +421,7 @@ func InstallApp(c *gin.Context) {
}() }()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m.Label}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m.Label})
} }
@@ -478,10 +442,10 @@ func InstallApp(c *gin.Context) {
// // appInfo := service.MyService.App().GetServerAppInfo(appId) // // appInfo := service.MyService.App().GetServerAppInfo(appId)
// //
// m := model.CustomizationPostData{} // m := model.CustomizationPostData{}
// c.BindJSON(&m) // c.ShouldBind(&m)
// //检查端口 // //检查端口
// if len(m.PortMap) == 0 || m.PortMap == "0" { // if len(m.PortMap) == 0 || m.PortMap == "0" {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) // c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return // return
// } // }
// if len(m.Port) == 0 || m.Port == "0" { // if len(m.Port) == 0 || m.Port == "0" {
@@ -490,14 +454,14 @@ func InstallApp(c *gin.Context) {
// //
// portMap, _ := strconv.Atoi(m.PortMap) // portMap, _ := strconv.Atoi(m.PortMap)
// if !port2.IsPortAvailable(portMap, "tcp") { // if !port2.IsPortAvailable(portMap, "tcp") {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + m.PortMap}) // c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + m.PortMap})
// return // return
// } // }
// //
// for _, u := range m.Udp { // for _, u := range m.Udp {
// t, _ := strconv.Atoi(u.CommendPort) // t, _ := strconv.Atoi(u.CommendPort)
// if !port2.IsPortAvailable(t, "udp") { // if !port2.IsPortAvailable(t, "udp") {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort}) // c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + u.CommendPort})
// return // return
// } // }
// } // }
@@ -505,7 +469,7 @@ func InstallApp(c *gin.Context) {
// for _, t := range m.Tcp { // for _, t := range m.Tcp {
// te, _ := strconv.Atoi(t.CommendPort) // te, _ := strconv.Atoi(t.CommendPort)
// if !port2.IsPortAvailable(te, "tcp") { // if !port2.IsPortAvailable(te, "tcp") {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + t.CommendPort}) // c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR, Message: "Duplicate port:" + t.CommendPort})
// return // return
// } // }
// } // }
@@ -522,7 +486,7 @@ func InstallApp(c *gin.Context) {
// //
// err := service.MyService.Docker().DockerPullImage(m.Image) // err := service.MyService.Docker().DockerPullImage(m.Image)
// if err != nil { // if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PULL_IMAGE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PULL_IMAGE_ERROR)}) // c.JSON(http.StatusOK, model.Result{Success: common_err.PULL_IMAGE_ERROR, Message: common_err.GetMsg(common_err.PULL_IMAGE_ERROR)})
// } // }
// //
// id := uuid.NewV4().String() // id := uuid.NewV4().String()
@@ -639,7 +603,7 @@ func InstallApp(c *gin.Context) {
// //
// }() // }()
// //
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: id}) // c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
// //
//} //}
@@ -655,27 +619,27 @@ func UnInstallApp(c *gin.Context) {
appId := c.Param("id") appId := c.Param("id")
if len(appId) == 0 { if len(appId) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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
} }
//info := service.MyService.App().GetUninstallInfo(appId) //info := service.MyService.App().GetUninstallInfo(appId)
info, err := service.MyService.Docker().DockerContainerInfo(appId) info, err := service.MyService.Docker().DockerContainerInfo(appId)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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
} }
//step停止容器 //step停止容器
err = service.MyService.Docker().DockerContainerStop(appId) err = service.MyService.Docker().DockerContainerStop(appId)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.UNINSTALL_APP_ERROR, Message: common_err.GetMsg(common_err.UNINSTALL_APP_ERROR), Data: err.Error()})
return return
} }
err = service.MyService.Docker().DockerContainerRemove(appId, false) err = service.MyService.Docker().DockerContainerRemove(appId, false)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.UNINSTALL_APP_ERROR, Message: oasis_err2.GetMsg(oasis_err2.UNINSTALL_APP_ERROR), Data: err.Error()}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.UNINSTALL_APP_ERROR, Message: common_err.GetMsg(common_err.UNINSTALL_APP_ERROR), Data: err.Error()})
return return
} }
@@ -740,7 +704,7 @@ func UnInstallApp(c *gin.Context) {
notify.Success = true notify.Success = true
notify.Finished = true notify.Finished = true
service.MyService.Notify().SendUninstallAppBySocket(notify) service.MyService.Notify().SendUninstallAppBySocket(notify)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
@@ -755,26 +719,35 @@ func UnInstallApp(c *gin.Context) {
// @Router /app/state/{id} [put] // @Router /app/state/{id} [put]
func ChangAppState(c *gin.Context) { func ChangAppState(c *gin.Context) {
appId := c.Param("id") appId := c.Param("id")
state := c.DefaultPostForm("state", "stop") js := make(map[string]string)
c.ShouldBind(&js)
state := js["state"]
if len(appId) == 0 || len(state) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
var err error var err error
if state == "stop" { if state == "start" {
err = service.MyService.Docker().DockerContainerStop(appId)
} else if state == "start" {
err = service.MyService.Docker().DockerContainerStart(appId) err = service.MyService.Docker().DockerContainerStart(appId)
} else if state == "restart" { } else if state == "restart" {
service.MyService.Docker().DockerContainerStop(appId) service.MyService.Docker().DockerContainerStop(appId)
err = service.MyService.Docker().DockerContainerStart(appId) err = service.MyService.Docker().DockerContainerStart(appId)
} else {
err = service.MyService.Docker().DockerContainerStop(appId)
} }
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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
} }
info, err := service.MyService.App().GetContainerInfo(appId) info, err := service.MyService.App().GetContainerInfo(appId)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info.State})
// @tiger - 用 {'state': ...} 来体现出参上下文
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info.State})
} }
// @Summary 查看容器日志 // @Summary 查看容器日志
@@ -788,7 +761,7 @@ func ChangAppState(c *gin.Context) {
func ContainerLog(c *gin.Context) { func ContainerLog(c *gin.Context) {
appId := c.Param("id") appId := c.Param("id")
log, _ := service.MyService.Docker().DockerContainerLog(appId) log, _ := service.MyService.Docker().DockerContainerLog(appId)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: log}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(log)})
} }
// @Summary 获取容器状态 // @Summary 获取容器状态
@@ -802,10 +775,10 @@ func ContainerLog(c *gin.Context) {
// @Router /app/state/{id} [get] // @Router /app/state/{id} [get]
func GetContainerState(c *gin.Context) { func GetContainerState(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
t := c.DefaultQuery("type", "0") //t := c.DefaultQuery("type", "0")
containerInfo, e := service.MyService.App().GetSimpleContainerInfo(id) containerInfo, e := service.MyService.App().GetSimpleContainerInfo(id)
if e != nil { if e != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: e.Error()}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: e.Error()})
return return
} }
@@ -813,12 +786,12 @@ func GetContainerState(c *gin.Context) {
data["state"] = containerInfo.State data["state"] = containerInfo.State
if t == "1" { // if t == "1" {
appInfo := service.MyService.App().GetAppDBInfo(id) // appInfo := service.MyService.App().GetAppDBInfo(id)
data["app"] = appInfo // data["app"] = appInfo
} // }
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
} }
// @Summary 更新设置 // @Summary 更新设置
@@ -838,10 +811,10 @@ func UpdateSetting(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
const CUSTOM = "custom" const CUSTOM = "custom"
m := model.CustomizationPostData{} m := model.CustomizationPostData{}
c.BindJSON(&m) c.ShouldBind(&m)
if len(id) == 0 { if len(id) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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
} }
//var cpd model.CustomizationPostData //var cpd model.CustomizationPostData
@@ -853,15 +826,14 @@ func UpdateSetting(c *gin.Context) {
// //check app name is exist // //check app name is exist
// if _, err := service.MyService.Docker().DockerListByName(m.Label); err == nil { // if _, err := service.MyService.Docker().DockerListByName(m.Label); err == nil {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR_APP_NAME_EXIST, Message: oasis_err2.GetMsg(oasis_err2.ERROR_APP_NAME_EXIST)}) // c.JSON(http.StatusOK, model.Result{Success: common_err.ERROR_APP_NAME_EXIST, Message: common_err.GetMsg(common_err.ERROR_APP_NAME_EXIST)})
// return // return
// } // }
service.MyService.Docker().DockerContainerStop(id) service.MyService.Docker().DockerContainerStop(id)
portMap, _ := strconv.Atoi(m.PortMap) portMap, _ := strconv.Atoi(m.PortMap)
if !port2.IsPortAvailable(portMap, "tcp") { if !port2.IsPortAvailable(portMap, "tcp") {
service.MyService.Docker().DockerContainerStart(id) service.MyService.Docker().DockerContainerStart(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + m.PortMap}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + m.PortMap})
return return
} }
@@ -871,28 +843,28 @@ func UpdateSetting(c *gin.Context) {
t, _ := strconv.Atoi(u.CommendPort) t, _ := strconv.Atoi(u.CommendPort)
if !port2.IsPortAvailable(t, "udp") { if !port2.IsPortAvailable(t, "udp") {
service.MyService.Docker().DockerContainerStart(id) service.MyService.Docker().DockerContainerStart(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
return return
} }
} else if u.Protocol == "tcp" { } else if u.Protocol == "tcp" {
te, _ := strconv.Atoi(u.CommendPort) te, _ := strconv.Atoi(u.CommendPort)
if !port2.IsPortAvailable(te, "tcp") { if !port2.IsPortAvailable(te, "tcp") {
service.MyService.Docker().DockerContainerStart(id) service.MyService.Docker().DockerContainerStart(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
return return
} }
} else if u.Protocol == "both" { } else if u.Protocol == "both" {
t, _ := strconv.Atoi(u.CommendPort) t, _ := strconv.Atoi(u.CommendPort)
if !port2.IsPortAvailable(t, "udp") { if !port2.IsPortAvailable(t, "udp") {
service.MyService.Docker().DockerContainerStart(id) service.MyService.Docker().DockerContainerStart(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
return return
} }
te, _ := strconv.Atoi(u.CommendPort) te, _ := strconv.Atoi(u.CommendPort)
if !port2.IsPortAvailable(te, "tcp") { if !port2.IsPortAvailable(te, "tcp") {
service.MyService.Docker().DockerContainerStart(id) service.MyService.Docker().DockerContainerStart(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: "Duplicate port:" + u.CommendPort}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: "Duplicate port:" + u.CommendPort})
return return
} }
} }
@@ -901,11 +873,11 @@ func UpdateSetting(c *gin.Context) {
service.MyService.Docker().DockerContainerUpdateName(id, id) service.MyService.Docker().DockerContainerUpdateName(id, id)
//service.MyService.Docker().DockerContainerRemove(id, true) //service.MyService.Docker().DockerContainerRemove(id, true)
containerId, err := service.MyService.Docker().DockerContainerCreate(m.Image, m, m.NetworkModel) containerId, err := service.MyService.Docker().DockerContainerCreate(m, id)
if err != nil { if err != nil {
service.MyService.Docker().DockerContainerUpdateName(m.Label, id) service.MyService.Docker().DockerContainerUpdateName(m.ContainerName, id)
service.MyService.Docker().DockerContainerStart(id) service.MyService.Docker().DockerContainerStart(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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
} }
// echo -e "hellow\nworld" >> // echo -e "hellow\nworld" >>
@@ -914,7 +886,7 @@ func UpdateSetting(c *gin.Context) {
err = service.MyService.Docker().DockerContainerStart(containerId) err = service.MyService.Docker().DockerContainerStart(containerId)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
return return
} }
service.MyService.Docker().DockerContainerRemove(id, true) service.MyService.Docker().DockerContainerRemove(id, true)
@@ -985,7 +957,7 @@ func UpdateSetting(c *gin.Context) {
//service.MyService.App().UpdateApp(appInfo) //service.MyService.App().UpdateApp(appInfo)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary update app version // @Summary update app version
@@ -1000,20 +972,20 @@ func PutAppUpdate(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
if len(id) == 0 { if len(id) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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
} }
inspect, err := service.MyService.Docker().DockerContainerInfo(id) inspect, err := service.MyService.Docker().DockerContainerInfo(id)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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
} }
imageLatest := strings.Split(inspect.Config.Image, ":")[0] + ":latest" imageLatest := strings.Split(inspect.Config.Image, ":")[0] + ":latest"
err = service.MyService.Docker().DockerPullImage(imageLatest, "", "") err = service.MyService.Docker().DockerPullImage(imageLatest, "", "")
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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
} }
@@ -1026,7 +998,7 @@ func PutAppUpdate(c *gin.Context) {
if err != nil { if err != nil {
service.MyService.Docker().DockerContainerUpdateName(inspect.Name, id) service.MyService.Docker().DockerContainerUpdateName(inspect.Name, id)
service.MyService.Docker().DockerContainerStart(id) service.MyService.Docker().DockerContainerStart(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
return return
} }
@@ -1034,43 +1006,13 @@ func PutAppUpdate(c *gin.Context) {
err = service.MyService.Docker().DockerContainerStart(containerId) err = service.MyService.Docker().DockerContainerStart(containerId)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
return return
} }
service.MyService.Docker().DockerContainerRemove(id, true) service.MyService.Docker().DockerContainerRemove(id, true)
delete(service.NewVersionApp, id) delete(service.NewVersionApp, id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
// @Summary get app index
// @Produce application/json
// @Accept application/json
// @Tags app
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /app/order [get]
func GetAppOrder(c *gin.Context) {
data := service.MyService.System().GetAppOrderFile()
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: json.RawMessage(data)})
}
// @Summary update app index
// @Produce application/json
// @Accept application/json
// @Tags app
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /app/order [post]
func PostAppOrder(c *gin.Context) {
data := c.PostForm("data")
service.MyService.System().UpAppOrderFile(data)
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
Data: json.RawMessage(data),
})
} }
// @Summary 获取容器详情 // @Summary 获取容器详情
@@ -1083,10 +1025,12 @@ func PostAppOrder(c *gin.Context) {
// @Router /app/info/{id} [get] // @Router /app/info/{id} [get]
func ContainerInfo(c *gin.Context) { func ContainerInfo(c *gin.Context) {
appId := c.Param("id") appId := c.Param("id")
// @tiger - 作为最佳实践,不应该直接把数据库的信息返回,来避免未来数据库结构上的迭代带来的新字段
appInfo := service.MyService.App().GetAppDBInfo(appId) appInfo := service.MyService.App().GetAppDBInfo(appId)
containerInfo, _ := service.MyService.Docker().DockerContainerStats(appId) containerInfo, _ := service.MyService.Docker().DockerContainerStats(appId)
var cpuModel = "arm" var cpuModel = "arm"
if cpu := service.MyService.ZiMa().GetCpuInfo(); len(cpu) > 0 { if cpu := service.MyService.System().GetCpuInfo(); len(cpu) > 0 {
if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "intel") > 0 { if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "intel") > 0 {
cpuModel = "intel" cpuModel = "intel"
} else if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "amd") > 0 { } else if strings.Count(strings.ToLower(strings.TrimSpace(cpu[0].ModelName)), "amd") > 0 {
@@ -1097,44 +1041,34 @@ func ContainerInfo(c *gin.Context) {
info, err := service.MyService.Docker().DockerContainerInfo(appId) info, err := service.MyService.Docker().DockerContainerInfo(appId)
if err != nil { if err != nil {
//todo 需要自定义错误 //todo 需要自定义错误
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), 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
} }
con := struct { con := struct {
Status string `json:"status"` Status string `json:"status"`
StartedAt string `json:"started_at"` StartedAt string `json:"started_at"`
CPUShares int64 `json:"cpu_shares"` CPUShares int64 `json:"cpu_shares"`
Memory int64 `json:"memory"` Memory int64 `json:"total_memory"` // @tiger - 改成 total_memory方便以后增加 free_memory 之类的字段
Restart string `json:"restart"` Restart string `json:"restart_policy"` // @tiger - 改成 restart_policy?
}{Status: info.State.Status, StartedAt: info.State.StartedAt, CPUShares: info.HostConfig.CPUShares, Memory: info.HostConfig.Memory >> 20, Restart: info.HostConfig.RestartPolicy.Name} }{Status: info.State.Status, StartedAt: info.State.StartedAt, CPUShares: info.HostConfig.CPUShares, Memory: info.HostConfig.Memory >> 20, Restart: info.HostConfig.RestartPolicy.Name}
data := make(map[string]interface{}, 5) data := make(map[string]interface{}, 5)
data["app"] = appInfo data["app"] = appInfo // @tiget - 最佳实践是,返回 appid然后具体的 app 信息由前端另行获取
data["cpu"] = cpuModel data["cpu"] = cpuModel // @tiger - 改成 arch
data["memory"] = service.MyService.System().GetMemInfo().Total data["memory"] = service.MyService.System().GetMemInfo()["total"] // @tiger - 改成 total_memory方便以后增加 free_memory 之类的字段
data["container"] = json2.RawMessage(containerInfo) data["container"] = json2.RawMessage(containerInfo)
data["info"] = con data["info"] = con
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
} }
// @Summary 获取安装所需要的数据 func GetDockerNetworks(c *gin.Context) {
// @Produce application/json
// @Accept application/json
// @Tags app
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /app/install/config [get]
func GetDockerInstallConfig(c *gin.Context) {
networks := service.MyService.Docker().DockerNetworkModelList() networks := service.MyService.Docker().DockerNetworkModelList()
data := make(map[string]interface{}, 2)
list := []map[string]string{} list := []map[string]string{}
for _, network := range networks { for _, network := range networks {
if network.Driver != "null" { if network.Driver != "null" {
list = append(list, map[string]string{"name": network.Name, "driver": network.Driver, "id": network.ID}) list = append(list, map[string]string{"name": network.Name, "driver": network.Driver, "id": network.ID})
} }
} }
data["networks"] = list c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
data["memory"] = service.MyService.System().GetMemInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
} }
// @Summary 获取依赖数据 // @Summary 获取依赖数据
@@ -1148,10 +1082,9 @@ func GetDockerInstallConfig(c *gin.Context) {
func ContainerRelyInfo(c *gin.Context) { func ContainerRelyInfo(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
appInfo := service.MyService.Rely().GetInfo(id) appInfo := service.MyService.Rely().GetInfo(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: appInfo}) c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: appInfo})
} }
// @Summary 获取可更新数据
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags app // @Tags app
@@ -1165,7 +1098,7 @@ func ContainerUpdateInfo(c *gin.Context) {
info, err := service.MyService.Docker().DockerContainerInfo(appId) info, err := service.MyService.Docker().DockerContainerInfo(appId)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: err.Error()}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: err.Error()})
return return
} }
var port model.PortArray var port model.PortArray
@@ -1187,13 +1120,13 @@ func ContainerUpdateInfo(c *gin.Context) {
showENV := info.Config.Labels["show_env"] showENV := info.Config.Labels["show_env"]
showENVList := strings.Split(showENV, ",") showENVList := strings.Split(showENV, ",")
showENVMap := make(map[string]string) showENVMap := make(map[string]string)
if len(showENVList) > 1 { if len(showENVList) > 0 && showENVList[0] != "" {
for _, name := range showENVList { for _, name := range showENVList {
showENVMap[name] = "1" showENVMap[name] = "1"
} }
} }
for _, v := range info.Config.Env { for _, v := range info.Config.Env {
if len(showENVList) > 1 { if len(showENVList) > 0 {
if _, ok := showENVMap[strings.Split(v, "=")[0]]; ok { if _, ok := showENVMap[strings.Split(v, "=")[0]]; ok {
temp := model.Env{ temp := model.Env{
Name: strings.Split(v, "=")[0], Name: strings.Split(v, "=")[0],
@@ -1243,7 +1176,7 @@ func ContainerUpdateInfo(c *gin.Context) {
} }
m.NetworkModel = string(info.HostConfig.NetworkMode) m.NetworkModel = string(info.HostConfig.NetworkMode)
m.Description = info.Config.Labels["desc"] m.Description = info.Config.Labels["desc"]
m.Label = strings.ReplaceAll(info.Name, "/", "") m.ContainerName = strings.ReplaceAll(info.Name, "/", "")
m.PortMap = info.Config.Labels["web"] m.PortMap = info.Config.Labels["web"]
m.Devices = driver m.Devices = driver
m.Envs = envs m.Envs = envs
@@ -1263,13 +1196,18 @@ func ContainerUpdateInfo(c *gin.Context) {
m.Cmd = info.Config.Cmd m.Cmd = info.Config.Cmd
m.HostName = info.Config.Hostname m.HostName = info.Config.Hostname
m.Privileged = info.HostConfig.Privileged m.Privileged = info.HostConfig.Privileged
name := info.Config.Labels["name"]
if len(name) == 0 {
name = strings.ReplaceAll(info.Name, "/", "")
}
m.Label = name
m.Protocol = info.Config.Labels["protocol"] m.Protocol = info.Config.Labels["protocol"]
if m.Protocol == "" { if m.Protocol == "" {
m.Protocol = "http" m.Protocol = "http"
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: m}) c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
} }
////准备安装(暂时不需要) ////准备安装(暂时不需要)
@@ -1320,5 +1258,5 @@ func ContainerUpdateInfo(c *gin.Context) {
// } // }
// data["udp"] = inarr // data["udp"] = inarr
// } // }
// c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data}) // c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
//} //}

View File

@@ -1,8 +1,6 @@
package v1 package v1
import ( import (
"bufio"
"encoding/csv"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
@@ -18,41 +16,13 @@ import (
"sync" "sync"
"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/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"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"
) )
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
@@ -64,35 +34,34 @@ 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: oasis_err2.INVALID_PARAMS, Success: common_err.INVALID_PARAMS,
Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.FILE_DOES_NOT_EXIST, Success: common_err.FILE_DOES_NOT_EXIST,
Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.FILE_READ_ERROR, Success: common_err.FILE_READ_ERROR,
Message: oasis_err2.GetMsg(oasis_err2.FILE_READ_ERROR), Message: common_err.GetMsg(common_err.FILE_READ_ERROR),
Data: err.Error(), Data: err.Error(),
}) })
return return
} }
result := string(info) result := string(info)
//返回结果 c.JSON(common_err.SUCCESS, model.Result{
c.JSON(http.StatusOK, model.Result{ Success: common_err.SUCCESS,
Success: oasis_err2.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS),
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
Data: result, Data: result,
}) })
} }
@@ -101,15 +70,15 @@ func GetLocalFile(c *gin.Context) {
path := c.Query("path") path := c.Query("path")
if len(path) == 0 { if len(path) == 0 {
c.JSON(http.StatusOK, model.Result{ c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.INVALID_PARAMS, Success: common_err.INVALID_PARAMS,
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS), Message: common_err.GetMsg(common_err.INVALID_PARAMS),
}) })
return return
} }
if !file.Exists(path) { if !file.Exists(path) {
c.JSON(http.StatusOK, model.Result{ c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.FILE_DOES_NOT_EXIST, Success: common_err.FILE_DOES_NOT_EXIST,
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST), Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
}) })
return return
} }
@@ -122,29 +91,29 @@ 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("t") t := c.Query("format")
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: oasis_err2.INVALID_PARAMS, Success: common_err.INVALID_PARAMS,
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS), Message: common_err.GetMsg(common_err.INVALID_PARAMS),
}) })
return return
} }
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: oasis_err2.FILE_DOES_NOT_EXIST, Success: common_err.FILE_DOES_NOT_EXIST,
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST), Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
}) })
return return
} }
@@ -159,8 +128,8 @@ func GetDownloadFile(c *gin.Context) {
info, err := os.Stat(filePath) info, err := os.Stat(filePath)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{ c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.FILE_DOES_NOT_EXIST, Success: common_err.FILE_DOES_NOT_EXIST,
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST), Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
}) })
return return
} }
@@ -180,18 +149,18 @@ 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: oasis_err2.INVALID_PARAMS, Success: common_err.INVALID_PARAMS,
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS), Message: common_err.GetMsg(common_err.INVALID_PARAMS),
}) })
return return
} }
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: oasis_err.ERROR, Success: common_err.SERVICE_ERROR,
Message: oasis_err2.GetMsg(oasis_err2.ERROR), Message: common_err.GetMsg(common_err.SERVICE_ERROR),
Data: err.Error(), Data: err.Error(),
}) })
return return
@@ -214,8 +183,22 @@ func GetDownloadFile(c *gin.Context) {
} }
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)
@@ -234,7 +217,12 @@ func GetDownloadSingleFile(c *gin.Context) {
// @Router /file/dirpath [get] // @Router /file/dirpath [get]
func DirPath(c *gin.Context) { func DirPath(c *gin.Context) {
path := c.DefaultQuery("path", "") path := c.DefaultQuery("path", "")
info := service.MyService.ZiMa().GetDirPath(path) info := service.MyService.System().GetDirPath(path)
shares := service.MyService.Shares().GetSharesList()
sharesMap := make(map[string]string)
for _, v := range shares {
sharesMap[v.Path] = fmt.Sprint(v.ID)
}
if path == "/DATA/AppData" { if path == "/DATA/AppData" {
list := service.MyService.Docker().DockerContainerList() list := service.MyService.Docker().DockerContainerList()
apps := make(map[string]string, len(list)) apps := make(map[string]string, len(list))
@@ -247,34 +235,19 @@ func DirPath(c *gin.Context) {
info[i].Type = "application" 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
}
}
} }
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 //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 {
@@ -293,12 +266,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: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.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
@@ -312,15 +288,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: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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.ZiMa().RenameFile(op, np) success, err := service.MyService.System().RenameFile(op, np)
c.JSON(http.StatusOK, model.Result{Success: success, Message: oasis_err2.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
@@ -333,20 +309,20 @@ 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: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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)
// if err != nil { // if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) // c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return // return
// } // }
code, _ = service.MyService.ZiMa().MkdirAll(path) code, _ = service.MyService.System().MkdirAll(path)
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)}) c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
} }
// @Summary create file // @Summary create file
@@ -359,20 +335,20 @@ 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: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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)
// if err != nil { // if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) // c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return // return
// } // }
code, _ = service.MyService.ZiMa().CreateFile(path) code, _ = service.MyService.System().CreateFile(path)
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)}) c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
} }
// @Summary upload file // @Summary upload file
@@ -393,7 +369,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.RootPath + "/temp/" + hash + strconv.Itoa(totalChunks) + "/" tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
if fileName != relative { if fileName != relative {
dirPath = strings.TrimSuffix(relative, fileName) dirPath = strings.TrimSuffix(relative, fileName)
tempDir += dirPath tempDir += dirPath
@@ -401,11 +377,11 @@ func GetFileUpload(c *gin.Context) {
} }
tempDir += chunkNumber tempDir += chunkNumber
if !file.CheckNotExist(tempDir) { if !file.CheckNotExist(tempDir) {
c.JSON(200, model.Result{Success: 200, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)}) c.JSON(200, model.Result{Success: 200, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
return return
} }
c.JSON(204, model.Result{Success: 204, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(204, model.Result{Success: 204, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary upload file // @Summary upload file
@@ -429,10 +405,10 @@ 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(oasis_err2.INVALID_PARAMS, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) c.JSON(common_err.INVALID_PARAMS, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return return
} }
tempDir := config.AppInfo.RootPath + "/temp/" + hash + strconv.Itoa(totalChunks) + "/" tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
if fileName != relative { if fileName != relative {
dirPath = strings.TrimSuffix(relative, fileName) dirPath = strings.TrimSuffix(relative, fileName)
@@ -453,7 +429,7 @@ func PostFileUpload(c *gin.Context) {
defer out.Close() defer out.Close()
_, err := io.Copy(out, f) _, err := io.Copy(out, f)
if err != nil { if err != nil {
c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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
} }
} else { } else {
@@ -461,15 +437,15 @@ func PostFileUpload(c *gin.Context) {
defer out.Close() defer out.Close()
_, err := io.Copy(out, f) _, err := io.Copy(out, f)
if err != nil { if err != nil {
c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
return return
} }
fileNum, err := ioutil.ReadDir(tempDir) fileNum, err := ioutil.ReadDir(tempDir)
if err != nil { if err != nil {
c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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
} }
if totalChunks == len(fileNum) { if totalChunks == len(fileNum) {
@@ -477,7 +453,7 @@ func PostFileUpload(c *gin.Context) {
file.RMDir(tempDir) file.RMDir(tempDir)
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary copy or move file // @Summary copy or move file
@@ -491,14 +467,14 @@ func PostFileUpload(c *gin.Context) {
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: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.SOURCE_DES_SAME, Message: oasis_err2.GetMsg(oasis_err2.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
} }
@@ -519,7 +495,6 @@ func PostOperateFileOrDir(c *gin.Context) {
uid := uuid.NewV4().String() uid := uuid.NewV4().String()
service.FileQueue.Store(uid, list) service.FileQueue.Store(uid, list)
service.OpStrArr = append(service.OpStrArr, uid) service.OpStrArr = append(service.OpStrArr, uid)
if len(service.OpStrArr) == 1 { if len(service.OpStrArr) == 1 {
go service.ExecOpFile() go service.ExecOpFile()
go service.CheckFileStatus() go service.CheckFileStatus()
@@ -528,7 +503,7 @@ func PostOperateFileOrDir(c *gin.Context) {
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.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
@@ -542,9 +517,9 @@ func PostOperateFileOrDir(c *gin.Context) {
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: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.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")
@@ -554,12 +529,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: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.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
@@ -574,26 +549,26 @@ func DeleteFile(c *gin.Context) {
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: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.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
@@ -609,13 +584,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: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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))
@@ -623,13 +598,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: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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))
@@ -654,5 +629,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: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }

View File

@@ -1,5 +0,0 @@
package v1
func aaa() {
}

Some files were not shown because too many files have changed in this diff Show More