Compare commits

...

71 Commits

Author SHA1 Message Date
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
link
94d0efdb12 Dev (#285)
* 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
2022-06-13 20:43:19 +08:00
link
1e821d1c10 Dev (#277)
* 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
2022-06-10 15:32:27 +08:00
link
2c80b53ee8 Dev (#276)
* 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
2022-06-10 15:16:56 +08:00
link
c33af66c6e Dev (#275)
* 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
2022-06-10 14:47:50 +08:00
link
9d47874ae3 Dev (#274)
* 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
2022-06-10 13:33:53 +08:00
link
c7b7a30210 Dev (#264)
* 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
2022-06-08 19:44:05 +08:00
link
fde665cd4d Dev (#263)
* 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
2022-06-08 19:32:05 +08:00
link
eaf2341a2a Dev (#262)
* 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
2022-06-08 19:31:01 +08:00
link
d4bed3e5c7 Dev (#261)
* 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
2022-06-08 18:19:45 +08:00
Tiger Wang (王豫)
fcb2b3f5a5 Create config.yml 2022-06-02 20:30:00 -04:00
link
60349c941a Update demo.yml 2022-05-18 16:59:43 +08:00
link
11bc70a710 Update demo.yml 2022-05-18 16:58:33 +08:00
link
665766019f Update demo.yml 2022-05-18 16:39:59 +08:00
link
57cef9624c Dev (#199)
* fix bug

* updata UI
2022-05-17 16:31:23 +08:00
409 changed files with 10239 additions and 31148 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!

5
.github/ISSUE_TEMPLATE/config.yml vendored Normal file
View File

@@ -0,0 +1,5 @@
blank_issues_enabled: false
contact_links:
- name: Questions, Ideas, Discussions
url: https://github.com/IceWhaleTech/CasaOS/discussions
about: Ask questions, propose ideas, or discuss anything related to CasaOS

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-[0-9]' | 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
@@ -43,7 +43,7 @@ jobs:
--instance-snapshot-name ${{ env.OLD_INSTANCE_SNAPSHOT_NAME }} \ --instance-snapshot-name ${{ env.OLD_INSTANCE_SNAPSHOT_NAME }} \
--instance-names ${{ env.NEW_INSTANCE_NAME }} \ --instance-names ${{ env.NEW_INSTANCE_NAME }} \
--availability-zone us-west-2a \ --availability-zone us-west-2a \
--bundle-id large_2_0 --bundle-id medium_2_0
- name: Wait for new instance running - name: Wait for new instance running
run: | run: |

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

3
.gitignore vendored
View File

@@ -29,7 +29,10 @@ gen
/out/ /out/
/db/ /db/
/docs/ /docs/
/web/
/conf/conf.ini /conf/conf.ini
/conf/conf.conf
/conf/conf.json
__debug_bin __debug_bin
main main
CasaOS CasaOS

View File

@@ -11,12 +11,90 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
### Changed ### Changed
### Removed ### Removed
### Security ### Security
### Fixed ### Fixed
## [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
### 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.([#196](https://github.com/IceWhaleTech/CasaOS/issues/196))
- [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))
- [Language] Update language pack [zarevskaya](https://github.com/zarevskaya) [patrickhilker](https://github.com/patrickhilker)
- [System] Interface path adjustment
### Removed
- [Files] Remove the online preview function of PDF files
### 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))
- [System] Fixed the problem of wireless network card traffic display.([#222](https://github.com/IceWhaleTech/CasaOS/issues/222))
## [0.3.1.1] - 2022-05-17 ## [0.3.1.1] - 2022-05-17
### Fixed ### Fixed

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>

2
UI

Submodule UI updated: 70d9529d06...bca27426e1

41
alpha.md Normal file
View File

@@ -0,0 +1,41 @@
<!--
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-06-27 11:37:26
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-21 18:12:31
* @FilePath: /CasaOS/alpha.md
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
-->
# alpha Test Description
## :warning: Warning
There is a risk of data loss in non-release versions, so please be careful to back up your data.
## Install/Update
``` curl -fsSL https://get.casaos.io | bash -s -- -v v0.3.4-alpha ```
## Check change log
[CHANGELOG](https://github.com/IceWhaleTech/CasaOS/blob/main/CHANGELOG.md)
## Check Design drawings
[Design drawings](https://www.figma.com/file/pvlGobvuWEvbCb3GLqXfim/CasaOS-V0.3.3)
## Feedback questions
Go [here]() to give feedback on your question, note that try to match the picture or video
## Retest after update
Wait for the fix to appear and update and retest, and follow up on the issue
## Thanks
Thank you for your great support, we will return your support from time to time.

24
conf/conf.conf.sample Normal file
View File

@@ -0,0 +1,24 @@
[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
TempPath = /var/lib/casaos/temp
[server]
HttpPort = 80
RunMode = release
ServerApi = https://api.casaos.io/casaos-api
Handshake = socket.casaos.io
Token =
USBAutoMount =
[system]

View File

@@ -1,42 +0,0 @@
[app]
PAGE_SIZE = 10
RuntimeRootPath = runtime/
LogSavePath = /casaOS/logs/server/
LogSaveName = log
LogFileExt = log
DateStrFormat = 20060102
DateTimeFormat = 2006-01-02 15:04:05
TimeFormat = 15:04:05
DateFormat = 2006-01-02
ProjectPath = /casaOS/server
RootPath = /casaOS
[server]
HttpPort = 8089
UDPPort =
RunMode = release
ServerApi = https://api.casaos.io/casaos-api
Handshake = socket.casaos.io
Token =
USBAutoMount =
[user]
UserName =
PWD =
Email = user@gmail.com
Description = description
Initialized = false
Avatar =
NickName =
PublicKey =
[system]
ConfigStr =
WidgetList =
Analyse =
[file]
ShareDir =
DownloadDir =

18
go.mod
View File

@@ -7,6 +7,9 @@ require (
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/Microsoft/hcsshim v0.8.22 // indirect
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 // indirect
github.com/ambelovsky/go-structs v1.1.0 // indirect
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect
github.com/bits-and-blooms/bitset v1.2.1 // indirect github.com/bits-and-blooms/bitset v1.2.1 // indirect
github.com/containerd/containerd v1.5.7 github.com/containerd/containerd v1.5.7
github.com/containerd/continuity v0.2.0 // indirect github.com/containerd/continuity v0.2.0 // indirect
@@ -16,36 +19,35 @@ require (
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.2 github.com/gin-contrib/gzip v0.0.2
github.com/gin-gonic/gin v1.7.2 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/go-ole/go-ole v1.2.5 // indirect
github.com/go-openapi/spec v0.20.4 // indirect
github.com/go-playground/validator/v10 v10.6.1 // indirect github.com/go-playground/validator/v10 v10.6.1 // indirect
github.com/gogo/googleapis v1.4.1 // indirect github.com/gogo/googleapis v1.4.1 // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible github.com/golang-jwt/jwt/v4 v4.4.1
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect 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/google/uuid v1.3.0 // indirect
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/jinzhu/copier v0.3.2 github.com/jinzhu/copier v0.3.2
github.com/json-iterator/go v1.1.11 // indirect github.com/json-iterator/go v1.1.11 // indirect
github.com/klauspost/compress v1.13.6 // indirect github.com/klauspost/compress v1.13.6 // indirect
github.com/kr/text v0.2.0 // indirect
github.com/leodido/go-urn v1.2.1 // 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-isatty v0.0.14 // indirect
github.com/mattn/go-sqlite3 v1.14.11 // indirect github.com/mattn/go-sqlite3 v1.14.11 // indirect
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/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/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
@@ -53,19 +55,18 @@ require (
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/spf13/afero v1.2.2
github.com/swaggo/gin-swagger v1.3.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 github.com/tklauser/go-sysconf v0.3.6 // indirect
github.com/ugorji/go v1.2.6 // indirect github.com/ugorji/go v1.2.6 // indirect
go.opencensus.io v0.23.0 // indirect 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/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/net v0.0.0-20211020060615-d418f374d309 // indirect
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
golang.org/x/sys v0.0.0-20211020174200-9d6173849985 // indirect golang.org/x/sys v0.0.0-20211020174200-9d6173849985 // indirect
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
golang.org/x/text v0.3.7 // 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/appengine v1.6.7 // indirect
@@ -73,6 +74,7 @@ require (
google.golang.org/grpc v1.41.0 // indirect google.golang.org/grpc v1.41.0 // indirect
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
gopkg.in/ini.v1 v1.62.0 // indirect gopkg.in/ini.v1 v1.62.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.0.0
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b // indirect 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

112
go.sum
View File

@@ -54,12 +54,11 @@ github.com/Azure/go-autorest/autorest/mocks v0.4.0/go.mod h1:LTp+uSrOhSkaKrUy935
github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k= github.com/Azure/go-autorest/autorest/mocks v0.4.1/go.mod h1:LTp+uSrOhSkaKrUy935gNZuuIPPVsHlr9DSOxSayd+k=
github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8= github.com/Azure/go-autorest/logger v0.2.0/go.mod h1:T9E3cAhj2VqvPOtCYAvby9aBXkZmbF5NWuPV8+WeEW8=
github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU= github.com/Azure/go-autorest/tracing v0.6.0/go.mod h1:+vhtPC754Xsa23ID7GlGsrdKBpUA79WCAKPPZVC2DeU=
github.com/BurntSushi/toml v0.3.1 h1:WXkYYl6Yr3qBf1K79EBnL4mak0OimBfB0XUf9Vl28OQ=
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU= github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo= github.com/BurntSushi/xgb v0.0.0-20160522181843-27f122750802/go.mod h1:IVnqGOEym/WlBOVXweHU+Q+/VP0lqqI8lqeDx9IjBqo=
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d h1:62lEBImTxZ83pgzywgDNIrPPuQ+j4ep9QjqrWBn1hrU= github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d h1:62lEBImTxZ83pgzywgDNIrPPuQ+j4ep9QjqrWBn1hrU=
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ= github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ=
github.com/KyleBanks/depth v1.2.1 h1:5h8fQADFrWtarTdtDudMmGsC7GPbOAu6RVB3ffsVFHc=
github.com/KyleBanks/depth v1.2.1/go.mod h1:jzSb9d0L43HxTQfT+oSA1EEp2q+ne2uh6XgeJcm8brE=
github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA= github.com/Microsoft/go-winio v0.4.11/go.mod h1:VhR8bwka0BXejwEJY73c50VrPtXAaKcyvVC4A4RozmA=
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA= github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw= github.com/Microsoft/go-winio v0.4.15-0.20190919025122-fc70bd9a86b5/go.mod h1:tTuCMEN+UleMWgg9dVx4Hu52b1bJo+59jBh3ajtinzw=
@@ -84,21 +83,25 @@ github.com/Microsoft/hcsshim/test v0.0.0-20201218223536-d3e5debf77da/go.mod h1:5
github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY= github.com/Microsoft/hcsshim/test v0.0.0-20210227013316-43a75bb4edd3/go.mod h1:mw7qgWloBUl75W/gVH3cQszUg1+gUITj7D6NY7ywVnY=
github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ= github.com/NYTimes/gziphandler v0.0.0-20170623195520-56545f4a5d46/go.mod h1:3wb06e3pkSAbeQ52E9H9iFoQsEEwGN64994WTCIhntQ=
github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU= github.com/OneOfOne/xxhash v1.2.2/go.mod h1:HSdplMjZKSmBqAxg5vPj2TmRDmfkzw+cTzAElWljhcU=
github.com/PuerkitoBio/purell v1.1.0/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/purell v1.1.1 h1:WEQqlqaGbrPkxLJWfBwQmfEAE1Z7ONdDLqrN38tNFfI=
github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0= github.com/PuerkitoBio/purell v1.1.1/go.mod h1:c11w/QuzBsJSee3cPx9rAFu61PvFxuPbtSwDGJws/X0=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578 h1:d+Bc7a5rLufV/sSk/8dngufqelfh6jnri85riMAaF/M=
github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE= github.com/PuerkitoBio/urlesc v0.0.0-20170810143723-de5bf2ad4578/go.mod h1:uGdkoq3SwY9Y+13GIhn11/XLaGBb4BfwItxLd5jeuXE=
github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ= github.com/Shopify/logrus-bugsnag v0.0.0-20171204204709-577dee27f20d/go.mod h1:HI8ITrYtUY+O+ZhtlqUnD8+KwNPOyugEhfP9fdUIaEQ=
github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/StackExchange/wmi v0.0.0-20190523213315-cbe66965904d/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY= github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46 h1:5sXbqlSomvdjlRbWyNqkPsJ3Fg+tQZCbgeX1VGljbQY=
github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg= github.com/StackExchange/wmi v0.0.0-20210224194228-fe8f1750fd46/go.mod h1:3eOhrUMpNV+6aFIbp5/iudMxNCF27Vw2OZgy4xEx0Fg=
github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20160405071501-a0175ee3bccc/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751 h1:JYp7IbQjafoB+tBA3gMyHYHrpOtNuDiK/uB5uXxq5wM=
github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc= github.com/alecthomas/template v0.0.0-20190718012654-fb15b899a751/go.mod h1:LOuyumcjzFXgccqObfd/Ljyb9UuFJ6TxHnclSeseNhc=
github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20151022065526-2efee857e7cf/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0= github.com/alecthomas/units v0.0.0-20190717042225-c3de453c63f4/go.mod h1:ybxpYRFXyAe+OPACYpWeL0wqObRcbAqCMya13uyzqw0=
github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0= github.com/alexflint/go-filemutex v0.0.0-20171022225611-72bdc8eae2ae/go.mod h1:CgnQgUtFrFz9mxFNtED3jI5tLDjKlOM+oUF/sTk6ps0=
github.com/ambelovsky/go-structs v1.1.0 h1:LXj4/mHnYw0qhXQhOo96+ULGQ88H8qMcZd5SHef8boY=
github.com/ambelovsky/go-structs v1.1.0/go.mod h1:zN3RBXQvxgjjq/Q/WZS7p5AEK+qC9mNg7ycnvoQ63Ak=
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109 h1:Tp8GVfUOEmJftBqi4+/aXTwJzm24POo6wIHeuTqaT+Y=
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109/go.mod h1:MUREokfMKREm1fOm2babarrkYdk/dGHWY+ITC3qHHPQ=
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 h1:suVCm9PiIhz7ftTbWQNe7u2YjVfr8AEuUiNWKWApdMM=
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19/go.mod h1:o0+8DH+3X+FEOgSdNud0+8jJAsjtR9H3hF+O10Zcj/c=
github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c= github.com/anmitsu/go-shlex v0.0.0-20161002113705-648efa622239/go.mod h1:2FmKhYUyUczH0OGQWaF5ceTx0UBShxjsH6f8oGKYe2c=
github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY= github.com/antihax/optional v1.0.0/go.mod h1:uupD/76wgC+ih3iEmQUL+0Ugr19nfwCT1kdvxnR2qWY=
github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8= github.com/armon/consul-api v0.0.0-20180202201655-eb2c6b5be1b6/go.mod h1:grANhF5doyWs3UAsr3K4I6qtAmlQcZDesFNEHPZAzj8=
@@ -289,6 +292,9 @@ github.com/docker/go-units v0.4.0/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDD
github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE= github.com/docker/libtrust v0.0.0-20150114040149-fa567046d9b1/go.mod h1:cyGadeNEkKy96OOhEzfZl+yxihPEzKnqJwvfuSUqbZE=
github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM= github.com/docker/spdystream v0.0.0-20160310174837-449fdfce4d96/go.mod h1:Qh8CwZgvJUkLughtfhJv5dyTYa91l1fOUCrgjqmcifM=
github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE= github.com/docopt/docopt-go v0.0.0-20180111231733-ee0de3bc6815/go.mod h1:WwZ+bS3ebgob9U8Nd0kOddGdZWjyMGR8Wziv+TBNwSE=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 h1:iFaUwBSo5Svw6L7HYpRu/0lE3e0BaElwnNO1qkNQxBY=
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5/go.mod h1:qssHWj60/X5sZFNxpG4HBPDHVqxNm4DfnCKgrbZOT+s=
github.com/dsnet/golib v0.0.0-20171103203638-1ea166775780/go.mod h1:Lj+Z9rebOhdfkVLjJ8T6VcRQv3SXugXy999NBtR9aFY=
github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E= github.com/dsoprea/go-exif/v2 v2.0.0-20200321225314-640175a69fe4/go.mod h1:Lm2lMM2zx8p4a34ZemkaUV95AnMl4ZvLbCUbwOvLC2E=
github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8= github.com/dsoprea/go-exif/v3 v3.0.0-20200717053412-08f1b6708903/go.mod h1:0nsO1ce0mh5czxGeLo4+OCZ/C6Eo6ZlMWsz7rH/Gxv8=
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b h1:NgNuLvW/gAFKU30ULWW0gtkCt56JfB7FrZ2zyo0wT8I= github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b h1:NgNuLvW/gAFKU30ULWW0gtkCt56JfB7FrZ2zyo0wT8I=
@@ -316,8 +322,6 @@ github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7
github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk= github.com/evanphx/json-patch v4.9.0+incompatible/go.mod h1:50XU6AFN0ol/bzJsmQLiYLvXMP4fmwYFNcr97nuDLSk=
github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4= github.com/fatih/color v1.7.0/go.mod h1:Zm6kSWBoL9eyXnKyktHP6abPY2pDugNf5KwzbycvMj4=
github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc= github.com/flynn/go-shlex v0.0.0-20150515145356-3f9db97f8568/go.mod h1:xEzjJPgXI435gkrCt3MPfRiAkVrwSbHsst4LCFVfpJc=
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b h1:r13MvtFTtnvxtuKK7z0ZSQ2EfMmTzWDHwfDvGCoqUQE=
github.com/forease/gotld v0.0.0-20190808124948-c50ff635576b/go.mod h1:EfR6AU78zUiZ36oVS5YrmTzc2um3zDXWPx4L4st++jo=
github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k= github.com/form3tech-oss/jwt-go v3.2.2+incompatible/go.mod h1:pbq4aXjuKjdthFRnoDwaVPLA+WlJuPGy+QneDUgJi2k=
github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY= github.com/francoispqt/gojay v1.2.13/go.mod h1:ehT5mTG4ua4581f1++1WLG0vPdaA9HaiDsoyrBGkyDY=
github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k= github.com/frankban/quicktest v1.11.3/go.mod h1:wRf/ReqHper53s+kmmSZizM8NamnL3IM0I9ntUbOk+k=
@@ -328,15 +332,10 @@ github.com/fullsailor/pkcs7 v0.0.0-20190404230743-d7302db945fa/go.mod h1:KnogPXt
github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY= github.com/garyburd/redigo v0.0.0-20150301180006-535138d7bcd7/go.mod h1:NR3MbYisc3/PwhQ00EMzDiPmrwpPxAn5GI05/YaO1SY=
github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v0.0.0-20150909031657-73d445a93680/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04= github.com/ghodss/yaml v1.0.0/go.mod h1:4dBDuWmgqj2HViK6kFavaiC9ZROes6MMH2rRYeMEF04=
github.com/gin-contrib/gzip v0.0.1/go.mod h1:fGBJBCdt6qCZuCAOwWuFhBB4OOq9EFqlo5dEaFhhu5w=
github.com/gin-contrib/gzip v0.0.2 h1:VMBkd4ZB1Hl7e1lOA5gEZ/qdD3d9vLIq57xKWgPCCV8= github.com/gin-contrib/gzip v0.0.2 h1:VMBkd4ZB1Hl7e1lOA5gEZ/qdD3d9vLIq57xKWgPCCV8=
github.com/gin-contrib/gzip v0.0.2/go.mod h1:YxxswVZIqOvcHEQpsSn+QF5guQtO1dCfy0shBPy4jFc= github.com/gin-contrib/gzip v0.0.2/go.mod h1:YxxswVZIqOvcHEQpsSn+QF5guQtO1dCfy0shBPy4jFc=
github.com/gin-contrib/sse v0.0.0-20170109093832-22d885f9ecc7/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-contrib/sse v0.0.0-20190301062529-5545eab6dad3/go.mod h1:VJ0WA2NBN22VlZ2dKZQPAPnyWw5XTlK1KymzLKsr59s=
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE= github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI= github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
github.com/gin-gonic/gin v1.3.0/go.mod h1:7cKuhb5qV2ggCFctp2fJQ+ErvciLZrIeoOSOm6mUr7Y=
github.com/gin-gonic/gin v1.4.0/go.mod h1:OW2EZn3DO8Ln9oIKOvM++LBO+5UPHJJDH72/q/3rZdM=
github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M= github.com/gin-gonic/gin v1.6.3/go.mod h1:75u5sXoLsGZoRN5Sgbi1eraJ4GU3++wFwWzhwvtwp4M=
github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA= github.com/gin-gonic/gin v1.7.2 h1:Tg03T9yM2xa8j6I3Z3oqLaQRSmKvxPd6g/2HJ6zICFA=
github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY= github.com/gin-gonic/gin v1.7.2/go.mod h1:jD2toBW3GZUr5UMcdrwQA10I7RuaFOl/SGeDjXkfUtY=
@@ -360,29 +359,13 @@ github.com/go-logr/logr v0.2.0/go.mod h1:z6/tIYblkpsD+a4lm/fGIIU9mZ+XfAiaFtq7xTg
github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM= github.com/go-ole/go-ole v1.2.4/go.mod h1:XCwSNxSkXRo4vlyPy93sltvi/qJq0jqQhjqQNIwKuxM=
github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY= github.com/go-ole/go-ole v1.2.5 h1:t4MGB5xEDZvXI+0rMjjsfBsD7yAgp/s9ZDkL1JndXwY=
github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0= github.com/go-ole/go-ole v1.2.5/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
github.com/go-openapi/jsonpointer v0.17.0/go.mod h1:cOnomiV+CVVwFLk0A/MExoFMjwdsUdVpsRhURCKh+3M=
github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg= github.com/go-openapi/jsonpointer v0.19.2/go.mod h1:3akKfEdA7DF1sugOqz1dVQHBcuDBPKZGEoHC/NkiQRg=
github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg= github.com/go-openapi/jsonpointer v0.19.3/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
github.com/go-openapi/jsonreference v0.17.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.0/go.mod h1:g4xxGn04lDIRh0GJb5QlpE3HfopLOL6uZrK/VgnsK9I=
github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc= github.com/go-openapi/jsonreference v0.19.2/go.mod h1:jMjeRr2HHw6nAVajTXJ4eiUwohSTlpa0o73RUL1owJc=
github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8= github.com/go-openapi/jsonreference v0.19.3/go.mod h1:rjx6GuL8TTa9VaixXglHmQmIL98+wF9xc8zWvFonSJ8=
github.com/go-openapi/jsonreference v0.19.5/go.mod h1:RdybgQwPxbL4UEjuAruzK1x3nE69AqPYEJeo/TWfEeg=
github.com/go-openapi/jsonreference v0.19.6 h1:UBIxjkht+AWIgYzCDSv2GN+E/togfwXUJFRTWhl2Jjs=
github.com/go-openapi/jsonreference v0.19.6/go.mod h1:diGHMEHg2IqXZGKxqyvWdfWU/aim5Dprw5bqpKkTvns=
github.com/go-openapi/spec v0.19.0/go.mod h1:XkF/MOi14NmjsfZ8VtAKf8pIlbZzyoTvZsdfssdxcBI=
github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo= github.com/go-openapi/spec v0.19.3/go.mod h1:FpwSN1ksY1eteniUU7X0N/BgJ7a4WvBFVA8Lj9mJglo=
github.com/go-openapi/spec v0.20.3/go.mod h1:gG4F8wdEDN+YPBMVnzE85Rbhf+Th2DTvA9nFPQ5AYEg=
github.com/go-openapi/spec v0.20.4 h1:O8hJrt0UMnhHcluhIdUgCLRWyM2x7QkBXRvOs7m+O1M=
github.com/go-openapi/spec v0.20.4/go.mod h1:faYFR1CvsJZ0mNsmsphTMSoRrNV3TEDoAM7FOEWeq8I=
github.com/go-openapi/swag v0.17.0/go.mod h1:AByQ+nYG6gQg71GINrmuDXCPWdL640yX49/kXLo40Tg=
github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.2/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk= github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
github.com/go-openapi/swag v0.19.14/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-openapi/swag v0.19.15 h1:D2NRCBzS9/pEY3gP9Nl8aDqGUcPFrwG2p+CNFrLyrCM=
github.com/go-openapi/swag v0.19.15/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A= github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4= github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q= github.com/go-playground/locales v0.13.0 h1:HyWk6mgj5qFqCT5fjGBuRArbVDfE4hi8+e8ceBS/t7Q=
@@ -401,6 +384,7 @@ github.com/godbus/dbus v0.0.0-20180201030542-885f9cc04c9c/go.mod h1:/YcGZj5zSblf
github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4= github.com/godbus/dbus v0.0.0-20190422162347-ade71ed3457e/go.mod h1:bBOAhwG1umN6/6ZUMtDFBMQR8jRg9O75tm9K00oMsK4=
github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.3/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM= github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU= github.com/gogo/googleapis v1.2.0/go.mod h1:Njal3psf3qN6dwBtQfUmBZh2ybovJ0tlu3o/AC7HYjU=
github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c= github.com/gogo/googleapis v1.4.0/go.mod h1:5YRNX2z1oM5gXdAkurHa942MDgEJyk02w4OecKY87+c=
@@ -413,8 +397,8 @@ github.com/gogo/protobuf v1.3.0/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXP
github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o= github.com/gogo/protobuf v1.3.1/go.mod h1:SlYgWuQ5SjCEi6WLHjHCa1yvBfUnHcTbrrZtXPKa29o=
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q= github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q= github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY= github.com/golang-jwt/jwt/v4 v4.4.1 h1:pC5DB52sCeK48Wlb9oPcdhnjkz1TKt1D/P7WKJ0kUcQ=
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt/v4 v4.4.1/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d h1:C/hKUcHT483btRbeGkrRjJz+Zbcj8audldIi9tRJDCc= github.com/golang/geo v0.0.0-20200319012246-673a6f80352d h1:C/hKUcHT483btRbeGkrRjJz+Zbcj8audldIi9tRJDCc=
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
@@ -453,6 +437,9 @@ github.com/golang/protobuf v1.4.3/go.mod h1:oDoupMAO8OvCJWAcko0GGGIgR6R6ocIYbsSw
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk= github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw= github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY= github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
github.com/golang/snappy v0.0.2 h1:aeE13tS0IiQgFjYdoL8qN3K1N2bXXtI6Vi51/y7BpMw=
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
github.com/gomodule/redigo v1.8.4/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc= github.com/gomodule/redigo v1.8.5 h1:nRAxCa+SVsyjSBrtZmG/cqb6VbTmuRzpg/PoTFlpumc=
github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0= github.com/gomodule/redigo v1.8.5/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ= github.com/google/btree v0.0.0-20180813153112-4030bb1f1f0c/go.mod h1:lNA+9X1NB3Zf8V7Ke586lFgjr2dZNuvo3lPJSGZ5JPQ=
@@ -499,6 +486,8 @@ github.com/googleapis/gax-go/v2 v2.0.3/go.mod h1:LLvjysVCY1JZeum8Z6l8qUty8fiNwE0
github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg= github.com/googleapis/gax-go/v2 v2.0.4/go.mod h1:0Wqv26UfaUD9n4G6kQubkQ+KchISgw+vpHVxEJEs9eg=
github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk= github.com/googleapis/gax-go/v2 v2.0.5/go.mod h1:DWXyrwAJ9X0FpwwEdw+IPEYBICEFu5mhpdKc/us6bOk=
github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg= github.com/googleapis/gnostic v0.4.1/go.mod h1:LRhVm6pbyptWbWbuZ38d1eyptfvIytN3ir6b65WBswg=
github.com/googollee/go-socket.io v1.6.2 h1:olKLLHJtHz1IkL/OrTyNriZZvVQYEORNkJAqsOwPask=
github.com/googollee/go-socket.io v1.6.2/go.mod h1:0vGP8/dXR9SZUMMD4+xxaGo/lohOw3YWMh2WRiWeKxg=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1 h1:EGx4pi6eqNxGaHF6qqu48+N2wcFQ5qg5FXgOdqsJ5d8=
github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY= github.com/gopherjs/gopherjs v0.0.0-20181017120253-0766667cb4d1/go.mod h1:wJfORRmW1u3UXTncJ5qlYoELFm8eSnnEO6hX4iZ3EWY=
github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ= github.com/gorilla/handlers v0.0.0-20150720190736-60c7bfde3e33/go.mod h1:Qkdc/uu4tH4g6mTK6auzZ766c4CA0Ng8+o/OAirnOIQ=
@@ -545,9 +534,6 @@ github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/
github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160202185014-0b12d6b521d8/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k= github.com/jmespath/go-jmespath v0.0.0-20160803190731-bd40a432e4c7/go.mod h1:Nht3zPeWKUH0NzdCt2Blrr5ys8VGpn0CEB0cQHVjt7k=
github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo= github.com/jonboulle/clockwork v0.1.0/go.mod h1:Ii8DK3G1RaLaWxj9trq07+26W01tbo22gdxWY5EU2bo=
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFFd8Hwg//Y=
github.com/json-iterator/go v1.1.5/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU= github.com/json-iterator/go v1.1.6/go.mod h1:+SdeFBvtyEkXs7REEP0seUULqWtbJapLOCVDaaPEHmU=
github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.7/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4= github.com/json-iterator/go v1.1.9/go.mod h1:KdQUCv79m/52Kvf8AW2vK1V8akMuk1QjK/uOdHXbAo4=
@@ -563,10 +549,15 @@ github.com/kisielk/errcheck v1.1.0/go.mod h1:EZBBE59ingxPouuu3KfxchcWSUPOHkagtvW
github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00= github.com/kisielk/errcheck v1.2.0/go.mod h1:/BMXB+zMLi60iA8Vv6Ksmxu/1UDYcXs4uQLJ+jE2L00=
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8= github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck= github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.3/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.13/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc= github.com/klauspost/compress v1.13.6 h1:P76CopJELS0TiO2mebmnzgWaajssP/EszplttgQxcgc=
github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk= github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.2/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ= github.com/konsorten/go-windows-terminal-sequences v1.0.3/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
@@ -588,14 +579,10 @@ github.com/lucas-clemente/quic-go v0.25.0 h1:K+X9Gvd7JXsOHtU0N2icZ2Nw3rx82uBej3m
github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg= github.com/lucas-clemente/quic-go v0.25.0/go.mod h1:YtzP8bxRVCBlO77yRanE264+fY/T2U9ZlW1AaHOsMOg=
github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI= github.com/lunixbochs/vtclean v1.0.0/go.mod h1:pHhQNgMf3btfWnGBVipUOjRYhoOsdGqdm/+2c2E2WMI=
github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ= github.com/magiconair/properties v1.8.0/go.mod h1:PppfXfuXeibc/6YijjN8zIbojt8czPbwD3XqdrwzmxQ=
github.com/mailru/easyjson v0.0.0-20180823135443-60711f1a8329/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190312143242-1de009706dbe/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc= github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs= github.com/mailru/easyjson v0.7.0/go.mod h1:KAzv3t3aY1NaHWoQz1+4F1ccyAH66Jk7yos7ldAVICs=
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho= github.com/marstr/guid v1.1.0/go.mod h1:74gB1z2wpxxInTG6yaqA7KrtM0NZ+RbrcqDvYHefzho=
github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc= github.com/marten-seemann/qpack v0.2.1/go.mod h1:F7Gl5L1jIgN1D11ucXefiuJS9UMVP2opoCp2jDKb7wc=
github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I= github.com/marten-seemann/qtls-go1-15 v0.1.4/go.mod h1:GyFwywLKkRt+6mfU99csTEY1joMZz5vmB1WNZH3P81I=
@@ -607,8 +594,6 @@ github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1 h1:EnzzN9fPUkUck/1CuY1FlzBaI
github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI= github.com/marten-seemann/qtls-go1-18 v0.1.0-beta.1/go.mod h1:PUhIQk19LoFt2174H4+an8TYvWOGjb/hHwphBeaDHwI=
github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU= github.com/mattn/go-colorable v0.0.9/go.mod h1:9vuHe8Xs5qXnSaW/c/ABM9alt+Vo+STaOChaDxuIBZU=
github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4= github.com/mattn/go-isatty v0.0.4/go.mod h1:M+lRXTBqGeGNdLjl/ufCoiOlB5xdOkqRJdNxMWT7Zi4=
github.com/mattn/go-isatty v0.0.7/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU= github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y= github.com/mattn/go-isatty v0.0.14 h1:yVuAays6BHfxijgZPzw+3Zlu5yQgKGP2/hcQbHb7S9Y=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94= github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
@@ -619,10 +604,13 @@ github.com/mattn/go-sqlite3 v1.14.11 h1:gt+cp9c0XGqe9S/wAHTL3n/7MqY+siPWgWJgqdsF
github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU= github.com/mattn/go-sqlite3 v1.14.11/go.mod h1:NyWgC/yNuGj7Q9rpYnZvas74GogHl5/Z4A/KQRfk6bU=
github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0= github.com/matttproud/golang_protobuf_extensions v1.0.1/go.mod h1:D8He9yQNgCq6Z5Ld7szi9bcBfOoFv/3dc6xSMkL2PC0=
github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4= github.com/matttproud/golang_protobuf_extensions v1.0.2-0.20181231171920-c182affec369/go.mod h1:BSXmuO+STAnVfrANrmjBb36TMTDstsz7MSK+HVaYKv4=
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4= github.com/microcosm-cc/bluemonday v1.0.1/go.mod h1:hsXNsILzKxV+sX77C5b8FSuKF00vh2OMYv+xgHpAMF4=
github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs= github.com/miekg/pkcs11 v1.0.3/go.mod h1:XsNlhZGX73bx86s2hdc/FuaLm2CPZJemRLMA+WTFxgs=
github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4= github.com/mistifyio/go-zfs v2.1.2-0.20190413222219-f784269be439+incompatible/go.mod h1:8AuVvqP/mXw1px98n46wfvcGfQ4ci2FwoAjKYxuo3Z4=
github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0= github.com/mitchellh/go-homedir v1.1.0/go.mod h1:SfyaCUpYCn1Vlf4IUYiD9fPX4A5wJrkLzIz1N1q0pr0=
github.com/mitchellh/mapstructure v1.1.2 h1:fmNYVwqnSfB9mZU6OS2O6GsXM+wcskZDuKQzvN1EDeE=
github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y= github.com/mitchellh/mapstructure v1.1.2/go.mod h1:FVVH3fgwuzCH5S8UJGiWEs2h04kUh9fWfEaFds41c1Y=
github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A= github.com/mitchellh/osext v0.0.0-20151018003038-5e2d6d41470f/go.mod h1:OkQIRizQZAeMln+1tSwduZz7+Af5oFlKirV/MSYes2A=
github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg= github.com/moby/locker v1.0.1 h1:fOXqR41zeveg4fFODix+1Ch4mj/gT0NE1XJbp/epuBg=
@@ -650,7 +638,8 @@ github.com/mxk/go-flowrate v0.0.0-20140419014527-cca7078d478f/go.mod h1:ZdcZmHo+
github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM= github.com/ncw/swift v1.0.47/go.mod h1:23YIA4yWVnGwv2dQlN4bB7egfYX6YLn0Yo/S6zZO/ZM=
github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo= github.com/neelance/astrewrite v0.0.0-20160511093645-99348263ae86/go.mod h1:kHJEU3ofeGjhHklVoIGuVj85JJwZ6kWPaJwCIxgnFmo=
github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM= github.com/neelance/sourcemap v0.0.0-20151028013722-8c68805598ab/go.mod h1:Qr6/a/Q4r9LP1IltGz7tA7iOK1WonHEYhu1HRBA7ZiM=
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno= github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A= github.com/nxadm/tail v1.4.4/go.mod h1:kenIhsEOeOJmVchQTgglprH7qJGnHDVpk1VPCcaMI8A=
github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE= github.com/nxadm/tail v1.4.8 h1:nPr65rt6Y5JFSKQO7qToXr7pePgD6Gwiw05lkbyAQTE=
github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU= github.com/nxadm/tail v1.4.8/go.mod h1:+ncqLTQzXmGhMZNUePPaPqPvBxHAIsmXswZKocGu+AU=
@@ -711,6 +700,8 @@ github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTK
github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic= github.com/pelletier/go-toml v1.2.0/go.mod h1:5z9KED0ma1S8pY6P1sdut58dfprrGBbd/94hg7ilaic=
github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc= github.com/pelletier/go-toml v1.8.1/go.mod h1:T2/BmBdy8dvIRq1a/8aqjN41wvWlN4lrapLU/GW4pbc=
github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU= github.com/peterbourgon/diskv v2.0.1+incompatible/go.mod h1:uqqh8zWWbv1HBMNONnaR/tNboyR3/BZd58JJSHlUSCU=
github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.0/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1-0.20171018195549-f15c970de5b7/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
@@ -719,8 +710,6 @@ github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINE
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4= github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA= github.com/pquerna/cachecontrol v0.0.0-20171018203845-0dec1b30a021/go.mod h1:prYjPmNq4d1NPVmpShWobRqXY3q7Vp+80DqgxxUrUIA=
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109 h1:h9WYaTCQJ7hap8C5vQniEum2YZbc+iRad/ROafTjy10=
github.com/prestonTao/upnp v0.0.0-20150206124352-f4370df5e109/go.mod h1:U7VCLF6LMHzOFD/6Kww2MTQuwaNeEA1U1dOxFyZBoBE=
github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.0.0-20180209125602-c332b6f63c06/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.8.0/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw= github.com/prometheus/client_golang v0.9.1/go.mod h1:7SWBe2y4D6OKWSNQJUaRYU/AaXPKyh/dDVn+NZz0KFw=
@@ -769,7 +758,6 @@ github.com/seccomp/libseccomp-golang v0.9.1/go.mod h1:GbW5+tmTXfcxTToHLXlScSlAvW
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo= github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
github.com/shirou/gopsutil/v3 v3.21.5 h1:YUBf0w/KPLk7w1803AYBnH7BmA+1Z/Q5MEZxpREUaB4= github.com/shirou/gopsutil/v3 v3.21.5 h1:YUBf0w/KPLk7w1803AYBnH7BmA+1Z/Q5MEZxpREUaB4=
github.com/shirou/gopsutil/v3 v3.21.5/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw= github.com/shirou/gopsutil/v3 v3.21.5/go.mod h1:ghfMypLDrFSWN2c9cDYFLHyynQ+QUht0cv/18ZqVczw=
github.com/shopspring/decimal v1.2.0/go.mod h1:DKyhrW/HYNuLGql+MJL6WCR6knT2jwCFRcu2hWCYk4o=
github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY= github.com/shurcooL/component v0.0.0-20170202220835-f88ec8f54cc4/go.mod h1:XhFIlyj5a1fBNx5aJTbKoIq0mNaPvOagO+HjB3EtxrY=
github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM= github.com/shurcooL/events v0.0.0-20181021180414-410e4ca65f48/go.mod h1:5u70Mqkb5O5cxEA8nxTsgrgLehJeAw6Oc4Ab1c/P1HM=
github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0= github.com/shurcooL/github_flavored_markdown v0.0.0-20181002035957-2122de532470/go.mod h1:2dOwnU2uBioM+SGy2aZoq1f/Sd1l9OkAeAUvjSyvgU0=
@@ -813,7 +801,6 @@ github.com/sourcegraph/annotate v0.0.0-20160123013949-f4cad6c6324d/go.mod h1:Udh
github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA= github.com/sourcegraph/syntaxhighlight v0.0.0-20170531221838-bd320f5d308e/go.mod h1:HuIsMU8RRBOtsCgI77wP899iHVBQpCmg4ErYMZB+2IA=
github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA= github.com/spaolacci/murmur3 v0.0.0-20180118202830-f09979ecbc72/go.mod h1:JwIasOWyU6f++ZhiEuf87xNszmSA2myDM2Kzu9HwQUA=
github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ= github.com/spf13/afero v1.1.2/go.mod h1:j4pytiNVoe2o6bmDsKpLACNPDBIoEAkihy7loJ1B0CQ=
github.com/spf13/afero v1.2.2 h1:5jhuqJyZCZf2JRofRvN/nIFgIWNzPa3/Vz8mYylgbWc=
github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk= github.com/spf13/afero v1.2.2/go.mod h1:9ZxEEn6pIJ8Rxe320qSDBk6AsU0r9pR7Q4OcevTdifk=
github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE= github.com/spf13/cast v1.3.0/go.mod h1:Qx5cxh0v+4UWYiBimWS+eyWzqEqokIECu5etghLkUJE=
github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ= github.com/spf13/cobra v0.0.2-0.20171109065643-2da4a54c5cee/go.mod h1:1l0Ry5zgKvJasoi3XT1TypsSe7PqH0Sj9dhYf7v3XqQ=
@@ -839,12 +826,6 @@ github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY= github.com/stretchr/testify v1.7.0 h1:nwc3DEeHmmLAfoZucVR881uASk0Mfjw8xYJ99tb5CcY=
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/swaggo/files v0.0.0-20190704085106-630677cd5c14/go.mod h1:gxQT6pBGRuIGunNf/+tSOB5OHvguWi8Tbt82WOkf35E=
github.com/swaggo/gin-swagger v1.3.0 h1:eOmp7r57oUgZPw2dJOjcGNMse9cvXcI4tTqBcnZtPsI=
github.com/swaggo/gin-swagger v1.3.0/go.mod h1:oy1BRA6WvgtCp848lhxce7BnWH4C8Bxa0m5SkWx+cS0=
github.com/swaggo/swag v1.5.1/go.mod h1:1Bl9F/ZBpVWh22nY0zmYyASPO1lI/zIwRDrpZU+tv8Y=
github.com/swaggo/swag v1.7.3 h1:ucB7irEdRrhjmW+Z1Ss4GjO68oPKQFjSgOR8BCAvcbU=
github.com/swaggo/swag v1.7.3/go.mod h1:zD8h6h4SPv7t3l+4BKdRquqW1ASWjKZgT6Qv9z3kNqI=
github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20170704070218-db04d3cc01c8/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20180916011248-d98352740cb2/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww= github.com/syndtr/gocapability v0.0.0-20200815063812-42c35b437635/go.mod h1:hkRG7XYTFWNJGYcbNJQlaLq0fg1yr4J4t/NcTQtrfww=
@@ -867,19 +848,18 @@ github.com/tmc/grpc-websocket-proxy v0.0.0-20190109142713-0ad062ec5ee5/go.mod h1
github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM= github.com/tv42/httpunix v0.0.0-20191220191345-2ba4b9c3382c/go.mod h1:hzIxponao9Kjc7aWznkXaL4U4TWaDSs8zcsY4Ka08nM=
github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc= github.com/ugorji/go v1.1.4/go.mod h1:uQMGLiO92mf5W77hV/PUCpI3pbzQx3CRekS0kk+RGrc=
github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw= github.com/ugorji/go v1.1.7/go.mod h1:kZn38zHttfInRq0xu/PH0az30d+z6vm202qpg1oXVMw=
github.com/ugorji/go v1.1.13/go.mod h1:jxau1n+/wyTGLQoCkjok9r5zFa/FxT6eI5HiHKQszjc=
github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E= github.com/ugorji/go v1.2.6 h1:tGiWC9HENWE2tqYycIqFTNorMmFRVhNwCpDOpWqnk8E=
github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0= github.com/ugorji/go v1.2.6/go.mod h1:anCg0y61KIhDlPZmnH+so+RQbysYVyDko0IMgJv0Nn0=
github.com/ugorji/go/codec v0.0.0-20181022190402-e5e69e061d4f/go.mod h1:VFNgLljTbGfSG7qAOspJ7OScBnGdDN/yBr0sguwnwf0=
github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY= github.com/ugorji/go/codec v1.1.7/go.mod h1:Ax+UKWsSmolVDwsd+7N3ZtXu+yMGCf907BLYF3GoBXY=
github.com/ugorji/go/codec v1.1.13/go.mod h1:oNVt3Dq+FO91WNQ/9JnHKQP2QJxTzoN7wCBFCq1OeuU=
github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ= github.com/ugorji/go/codec v1.2.6 h1:7kbGefxLoDBuYXOms4yD7223OpNMMPNPZxXk5TvFcyQ=
github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw= github.com/ugorji/go/codec v1.2.6/go.mod h1:V6TCNZ4PHqoHGFZuSG1W8nrCzzdgA2DozYxWFFpvxTw=
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v0.0.0-20171014202726-7bc6a0acffa5/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA= github.com/urfave/cli v1.20.0/go.mod h1:70zkFmudgCuE/ngEzBv17Jvp/497gISqfk5gWijbERA=
github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.1/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0= github.com/urfave/cli v1.22.2/go.mod h1:Gos4lmkARVdJ6EkW0WaNv/tZAAMe9V7XWyB60NtXRu0=
github.com/urfave/cli/v2 v2.3.0/go.mod h1:LJmUH05zAU44vOAcrfzZQKsZbVcdbOG8rtL3/XcUArI=
github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU= github.com/viant/assertly v0.4.8/go.mod h1:aGifi++jvCrUaklKEKT0BU95igDNaqkvz+49uaYMPRU=
github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM= github.com/viant/toolbox v0.24.0/go.mod h1:OxMCG57V0PXuIP2HNQrtJf2CjqdmbrOx5EkMILuUhzM=
github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk= github.com/vishvananda/netlink v0.0.0-20181108222139-023a6dafdcdf/go.mod h1:+SR5DhBJrl6ZM7CoCKvpw5BKroDKQ+PJqOg65H/2ktk=
@@ -893,6 +873,8 @@ github.com/willf/bitset v1.1.11/go.mod h1:83CECat5yLh5zVOf4P1ErAgKA5UDvKtgyUABdr
github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU= github.com/xeipuuv/gojsonpointer v0.0.0-20180127040702-4e3ac2762d5f/go.mod h1:N2zxlSyiKSe5eX1tZViRH5QA0qijqEDrYZiPEAiq3wU=
github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ= github.com/xeipuuv/gojsonreference v0.0.0-20180127040603-bd5ef7bd5415/go.mod h1:GwrjFmJcFw6At/Gs6z4yjiIwzuJ1/+UwLxMQDVQXShQ=
github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs= github.com/xeipuuv/gojsonschema v0.0.0-20180618132009-1d523034197f/go.mod h1:5yf86TLmAcydyeJq5YvxkGPE2fm/u4myDekKRoLuqhs=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU= github.com/xiang90/probing v0.0.0-20190116061207-43a291ad63a2/go.mod h1:UETIi67q53MR2AWcXfiuqkDkRtnGDLqkBTpCHuJHxtU=
github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q= github.com/xordataexchange/crypt v0.0.3-0.20170626215501-b2862e3d0a77/go.mod h1:aYKd//L2LvnjZzWKhF00oedf4jCCReLcmhLdhm1A27Q=
github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74= github.com/yuin/goldmark v1.1.25/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
@@ -919,8 +901,11 @@ go.opencensus.io v0.23.0 h1:gqCw0LfLxScz8irSi8exQc7fyQ0fKQU/qnC/X8+V/1M=
go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E= go.opencensus.io v0.23.0/go.mod h1:XItmlyltB5F7CS4xOC1DcqMoFqwtC6OG2xF7mCv7P7E=
go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI= go.opentelemetry.io/proto/otlp v0.7.0/go.mod h1:PqfVotwruBrMGOCsRd/89rSnXhoiJIqeYNgFYFoEGnI=
go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.3.2/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/atomic v1.4.0 h1:cxzIVoETapQEqDhQu3QfnvXAV4AlzcvUCxkVUFw3+EU=
go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE= go.uber.org/atomic v1.4.0/go.mod h1:gD2HeocX3+yG+ygLZcrzQJaqmWj9AIm7n08wl/qW/PE=
go.uber.org/multierr v1.1.0 h1:HoEmRHQPVSqub6w2z2d2EOVs2fjyFRGyofhKuyDq0QI=
go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0= go.uber.org/multierr v1.1.0/go.mod h1:wR5kodmAFQ0UK8QlbwjlSNy0Z68gJhDJUG5sjR94q/0=
go.uber.org/zap v1.10.0 h1:ORx85nbTijNz8ljznvCMR1ZBIPKFn3jQrag10X2AsuM=
go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q= go.uber.org/zap v1.10.0/go.mod h1:vwi/ZaCAaUcBkycHslxD9B2zi4UTXhF60s6SWpuDF0Q=
go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE= go4.org v0.0.0-20180809161055-417644f6feb5/go.mod h1:MkTOUMDaeVYJUOUsaDXIhWPZYa1yOyC1qaOBpL57BhE=
golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw= golang.org/x/build v0.0.0-20190111050920-041ab4dc3f9d/go.mod h1:OWs+y06UdEOHN4y+MfF/py+xQ/tYqIWW03b70/CG9Rw=
@@ -981,7 +966,6 @@ golang.org/x/mod v0.5.0/go.mod h1:5OXOZSfqPIIbmVBIIKWRFfZjPR0E5r58TLhUjH0a2Ro=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181005035420-146acd28ed58/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181011144130-49bb7cea24b1/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181029044818-c44066c5c816/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20181106065722-10aee1819953/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -996,7 +980,6 @@ golang.org/x/net v0.0.0-20190501004415-9ce7a6920f09/go.mod h1:t9HGtf8HONx5eT2rtn
golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg= golang.org/x/net v0.0.0-20190503192946-f4e77d36d62c/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190522155817-f3200d17e092/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks= golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
golang.org/x/net v0.0.0-20190611141213-3f473d35a33a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190613194153-d28f0bde5980/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190619014844-b5b0513f8c1b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
@@ -1025,10 +1008,8 @@ golang.org/x/net v0.0.0-20201006153459-a7d1128ccaa0/go.mod h1:sp8m0HH+o8qH0wwXwY
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU= golang.org/x/net v0.0.0-20201110031124-69a78807bb2b/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20201224014010-6772e930b67b/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210119194325-5f4716e94777/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg= golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM= golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
golang.org/x/net v0.0.0-20210421230115-4e50805a0758/go.mod h1:72T/g9IO56b78aLF+1Kcs5dz7/ng1VjMUvfKvpfy+jM=
golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk= golang.org/x/net v0.0.0-20210428140749-89ef3d95e781/go.mod h1:OJAsFXCWl8Ukc7SiCT/9KSuxbyM7479/AVlXFRxuMCk=
golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y= golang.org/x/net v0.0.0-20210805182204-aaa1db679c0d/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI= golang.org/x/net v0.0.0-20211020060615-d418f374d309 h1:A0lJIi+hcTR6aajJH4YqKWwohY4aW9RO7oRMcdv+HKI=
@@ -1061,9 +1042,7 @@ golang.org/x/sys v0.0.0-20180909124046-d0be0721c37e/go.mod h1:STP8DvDyc/dI5b8T5h
golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181029174526-d69651ed3497/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181107165924-66b7b1311ac8/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20181116152217-5ac8a444bdc5/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20181228144115-9a3f9b0469bb/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190312061237-fead79001313/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190316082340-a2f829d7f35f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1075,7 +1054,6 @@ golang.org/x/sys v0.0.0-20190522044717-8097e1b27ff5/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190602015325-4c4f7f33c9ed/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606165138-5da285871e9c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190606203320-7fc4e5ec1444/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190610200419-93c9922d18ae/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190616124812-15dcb6c0061f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190624142023-c5567b49c5d0/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20190726091711-fc99dfbffb4e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
@@ -1126,13 +1104,11 @@ golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7w
golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201201145000-ef89a241ccb3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20201202213521-69691e467435/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210112080510-489259a85091/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210124154548-22da62e12c0c/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210217105451-b926d437f341/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210316164454-77fc1eacc6aa/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210324051608-47abb6519492/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210420072515-93ed5bcd2bfe/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs= golang.org/x/sys v0.0.0-20210426230700-d19ff857e887/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@@ -1176,9 +1152,7 @@ golang.org/x/tools v0.0.0-20190328211700-ab21143f2384/go.mod h1:LCzVGOaR6xXOjkQ3
golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190425150028-36563e24a262/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190506145303-2d16b83fe98c/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q= golang.org/x/tools v0.0.0-20190524140312-2c0ae7006135/go.mod h1:RgjU9mgBXZiqYHBnxXauZ1Gv1EHHAz9KjViQ78xBX0Q=
golang.org/x/tools v0.0.0-20190606050223-4d9ae51c2468/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190606124116-d0a3d012864b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190611222205-d73e1c7e250b/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190614205625-5aca471b1d59/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190621195816-6e04913cbbac/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc= golang.org/x/tools v0.0.0-20190624222133-a101b041ded4/go.mod h1:/rFqwRUd4F7ZHNgwSSTFct+R/Kf4OFW1sUzUTQQTgfc=
@@ -1214,7 +1188,6 @@ golang.org/x/tools v0.0.0-20200804011535-6c149bb5ef0d/go.mod h1:njjCfa9FT2d7l9Bc
golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA= golang.org/x/tools v0.0.0-20200825202427-b303f430e36d/go.mod h1:njjCfa9FT2d7l9Bc6FUM5FLjQPp3cFF28FI3qnDFljA=
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.0/go.mod h1:xkSsbof2nBLbhDlRMhhhyNLN/zl3eTqcnHD5viDpcZ0=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ= golang.org/x/tools v0.1.7 h1:6j8CgantCy3yc8JGBqkDLMKWqZ0RDU2g1HVgacojGWQ=
golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo= golang.org/x/tools v0.1.7/go.mod h1:LGqMHiF4EqQNHR1JncWGqT5BVaXmza+X+BDGol+dOxo=
@@ -1338,18 +1311,16 @@ gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8
gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20141024133853-64131543e789/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q= gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw= gopkg.in/cheggaaa/pb.v1 v1.0.25/go.mod h1:V/YB90LKu/1FcN3WVnfiiE5oMCibMjukxqG/qStrOgw=
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI= gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys= gopkg.in/fsnotify.v1 v1.4.7/go.mod h1:Tz8NjZHkW78fSQdbUxIjBTcgA1z1m8ZHf0WmKUhAMys=
gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo= gopkg.in/gemnasium/logrus-airbrake-hook.v2 v2.1.2/go.mod h1:Xk6kEKp8OKb+X14hQBKWaSkCsqBpgog8nAV2xsGOxlo=
gopkg.in/go-playground/assert.v1 v1.2.1/go.mod h1:9RXL0bg/zibRAgZUYszZSwO/z8Y/a8bDuhia5mkpMnE=
gopkg.in/go-playground/validator.v8 v8.18.2/go.mod h1:RX2a/7Ha8BgOhfk7j780h4/u/RRjR0eouCJSH80/M2Y=
gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw= gopkg.in/inf.v0 v0.9.1/go.mod h1:cWUDdTG/fYaXco+Dcufb5Vnc6Gp2YChqWtbxRZE0mXw=
gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU= gopkg.in/ini.v1 v1.62.0 h1:duBzk771uxoUuOlyRLkHsygud9+5lrlGjdFBb4mSKDU=
gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k= gopkg.in/ini.v1 v1.62.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k= gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo= gopkg.in/resty.v1 v1.12.0/go.mod h1:mDo4pnntr5jdWRML875a/NmxYqAlA73dVijT2AXvQQo=
gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI= gopkg.in/square/go-jose.v2 v2.2.2/go.mod h1:M9dMgbHiYLoDGQrXy7OpJDJWiKiU//h+vD76mk0e1AI=
@@ -1369,7 +1340,6 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY= gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ= gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b h1:h8qDotaEPuJATrMmW04NCwg7v22aHH28wwpauUhK9Oo=
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4= gorm.io/driver/sqlite v1.2.6 h1:SStaH/b+280M7C8vXeZLz/zo9cLQmIGwwj3cSj7p6l4=

79
main.go
View File

@@ -6,14 +6,15 @@ import (
"net/http" "net/http"
"time" "time"
"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"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/pkg/utils/random"
"github.com/IceWhaleTech/CasaOS/route" "github.com/IceWhaleTech/CasaOS/route"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/robfig/cron" "github.com/robfig/cron"
"gorm.io/gorm" "gorm.io/gorm"
@@ -23,32 +24,26 @@ var sqliteDB *gorm.DB
var configFlag = flag.String("c", "", "config address") var configFlag = flag.String("c", "", "config address")
var dbFlag = flag.String("db", "", "db path") var dbFlag = flag.String("db", "", "db path")
var showUserInfo = flag.Bool("show-user-info", false, "show user info") var resetUser = flag.Bool("ru", false, "reset user")
var user = flag.String("user", "", "user name")
func init() { func init() {
flag.Parse() flag.Parse()
config.InitSetup(*configFlag) config.InitSetup(*configFlag)
config.UpdateSetup() config.UpdateSetup()
loger2.LogSetup() 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, loger2.NewOLoger()) service.MyService = service.NewService(sqliteDB)
service.Cache = cache.Init() service.Cache = cache.Init()
go service.UDPService() service.GetToken()
fmt.Println("token", 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()
@@ -66,38 +61,43 @@ func init() {
// @name Authorization // @name Authorization
// @BasePath /v1 // @BasePath /v1
func main() { func main() {
if *showUserInfo { service.NotifyMsg = make(chan notify.Message, 10)
fmt.Println("CasaOS User Info") if *resetUser {
fmt.Println("UserName:" + config.UserInfo.UserName) if user == nil || len(*user) == 0 {
fmt.Println("Password:" + config.UserInfo.PWD) fmt.Println("user is empty")
return
}
userData := service.MyService.User().GetUserAllInfoByName(*user)
if userData.Id == 0 {
fmt.Println("user not exist")
return
}
password := random.RandomString(6, false)
userData.Password = encryption.GetMD5ByStr(password)
service.MyService.User().UpdateUserPassword(userData)
fmt.Println("User reset successful")
fmt.Println("UserName:" + userData.Username)
fmt.Println("Password:" + password)
return return
} }
go route.SocketInit(service.NotifyMsg)
//model.Setup() //model.Setup()
//gredis.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()
service.LoopFriend()
service.MyService.App().CheckNewImage()
})
if err != nil {
fmt.Println(err)
}
err = cron2.AddFunc("0/1 * * * * *", func() {
notify := model2.AppNotify{}
notify.CustomId = ""
notify.Type = types.NOTIFY_TYPE_HEALTH_CHECK
go service.MyService.Notify().SendText(notify)
err := cron2.AddFunc("0/5 * * * * *", func() {
if service.ClientCount > 0 {
//route.SendNetINfoBySocket()
//route.SendCPUBySocket()
//route.SendMemBySocket()
// route.SendDiskBySocket()
//route.SendUSBBySocket()
route.SendAllHardwareStatusBySocket()
}
}) })
if err != nil { if err != nil {
fmt.Println(err) fmt.Println(err)
@@ -114,4 +114,7 @@ func main() {
s.ListenAndServe() s.ListenAndServe()
// if err := r.Run(fmt.Sprintf(":%v", config.ServerInfo.HttpPort)); err != nil {
// fmt.Println("failed run app: ", err)
// }
} }

View File

@@ -1,31 +1,40 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2021-10-08 10:29:08
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-22 11:06:07
* @FilePath: /CasaOS/middleware/gin.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package middleware 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 {
return func(c *gin.Context) { return func(c *gin.Context) {
method := c.Request.Method method := c.Request.Method
//origin := c.Request.Header.Get("Origin") //请求头部
//if origin != "" {
//接收客户端发送的origin (重要!)
c.Writer.Header().Set("Access-Control-Allow-Origin", "*")
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.Header("Access-Control-Max-Age", "172800") c.Header("Access-Control-Max-Age", "172800")
//允许客户端传递校验信息比如 cookie (重要)
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")
//} //}
//允许类型校验 //允许类型校验
@@ -42,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"`
@@ -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,11 +1,23 @@
/*
* @Author: link a624669980@163.com
* @Date: 2022-05-16 17:37:08
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-13 10:46:38
* @FilePath: /CasaOS/model/category.go
* @Description:
*/
package model package model
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 属于动态信息,应该单独放在一个出参结构中(原因见另外一个关于 静态/动态 出参的注释)
} }

View File

@@ -1,3 +1,13 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-13 10:43:45
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-13 11:00:04
* @FilePath: /CasaOS/model/disk.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model package model
type LSBLKModel struct { type LSBLKModel struct {
@@ -53,8 +63,8 @@ type DriveUSB struct {
Size uint64 `json:"size"` Size uint64 `json:"size"`
Used uint64 `json:"use"` Used uint64 `json:"use"`
Model string `json:"model"` Model string `json:"model"`
Mount bool `json:"mount"` //是否完全挂载 Mount bool `json:"mount"`
Avail uint64 `json:"avail"` //可用空间 Avail uint64 `json:"avail"`
} }
type Storage struct { type Storage struct {

View File

@@ -1,8 +1,18 @@
/*
* @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"`
} }

33
model/file.go Normal file
View File

@@ -0,0 +1,33 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-20 16:27:12
* @LastEditors: LinkLeong
* @LastEditTime: 2022-06-09 18:18:46
* @FilePath: /CasaOS/model/file.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
type FileOperate struct {
Type string `json:"type" binding:"required"`
Item []FileItem `json:"item" binding:"required"`
TotalSize int64 `json:"total_size"`
ProcessedSize int64 `json:"processed_size"`
To string `json:"to" binding:"required"`
Style string `json:"style"`
Finished bool `json:"finished"`
}
type FileItem struct {
From string `json:"from" binding:"required"`
Finished bool `json:"finished"`
Size int64 `json:"size"`
ProcessedSize int64 `json:"processed_size"`
}
type FileUpdate struct {
FilePath string `json:"path" binding:"required"`
FileContent string `json:"content" binding:"required"`
}

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"`
@@ -127,4 +128,6 @@ type CustomizationPostData struct {
Privileged bool `json:"privileged"` Privileged bool `json:"privileged"`
CapAdd []string `json:"cap_add"` CapAdd []string `json:"cap_add"`
Cmd []string `json:"cmd"` Cmd []string `json:"cmd"`
Protocol string `json:"protocol"`
Host string `json:"host"`
} }

View File

@@ -0,0 +1,21 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-27 15:01:58
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-31 14:51:21
* @FilePath: /CasaOS/model/notify/application.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package notify
type Application struct {
Name string `json:"name"`
State string `json:"state"`
Type string `json:"type"`
Icon string `json:"icon"`
Message string `json:"message"`
Finished bool `json:"finished"`
Success bool `json:"success"`
}

22
model/notify/file.go Normal file
View File

@@ -0,0 +1,22 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-26 14:21:57
* @LastEditors: LinkLeong
* @LastEditTime: 2022-06-02 11:14:15
* @FilePath: /CasaOS/model/notify/file.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package notify
type File struct {
Finished bool `json:"finished"`
ProcessedSize int64 `json:"processed_size"`
ProcessingPath string `json:"processing_path"`
Status string `json:"status"`
TotalSize int64 `json:"total_size"`
Id string `json:"id"`
To string `json:"to"`
Type string `json:"type"`
}

20
model/notify/message.go Normal file
View File

@@ -0,0 +1,20 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-26 14:39:22
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-26 19:08:52
* @FilePath: /CasaOS/model/notify/message.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package notify
import (
f "github.com/ambelovsky/gosf"
)
type Message struct {
Path string `json:"path"`
Msg f.Message `json:"msg"`
}

18
model/notify/result.go Normal file
View File

@@ -0,0 +1,18 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-26 14:21:11
* @LastEditors: LinkLeong
* @LastEditTime: 2022-05-27 11:15:59
* @FilePath: /CasaOS/model/notify/result.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package notify
// Notify struct for Notify
type NotifyModel struct {
Data interface{} `json:"data"`
State string `json:"state"`
}

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,3 +1,13 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-14 11:02:06
* @FilePath: /CasaOS/model/sys_common.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model package model
import "time" import "time"
@@ -27,23 +37,24 @@ type ServerModel struct {
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
} }
//服务配置 //服务配置
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
TempPath string
} }
//公共返回模型 //公共返回模型
@@ -63,12 +74,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,5 +1,15 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2021-09-30 18:18:14
* @LastEditors: LinkLeong
* @LastEditTime: 2022-06-21 11:09:30
* @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.conf"
) )

View File

@@ -1,3 +1,13 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-14 10:58:45
* @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 (
@@ -42,6 +52,9 @@ func InitSetup(config string) {
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)
@@ -57,6 +70,26 @@ func InitSetup(config string) {
mapTo("system", SystemConfigInfo) mapTo("system", SystemConfigInfo)
mapTo("file", FileSettingInfo) mapTo("file", FileSettingInfo)
SystemConfigInfo.ConfigPath = configDir SystemConfigInfo.ConfigPath = configDir
if len(AppInfo.DBPath) == 0 {
AppInfo.DBPath = "/var/lib/casaos"
Cfg.SaveTo(configDir)
}
if len(AppInfo.LogPath) == 0 {
AppInfo.LogPath = "/var/log/casaos/"
Cfg.SaveTo(configDir)
}
if len(AppInfo.ShellPath) == 0 {
AppInfo.ShellPath = "/usr/share/casaos/shell"
Cfg.SaveTo(configDir)
}
if len(AppInfo.UserDataPath) == 0 {
AppInfo.UserDataPath = "/var/lib/casaos/conf"
Cfg.SaveTo(configDir)
}
if len(AppInfo.TempPath) == 0 {
AppInfo.TempPath = "/var/lib/casaos/temp"
Cfg.SaveTo(configDir)
}
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd() // AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
} }

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

View File

@@ -1,11 +1,22 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-11 18:10:53
* @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,29 @@ 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{})
db.Exec(`alter table o_user rename to old_user;
create table o_users ( id integer primary key,username text,password text,role text,email text,nickname text,avatar text,description text,created_at datetime,updated_at datetime);
insert into o_users select id,user_name,password,role,email,nick_name,avatar,description,created_at,updated_at from old_user;
drop table old_user;
drop table o_user;
`)
err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.UserDBModel{})
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())
}

View File

@@ -1,26 +1,32 @@
package oasis_err package common_err
const ( const (
SUCCESS = 200 SUCCESS = 200
ERROR = 500 SERVICE_ERROR = 500
INVALID_PARAMS = 400 CLIENT_ERROR = 400
ERROR_AUTH_TOKEN = 401 ERROR_AUTH_TOKEN = 401
INVALID_PARAMS = 4000
//user //user
PWD_INVALID = 10001 PWD_INVALID = 10001
PWD_IS_EMPTY = 10002 PWD_IS_EMPTY = 10002
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
PWD_INVALID_OLD = 10003
ACCOUNT_LOCK = 10004
//system //system
DIR_ALREADY_EXISTS = 20001 DIR_ALREADY_EXISTS = 20001
FILE_ALREADY_EXISTS = 20002 FILE_ALREADY_EXISTS = 20002
FILE_OR_DIR_EXISTS = 20003 FILE_OR_DIR_EXISTS = 20003
PORT_IS_OCCUPIED = 20004 PORT_IS_OCCUPIED = 20004
COMMAND_ERROR_INVALID_OPERATION = 20005 COMMAND_ERROR_INVALID_OPERATION = 20005
VERIFICATION_FAILURE = 20006
//zerotier
GET_TOKEN_ERROR = 30001
//disk //disk
NAME_NOT_AVAILABLE = 40001 NAME_NOT_AVAILABLE = 40001
@@ -40,39 +46,38 @@ const (
FILE_READ_ERROR = 60002 FILE_READ_ERROR = 60002
FILE_DELETE_ERROR = 60003 FILE_DELETE_ERROR = 60003
DIR_NOT_EXISTS = 60004 DIR_NOT_EXISTS = 60004
SOURCE_DES_SAME = 60005
//shortcuts //shortcuts
SHORTCUTS_URL_ERROR = 70001 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{ var MsgFlags = map[int]string{
SUCCESS: "ok", SUCCESS: "ok",
ERROR: "fail", SERVICE_ERROR: "Fail",
CLIENT_ERROR: "Fail",
INVALID_PARAMS: "Parameters Error", INVALID_PARAMS: "Parameters Error",
ERROR_AUTH_TOKEN: "Error auth token", ERROR_AUTH_TOKEN: "Error auth token",
//user //user
PWD_INVALID: "Invalid password", PWD_INVALID: "Invalid password",
PWD_IS_EMPTY: "Password is empty", PWD_IS_EMPTY: "Password is empty",
PWD_INVALID_OLD: "Invalid old password", PWD_INVALID_OLD: "Invalid old password",
ACCOUNT_LOCK: "Account is locked", 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 //system
DIR_ALREADY_EXISTS: "Folder already exists", DIR_ALREADY_EXISTS: "Folder already exists",
FILE_ALREADY_EXISTS: "File already exists", FILE_ALREADY_EXISTS: "File already exists",
FILE_OR_DIR_EXISTS: "File or folder already exists", FILE_OR_DIR_EXISTS: "File or folder already exists",
PORT_IS_OCCUPIED: "Port is occupied", PORT_IS_OCCUPIED: "Port is occupied",
VERIFICATION_FAILURE: "Verification failure",
//zerotier
GET_TOKEN_ERROR: "Get token error,Please log in to zerotier's official website to confirm whether the account is available",
//app //app
UNINSTALL_APP_ERROR: "Error uninstalling app", UNINSTALL_APP_ERROR: "Error uninstalling app",
@@ -88,6 +93,7 @@ var MsgFlags = map[int]string{
FORMAT_ERROR: "Formatting failed, please check if the directory is occupied", 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", FILE_DOES_NOT_EXIST: "File does not exist",
DIR_NOT_EXISTS: "Directory does not exist", DIR_NOT_EXISTS: "Directory does not exist",
@@ -96,12 +102,6 @@ var MsgFlags = map[int]string{
FILE_DELETE_ERROR: "Delete error", FILE_DELETE_ERROR: "Delete error",
SHORTCUTS_URL_ERROR: "URL error", SHORTCUTS_URL_ERROR: "URL error",
PERSON_REMOTE_ERROR: "Remote connection error",
PERSON_DOWN_NOT_EXIST: "Download record does not exist",
PERSON_EXIST_DOWNLOAD: "The same download task exists",
PERSON_EXIST_FRIEND: "Friend already exist",
PERSON_NOT_EXIST_USER: "User does not exist",
PERSON_MYSELF: "You can not add yourself",
COMMAND_ERROR_INVALID_OPERATION: "invalid operation", COMMAND_ERROR_INVALID_OPERATION: "invalid operation",
} }
@@ -111,5 +111,5 @@ func GetMsg(code int) string {
if ok { if ok {
return msg return msg
} }
return MsgFlags[ERROR] 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

@@ -2,9 +2,11 @@ package file
import ( import (
"bufio" "bufio"
"errors"
"fmt" "fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"log"
"mime/multipart" "mime/multipart"
"os" "os"
"path" "path"
@@ -12,6 +14,8 @@ import (
"path/filepath" "path/filepath"
"strconv" "strconv"
"strings" "strings"
"github.com/mholt/archiver/v3"
) )
// GetSize get the file size // GetSize get the file size
@@ -182,7 +186,7 @@ func ReadFullFile(path string) []byte {
} }
// File copies a single file from src to dst // File copies a single file from src to dst
func CopyFile(src, dst string) error { func CopyFile(src, dst, style string) error {
var err error var err error
var srcfd *os.File var srcfd *os.File
var dstfd *os.File var dstfd *os.File
@@ -193,20 +197,55 @@ func CopyFile(src, dst string) error {
if !strings.HasSuffix(dst, "/") { if !strings.HasSuffix(dst, "/") {
dst += "/" dst += "/"
} }
dstPath := dst
dst += lastPath dst += lastPath
for i := 0; Exists(dst); i++ { if Exists(dst) {
name := strings.Split(lastPath, ".") if style == "skip" {
nameIndex := 0 return nil
if len(name) > 2 { } else {
nameIndex = len(name) - 2 os.Remove(dst)
} }
name[nameIndex] = name[nameIndex] + "(Copy)" }
dst = dstPath
for _, v := range name { if srcfd, err = os.Open(src); err != nil {
dst += v + "." 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())
}
/**
* @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)
} }
dst = strings.TrimSuffix(dst, ".")
} }
if srcfd, err = os.Open(src); err != nil { if srcfd, err = os.Open(src); err != nil {
@@ -240,7 +279,7 @@ func GetNoDuplicateFileName(fullPath string) string {
} }
// Dir copies a whole directory recursively // Dir copies a whole directory recursively
func CopyDir(src string, dst string) error { func CopyDir(src string, dst string, style string) error {
var err error var err error
var fds []os.FileInfo var fds []os.FileInfo
var srcinfo os.FileInfo var srcinfo os.FileInfo
@@ -249,16 +288,23 @@ func CopyDir(src string, dst string) error {
return err return err
} }
if !srcinfo.IsDir() { if !srcinfo.IsDir() {
if err = CopyFile(src, dst); err != nil { if err = CopyFile(src, dst, style); err != nil {
fmt.Println(err) fmt.Println(err)
} }
return nil return nil
} }
dstPath := dst //dstPath := dst
lastPath := src[strings.LastIndex(src, "/")+1:] lastPath := src[strings.LastIndex(src, "/")+1:]
dst += "/" + lastPath dst += "/" + lastPath
for i := 0; Exists(dst); i++ { // for i := 0; Exists(dst); i++ {
dst = dstPath + "/" + lastPath + strconv.Itoa(i+1) // dst = dstPath + "/" + lastPath + strconv.Itoa(i+1)
// }
if Exists(dst) {
if style == "skip" {
return nil
} else {
os.Remove(dst)
}
} }
if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil { if err = os.MkdirAll(dst, srcinfo.Mode()); err != nil {
return err return err
@@ -271,11 +317,11 @@ func CopyDir(src string, dst string) error {
dstfp := dst //path.Join(dst, fd.Name()) dstfp := dst //path.Join(dst, fd.Name())
if fd.IsDir() { if fd.IsDir() {
if err = CopyDir(srcfp, dstfp); err != nil { if err = CopyDir(srcfp, dstfp, style); err != nil {
fmt.Println(err) fmt.Println(err)
} }
} else { } else {
if err = CopyFile(srcfp, dstfp); err != nil { if err = CopyFile(srcfp, dstfp, style); err != nil {
fmt.Println(err) fmt.Println(err)
} }
} }
@@ -332,3 +378,172 @@ func SpliceFiles(dir, path string, length int, startPoint int) error {
return nil return nil
} }
func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
switch t {
case "zip", "":
return ".zip", archiver.NewZip(), nil
case "tar":
return ".tar", archiver.NewTar(), nil
case "targz":
return ".tar.gz", archiver.NewTarGz(), nil
case "tarbz2":
return ".tar.bz2", archiver.NewTarBz2(), nil
case "tarxz":
return ".tar.xz", archiver.NewTarXz(), nil
case "tarlz4":
return ".tar.lz4", archiver.NewTarLz4(), nil
case "tarsz":
return ".tar.sz", archiver.NewTarSz(), nil
default:
return "", nil, errors.New("format not implemented")
}
}
func AddFile(ar archiver.Writer, path, commonPath string) error {
info, err := os.Stat(path)
if err != nil {
return err
}
if !info.IsDir() && !info.Mode().IsRegular() {
return nil
}
file, err := os.Open(path)
if err != nil {
return err
}
defer file.Close()
if path != commonPath {
filename := info.Name()
err = ar.Write(archiver.File{
FileInfo: archiver.FileInfo{
FileInfo: info,
CustomName: filename,
},
ReadCloser: file,
})
if err != nil {
return err
}
}
if info.IsDir() {
names, err := file.Readdirnames(0)
if err != nil {
return err
}
for _, name := range names {
err = AddFile(ar, filepath.Join(path, name), commonPath)
if err != nil {
log.Printf("Failed to archive %v", err)
}
}
}
return nil
}
func CommonPrefix(sep byte, paths ...string) string {
// Handle special cases.
switch len(paths) {
case 0:
return ""
case 1:
return path.Clean(paths[0])
}
// Note, we treat string as []byte, not []rune as is often
// done in Go. (And sep as byte, not rune). This is because
// most/all supported OS' treat paths as string of non-zero
// bytes. A filename may be displayed as a sequence of Unicode
// runes (typically encoded as UTF-8) but paths are
// not required to be valid UTF-8 or in any normalized form
// (e.g. "é" (U+00C9) and "é" (U+0065,U+0301) are different
// file names.
c := []byte(path.Clean(paths[0]))
// We add a trailing sep to handle the case where the
// common prefix directory is included in the path list
// (e.g. /home/user1, /home/user1/foo, /home/user1/bar).
// path.Clean will have cleaned off trailing / separators with
// the exception of the root directory, "/" (in which case we
// make it "//", but this will get fixed up to "/" bellow).
c = append(c, sep)
// Ignore the first path since it's already in c
for _, v := range paths[1:] {
// Clean up each path before testing it
v = path.Clean(v) + string(sep)
// Find the first non-common byte and truncate c
if len(v) < len(c) {
c = c[:len(v)]
}
for i := 0; i < len(c); i++ {
if v[i] != c[i] {
c = c[:i]
break
}
}
}
// Remove trailing non-separator characters and the final separator
for i := len(c) - 1; i >= 0; i-- {
if c[i] == sep {
c = c[:i]
break
}
}
return string(c)
}
func GetFileOrDirSize(path string) (int64, error) {
fileInfo, err := os.Stat(path)
if err != nil {
return 0, err
}
if fileInfo.IsDir() {
return DirSizeB(path + "/")
}
return fileInfo.Size(), nil
}
//getFileSize get file size by path(B)
func DirSizeB(path string) (int64, error) {
var size int64
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
if !info.IsDir() {
size += info.Size()
}
return 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
}

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,28 +1,41 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2021-09-30 18:18:14
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-18 17:30:38
* @FilePath: /CasaOS/pkg/utils/jwt/jwt.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package jwt package jwt
import ( import (
"time" "time"
jwt "github.com/golang-jwt/jwt" jwt "github.com/golang-jwt/jwt/v4"
) )
type Claims struct { type Claims struct {
UserName string `json:"username"` Username string `json:"username"`
PassWord string `json:"password"` PassWord string `json:"password"`
jwt.StandardClaims Id int `json:"id"`
jwt.RegisteredClaims
} }
var jwtSecret []byte var jwtSecret []byte
//创建token //创建token
func GenerateToken(username, password string) (string, error) { func GenerateToken(username, password string, id int, issuer string, t time.Duration) (string, error) {
expireTime := time.Now().AddDate(999, 0, 0)
clims := Claims{ clims := Claims{
username, username,
password, password,
jwt.StandardClaims{ id,
ExpiresAt: expireTime.Unix(), jwt.RegisteredClaims{
Issuer: "gin-blog", ExpiresAt: jwt.NewNumericDate(time.Now().Add(t)),
IssuedAt: jwt.NewNumericDate(time.Now()),
NotBefore: jwt.NewNumericDate(time.Now()),
Issuer: issuer,
}, },
} }
@@ -33,13 +46,17 @@ func GenerateToken(username, password string) (string, error) {
} }
//解析token //解析token
func ParseToken(token string) (*Claims, error) { func ParseToken(token string, valid bool) (*Claims, error) {
tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) { tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
return jwtSecret, nil return jwtSecret, nil
}) })
if tokenClaims != nil { if tokenClaims != nil {
if clims, ok := tokenClaims.Claims.(*Claims); ok && tokenClaims.Valid { if clims, ok := tokenClaims.Claims.(*Claims); ok {
return clims, nil if valid && tokenClaims.Valid {
return clims, nil
} else if !valid {
return clims, nil
}
} }
} }
return nil, err return nil, err

View File

@@ -1,54 +1,75 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-06-17 14:01:25
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-18 17:31:15
* @FilePath: /CasaOS/pkg/utils/jwt/jwt_helper.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package jwt package jwt
import ( import (
"fmt" "fmt"
"net/http" "strconv"
"time"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
func JWT(swagHandler gin.HandlerFunc) gin.HandlerFunc { func JWT() gin.HandlerFunc {
return func(c *gin.Context) { return func(c *gin.Context) {
var code int var code int
code = oasis_err2.SUCCESS code = common_err.SUCCESS
token := c.GetHeader("Authorization") token := c.GetHeader("Authorization")
if len(token) == 0 { if len(token) == 0 {
token = c.Query("token") token = c.Query("token")
} }
if token == "" { if token == "" {
code = oasis_err2.INVALID_PARAMS code = common_err.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 { claims, err := ParseToken(token, false)
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)})
//_, err := ParseToken(token)
if err != nil {
code = common_err.ERROR_AUTH_TOKEN
} else if (c.Request.URL.Path == "/v1/file" || c.Request.URL.Path == "/v1/image" || c.Request.URL.Path == "/v1/file/upload" || c.Request.URL.Path == "/v1/batch") && claims.VerifyIssuer("casaos", true) {
//Special treatment
} else if !claims.VerifyExpiresAt(time.Now(), true) || !claims.VerifyIssuer("casaos", true) {
code = common_err.ERROR_AUTH_TOKEN
}
if code != common_err.SUCCESS {
c.JSON(code, model.Result{Success: code, Message: common_err.GetMsg(code)})
c.Abort() c.Abort()
return return
} }
c.Request.Header.Add("user_id", strconv.Itoa(claims.Id))
c.Next() c.Next()
} }
} }
//获取token //get AccessToken
func GetToken(username, pwd string) string { func GetAccessToken(username, pwd string, id int) string {
token, err := GenerateToken(username, pwd) token, err := GenerateToken(username, pwd, id, "casaos", 3*time.Hour*time.Duration(1))
if err == nil { if err == nil {
return token return token
} else { } else {
loger2.NewOLoger().Fatal(fmt.Sprintf("Get Token Fail: %V", err)) loger2.Error(fmt.Sprintf("Get Token Fail: %V", err))
return ""
}
}
func GetRefreshToken(username, pwd string, id int) string {
token, err := GenerateToken(username, pwd, id, "refresh", 7*24*time.Hour*time.Duration(1))
if err == nil {
return token
} else {
loger2.Error(fmt.Sprintf("Get Token Fail: %V", err))
return "" return ""
} }
} }

View File

@@ -1,109 +1,92 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-06-02 15:09:38
* @LastEditors: LinkLeong
* @LastEditTime: 2022-06-27 15:47:49
* @FilePath: /CasaOS/pkg/utils/loger/log.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package loger package loger
import ( import (
"fmt" "fmt"
"log"
"os" "os"
"path"
"path/filepath" "path/filepath"
"runtime" "runtime"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
file2 "github.com/IceWhaleTech/CasaOS/pkg/utils/file" "go.uber.org/zap"
"go.uber.org/zap/zapcore"
"gopkg.in/natefinch/lumberjack.v2"
) )
//定义一个int的别名 var loggers *zap.Logger
type Level int
type OLog interface { func getFileLogWriter() (writeSyncer zapcore.WriteSyncer) {
Debug(v ...interface{}) // 使用 lumberjack 实现 log rotate
Info(v ...interface{}) lumberJackLogger := &lumberjack.Logger{
Warn(v ...interface{}) Filename: filepath.Join(config.AppInfo.LogPath, fmt.Sprintf("%s.%s",
Error(v ...interface{}) config.AppInfo.LogSaveName,
Fatal(v ...interface{}) config.AppInfo.LogFileExt,
Path() string )),
} MaxSize: 10,
MaxBackups: 60,
type oLog struct { MaxAge: 1,
} Compress: true,
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 LogSetup() {
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) return zapcore.AddSync(lumberJackLogger)
} }
func (o *oLog) Path() string {
filePath := fmt.Sprintf("%s", config.AppInfo.LogSavePath) func LogInit() {
fileName := fmt.Sprintf("%s.%s", encoderConfig := zap.NewProductionEncoderConfig()
config.AppInfo.LogSaveName, encoderConfig.EncodeTime = zapcore.EpochTimeEncoder
config.AppInfo.LogFileExt, encoder := zapcore.NewJSONEncoder(encoderConfig)
fileWriteSyncer := getFileLogWriter()
core := zapcore.NewTee(
zapcore.NewCore(encoder, zapcore.AddSync(os.Stdout), zapcore.InfoLevel),
zapcore.NewCore(encoder, fileWriteSyncer, zapcore.InfoLevel),
) )
return filePath + fileName loggers = zap.New(core)
}
func (o *oLog) Debug(v ...interface{}) {
setPrefix(DEBUG)
logger.Println(v)
} }
func (o *oLog) Info(v ...interface{}) { func Info(message string, fields ...zap.Field) {
setPrefix(INFO) callerFields := getCallerInfoForLog()
logger.Println(v) fields = append(fields, callerFields...)
loggers.Info(message, fields...)
} }
func (o *oLog) Warn(v ...interface{}) { func Debug(message string, fields ...zap.Field) {
setPrefix(WARN) callerFields := getCallerInfoForLog()
logger.Println(v) fields = append(fields, callerFields...)
loggers.Debug(message, fields...)
} }
func (o *oLog) Error(v ...interface{}) { func Error(message string, fields ...zap.Field) {
setPrefix(ERROR) callerFields := getCallerInfoForLog()
logger.Println(v) fields = append(fields, callerFields...)
loggers.Error(message, fields...)
} }
func (o *oLog) Fatal(v ...interface{}) { func Warn(message string, fields ...zap.Field) {
setPrefix(FATAL) callerFields := getCallerInfoForLog()
logger.Println(v) fields = append(fields, callerFields...)
loggers.Warn(message, fields...)
} }
func setPrefix(level Level) { func getCallerInfoForLog() (callerFields []zap.Field) {
_, file, line, ok := runtime.Caller(DefaultCallerDepth)
if ok { pc, file, line, ok := runtime.Caller(2) // 回溯两层,拿到写日志的调用方的函数信息
logPrefix = fmt.Sprintf("[%s][%s:%d]", levelFlags[level], filepath.Base(file), line) if !ok {
} else { return
logPrefix = fmt.Sprintf("[%s]", levelFlags[level])
} }
funcName := runtime.FuncForPC(pc).Name()
funcName = path.Base(funcName) //Base函数返回路径的最后一个元素只保留函数名
logger.SetPrefix(logPrefix) callerFields = append(callerFields, zap.String("func", funcName), zap.String("file", file), zap.Int("line", line))
} return
func NewOLoger() OLog {
return &oLog{}
} }

View File

@@ -1,24 +1,27 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-21 15:27:53
* @FilePath: /CasaOS/pkg/utils/version/version.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
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) {
@@ -33,51 +36,9 @@ func IsNeedUpdate() (bool, model.Version) {
if a > b { if a > b {
return true, version return true, version
} }
} if a < b {
return false, version return false, version
}
func IsClientNeedUpdate() (bool, model.Version) {
var version model.Version
v := httper.OasisGet(config.ServerInfo.ServerApi + "/v1/sys/client/version")
data := gjson.Get(v, "data")
json2.Unmarshal([]byte(data.String()), &version)
v1 := strings.Split(version.Version, ".")
v2 := strings.Split(types.CURRENTVERSION, ".")
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, 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
}

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,165 +1,31 @@
package route package route
import ( import (
"encoding/xml" "os"
"fmt"
"runtime"
"strconv" "strconv"
"strings" "strings"
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/model/system_app"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command" "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper" "github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
) )
func InitFunction() { func InitFunction() {
go checkSystemApp()
Update2_3() ShellInit()
CheckSerialDiskMount() CheckSerialDiskMount()
CheckToken2_11() CheckToken2_11()
ImportApplications() ImportApplications()
ChangeAPIUrl() ChangeAPIUrl()
InitSystemApplication()
MoveUserToDB()
} }
var syncIsExistence = false
func installSyncthing(appId string) {
var appInfo model.ServerAppList
m := model.CustomizationPostData{}
var dockerImage string
var dockerImageVersion string
appInfo = service.MyService.Casa().GetServerAppInfo(appId, "system", "us_en")
dockerImage = appInfo.Image
dockerImageVersion = appInfo.ImageVersion
if len(appInfo.ImageVersion) == 0 {
dockerImageVersion = "latest"
}
if appInfo.NetworkModel != "host" {
for i := 0; i < len(appInfo.Ports); i++ {
if p, _ := strconv.Atoi(appInfo.Ports[i].ContainerPort); port.IsPortAvailable(p, appInfo.Ports[i].Protocol) {
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
} else {
if appInfo.Ports[i].Protocol == "tcp" {
if p, err := port.GetAvailablePort("tcp"); err == nil {
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
}
} else if appInfo.Ports[i].Protocol == "upd" {
if p, err := port.GetAvailablePort("udp"); err == nil {
appInfo.Ports[i].CommendPort = strconv.Itoa(p)
}
}
}
if appInfo.Ports[i].Type == 0 {
appInfo.PortMap = appInfo.Ports[i].CommendPort
}
}
}
for i := 0; i < len(appInfo.Devices); i++ {
if !file.CheckNotExist(appInfo.Devices[i].ContainerPath) {
appInfo.Devices[i].Path = appInfo.Devices[i].ContainerPath
}
}
if len(appInfo.Tip) > 0 {
appInfo.Tip = env_helper.ReplaceStringDefaultENV(appInfo.Tip)
}
appInfo.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20
id := uuid.NewV4().String()
installLog := model2.AppNotify{}
// step下载镜像
err := service.MyService.Docker().DockerPullImage(dockerImage+":"+dockerImageVersion, installLog)
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 {
continue
}
if strings.Contains(info.Config.Image, "linuxserver/syncthing") {
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 := ""
for _, i := range info.HostConfig.Mounts {
if i.Target == "/config" {
path = i.Source
break
}
}
content := file.ReadFullFile(path + "config.xml")
syncConfig := &system_app.SyncConfig{}
xml.Unmarshal(content, &syncConfig)
config.SystemConfigInfo.SyncKey = syncConfig.Key
break
}
}
if !syncIsExistence {
installSyncthing("74")
}
}
func CheckSerialDiskMount() { func CheckSerialDiskMount() {
// check mount point // check mount point
dbList := service.MyService.Disk().GetSerialAll() dbList := service.MyService.Disk().GetSerialAll()
@@ -197,10 +63,14 @@ func CheckSerialDiskMount() {
} }
} }
service.MyService.Disk().RemoveLSBLKCache() service.MyService.Disk().RemoveLSBLKCache()
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AutoRemoveUnuseDir") command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;AutoRemoveUnuseDir")
} }
func Update2_3() { func ShellInit() {
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/assist.sh") command.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/assist.sh | bash")
if !file.CheckNotExist("/casaOS") {
command.OnlyExec("source /casaOS/server/shell/update.sh ;")
command.OnlyExec("source " + config.AppInfo.ShellPath + "/delete-old-service.sh ;")
}
} }
func CheckToken2_11() { func CheckToken2_11() {
@@ -210,43 +80,14 @@ func CheckToken2_11() {
config.Cfg.Section("server").Key("Token").SetValue(token()) config.Cfg.Section("server").Key("Token").SetValue(token())
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath) 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 { if len(config.UserInfo.Description) == 0 {
config.Cfg.Section("user").Key("Description").SetValue("nothing") config.Cfg.Section("user").Key("Description").SetValue("nothing")
config.UserInfo.Description = "nothing" config.UserInfo.Description = "nothing"
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath) 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") { 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().UpdateUSBAutoMount("False")
service.MyService.System().ExecUSBAutoMountShell("False") service.MyService.System().ExecUSBAutoMountShell("False")
} }
@@ -277,22 +118,23 @@ func ChangeAPIUrl() {
} }
// 0.3.1 //0.3.3
func InitSystemApplication() { //Transferring user data to the database
list := service.MyService.App().GetApplicationList() func MoveUserToDB() {
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" if len(config.UserInfo.UserName) > 0 && service.MyService.User().GetUserInfoByUserName(config.UserInfo.UserName).Id == 0 {
application.Icon = "/ui/img/CasaConnect.svg" user := model2.UserDBModel{}
application.Type = "system" user.Username = config.UserInfo.UserName
application.Order = 0 user.Email = config.UserInfo.Email
user.Nickname = config.UserInfo.NickName
user.Password = encryption.GetMD5ByStr(config.UserInfo.PWD)
user.Role = "admin"
user = service.MyService.User().CreateUser(user)
if user.Id > 0 {
userPath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id)
file.MkDir(userPath)
os.Rename("/casaOS/server/conf/app_order.json", userPath+"/app_order.json")
}
service.MyService.App().CreateApplication(application)
} }
} }

275
route/periodical.go Normal file
View File

@@ -0,0 +1,275 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-01 15:11:36
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-21 15:25:07
* @FilePath: /CasaOS/route/periodical.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package route
import (
"reflect"
"strconv"
"strings"
"time"
"unsafe"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/service"
)
func SendNetINfoBySocket() {
netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{}
nets := service.MyService.System().GetNet(true)
for _, n := range netList {
for _, netCardName := range nets {
if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.System().GetNetState(n.Name))
item.Time = time.Now().Unix()
newNet = append(newNet, item)
break
}
}
}
service.MyService.Notify().SendNetInfoBySocket(newNet)
}
func SendCPUBySocket() {
cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum()
cpuData := make(map[string]interface{})
cpuData["percent"] = cpu
cpuData["num"] = num
service.MyService.Notify().SendCPUInfoBySocket(cpuData)
}
func SendMemBySocket() {
service.MyService.Notify().SendMemInfoBySocket(service.MyService.System().GetMemInfo())
}
func SendDiskBySocket() {
list := service.MyService.Disk().LSBLK(true)
summary := model.Summary{}
healthy := true
findSystem := 0
for i := 0; i < len(list); i++ {
if len(list[i].Children) > 0 && findSystem == 0 {
for j := 0; j < len(list[i].Children); j++ {
if len(list[i].Children[j].Children) > 0 {
for _, v := range list[i].Children[j].Children {
if v.MountPoint == "/" {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
} else {
if list[i].Children[j].MountPoint == "/" {
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
}
}
if findSystem == 1 {
findSystem += 1
continue
}
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
healthy = true
} else {
healthy = temp.SmartStatus.Passed
}
//list[i].Temperature = temp.Temperature.Current
if len(list[i].Children) > 0 {
for _, v := range list[i].Children {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
}
}
}
}
summary.Health = healthy
service.MyService.Notify().SendDiskInfoBySocket(summary)
}
func SendUSBBySocket() {
usbList := service.MyService.Disk().LSBLK(false)
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
temp := model.DriveUSB{}
temp.Model = v.Model
temp.Name = v.Name
temp.Size = v.Size
mountTemp := true
if len(v.Children) == 0 {
mountTemp = false
}
for _, child := range v.Children {
if len(child.MountPoint) > 0 {
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
temp.Used += used
} else {
mountTemp = false
}
}
temp.Mount = mountTemp
usb = append(usb, temp)
}
}
service.MyService.Notify().SendUSBInfoBySocket(usb)
}
func SendAllHardwareStatusBySocket() {
netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{}
nets := service.MyService.System().GetNet(true)
for _, n := range netList {
for _, netCardName := range nets {
if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.System().GetNetState(n.Name))
item.Time = time.Now().Unix()
newNet = append(newNet, item)
break
}
}
}
cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum()
cpuData := make(map[string]interface{})
cpuData["percent"] = cpu
cpuData["num"] = num
list := service.MyService.Disk().LSBLK(true)
summary := model.Summary{}
healthy := true
findSystem := 0
for i := 0; i < len(list); i++ {
if len(list[i].Children) > 0 && findSystem == 0 {
for j := 0; j < len(list[i].Children); j++ {
if len(list[i].Children[j].Children) > 0 {
for _, v := range list[i].Children[j].Children {
if v.MountPoint == "/" {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
} else {
if list[i].Children[j].MountPoint == "/" {
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
findSystem = 1
break
}
}
}
}
if findSystem == 1 {
findSystem += 1
continue
}
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) {
healthy = true
} else {
healthy = temp.SmartStatus.Passed
}
if len(list[i].Children) > 0 {
for _, v := range list[i].Children {
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
summary.Size += s
summary.Avail += a
summary.Used += u
}
}
}
}
summary.Health = healthy
usbList := service.MyService.Disk().LSBLK(false)
usb := []model.DriveUSB{}
for _, v := range usbList {
if v.Tran == "usb" {
temp := model.DriveUSB{}
temp.Model = v.Model
temp.Name = v.Name
temp.Size = v.Size
mountTemp := true
if len(v.Children) == 0 {
mountTemp = false
}
for _, child := range v.Children {
if len(child.MountPoint) > 0 {
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
used, _ := strconv.ParseUint(child.FSUsed, 10, 64)
temp.Used += used
} else {
mountTemp = false
}
}
temp.Mount = mountTemp
usb = append(usb, temp)
}
}
memInfo := service.MyService.System().GetMemInfo()
service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memInfo, cpuData, newNet)
}

View File

@@ -8,11 +8,11 @@ import (
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt" 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/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 var OnlineDemo bool = false
func InitRouter() *gin.Engine { func InitRouter() *gin.Engine {
@@ -20,262 +20,203 @@ 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.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/user/refresh", v1.PostUserRefreshToken)
// No short-term modifications
r.GET("/v1/users/image", v1.GetUserImage)
r.GET("/v1/guide/check", v1.GetGuideCheck) r.GET("/v1/users/status", v1.GetUserStatus) //init/check
//r.GET("/v1/guide/check", v1.GetGuideCheck) // /v1/sys/guide_check
r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug
r.GET("/v1/sys/socket-port", v1.GetSystemSocketPort) //sys/socket_port
r.GET("/v1/debug", v1.GetSystemConfigDebug)
//set user
r.POST("/v1/user/setusernamepwd", v1.Set_Name_Pwd)
//get user info
r.GET("/v1/user/info", v1.GetUserInfo)
//get user info
r.GET("/v1/person/shareid", v1.GetPersonShareId)
v1Group := r.Group("/v1") v1Group := r.Group("/v1")
v1Group.Use(jwt2.JWT(swagHandler)) v1Group.Use(jwt2.JWT())
{ {
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)
//chang head v1UsersGroup.GET("/current/custom/:key", v1.GetUserCustomConf)
v1UserGroup.POST("/head", v1.PostUserHead) v1UsersGroup.POST("/current/custom/:key", v1.PostUserCustomConf)
//chang user name v1UsersGroup.DELETE("/current/custom/:key", v1.DeleteUserCustomConf)
v1UserGroup.PUT("/username", v1.PutUserName)
//chang pwd
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) 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)
} }
v1ZiMaGroup := v1Group.Group("/zima") v1AppsGroup := v1Group.Group("/apps")
v1ZiMaGroup.Use() v1AppsGroup.Use()
{ {
//获取cpu信息 v1AppsGroup.GET("", v1.AppList) //list
v1ZiMaGroup.GET("/getcpuinfo", v1.CupInfo) v1AppsGroup.GET("/:id", v1.AppInfo)
//获取内存信息
v1ZiMaGroup.GET("/getmeminfo", v1.MemInfo)
//获取硬盘信息
v1ZiMaGroup.GET("/getdiskinfo", v1.DiskInfo)
//获取网络信息
v1ZiMaGroup.GET("/getnetinfo", v1.NetInfo)
//获取系统信息
v1ZiMaGroup.GET("/sysinfo", v1.SysInfo)
} }
v1DDNSGroup := v1Group.Group("/ddns") v1ContainerGroup := v1Group.Group("/container")
v1DDNSGroup.Use() v1ContainerGroup.Use()
{ {
//获取ddns列表 v1ContainerGroup.GET("", v1.MyAppList) ///my/list
v1DDNSGroup.GET("/getlist", v1.DDNSGetDomainList) v1ContainerGroup.GET("/usage", v1.AppUsageList)
//测试连接性 v1ContainerGroup.GET("/:id", v1.ContainerUpdateInfo) ///update/:id/info
v1DDNSGroup.GET("/ping/:api_host", v1.DDNSPing) v1ContainerGroup.GET("/:id/logs", v1.ContainerLog) // /app/logs/:id
//获取ip v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) //app/install/config
v1DDNSGroup.GET("/ip", v1.DDNSGetIP)
//设置ddns v1ContainerGroup.GET("/:id/state", v1.GetContainerState) //app/state/:id ?state=install_progress
v1DDNSGroup.POST("/set", v1.DDNSAddConfig) // there are problems, temporarily do not deal with
//获取ddns v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) //app/terminal/:id
v1DDNSGroup.GET("/list", v1.DDNSConfigList) v1ContainerGroup.POST("", v1.InstallApp) //app/install
//获取ddns //v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id
v1DDNSGroup.DELETE("/delete/:id", v1.DDNSDelete)
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)
} }
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/:id", v1.InstallApp)
//卸载app
v1AppGroup.DELETE("/uninstall/:id", v1.UnInstallApp)
//获取安装进度
v1AppGroup.GET("/speed/:id", v1.GetInstallSpeed)
//获取进度
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("/check", v1.CheckVersion) v1SysGroup.GET("/version", v1.GetSystemCheckVersion) //version/check
v1SysGroup.GET("/hardware/info", v1.GetSystemHardwareInfo)
v1SysGroup.GET("/client/version", v1.GetClientVersion)
v1SysGroup.POST("/update", v1.SystemUpdate) v1SysGroup.POST("/update", v1.SystemUpdate)
v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) //hardware/info
v1SysGroup.GET("/wsssh", v1.WsSsh) v1SysGroup.GET("/wsssh", v1.WsSsh)
v1SysGroup.GET("/config", v1.GetSystemConfig) v1SysGroup.POST("/ssh-login", v1.PostSshLogin)
v1SysGroup.GET("/error/logs", v1.GetCasaOSErrorLogs) //v1SysGroup.GET("/config", v1.GetSystemConfig) //delete
v1SysGroup.POST("/config", v1.PostSetSystemConfig) //v1SysGroup.POST("/config", v1.PostSetSystemConfig)
v1SysGroup.GET("/widget/config", v1.GetWidgetConfig) v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) //error/logs
v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig) //v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete
//v1SysGroup.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.GET("/port", v1.GetCasaOSPort)
v1SysGroup.PUT("/port", v1.PutCasaOSPort) v1SysGroup.PUT("/port", v1.PutCasaOSPort)
v1SysGroup.POST("/kill", v1.PostKillCasaOS)
v1SysGroup.GET("/info", v1.Info)
v1SysGroup.PUT("/usb/off", v1.PutSystemOffUSBAutoMount)
v1SysGroup.PUT("/usb/on", v1.PutSystemOnUSBAutoMount)
v1SysGroup.GET("/usb", v1.GetSystemUSBAutoMount)
} }
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("/new/download", v1.GetFileDownloadNew)
v1FileGroup.POST("/operate", v1.PostOperateFileOrDir)
v1FileGroup.DELETE("/delete", v1.DeleteFile)
v1FileGroup.PUT("/update", v1.PutFileContent)
v1FileGroup.GET("/image", v1.GetFileImage)
//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)
v1ShareGroup.GET("/list", v1.GetShareDirList)
v1ShareGroup.GET("/info/:id", v1.GetShareDirInfo)
v1ShareGroup.PUT("/update/:id", v1.PutShareDirEdit)
}
v1TaskGroup := v1Group.Group("/task")
v1TaskGroup.Use()
{
v1TaskGroup.GET("/list", v1.GetTaskList)
v1TaskGroup.PUT("/update", v1.PutTaskUpdate)
v1TaskGroup.POST("/add", v1.PostTaskAdd)
v1TaskGroup.PUT("/completion/:id", v1.PutTaskMarkerCompletion)
v1BatchGroup.DELETE("", v1.DeleteFile) //file/delete
v1BatchGroup.DELETE("/:id/task", v1.DeleteOperateFileOrDir)
v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) //file/operate
v1BatchGroup.GET("", v1.GetDownloadFile)
}
v1ImageGroup := v1Group.Group("/image")
v1ImageGroup.Use()
{
v1ImageGroup.GET("", v1.GetFileImage)
} }
v1NotifyGroup := v1Group.Group("/notify") v1DisksGroup := v1Group.Group("/disks")
v1NotifyGroup.Use() v1DisksGroup.Use()
{ {
v1NotifyGroup.GET("/ws", v1.NotifyWS) //v1DiskGroup.GET("/check", v1.GetDiskCheck) //delete
v1NotifyGroup.PUT("/read/:id", v1.PutNotifyRead) //v1DisksGroup.GET("", v1.GetDiskInfo)
//v1DisksGroup.POST("", v1.PostMountDisk)
v1DisksGroup.GET("", v1.GetDiskList)
// //format storage
// v1DiskGroup.POST("/format", v1.PostDiskFormat)
// //mount SATA disk
// v1DiskGroup.POST("/mount", v1.PostMountDisk)
// //umount sata disk
// v1DiskGroup.POST("/umount", v1.PostDiskUmount)
//v1DiskGroup.GET("/type", v1.FormatDiskType)//delete
v1DisksGroup.DELETE("/part", v1.RemovePartition) //disk/delpart
} }
v1PersonGroup := v1Group.Group("/person") v1StorageGroup := v1Group.Group("/storage")
v1PersonGroup.Use() v1StorageGroup.Use()
{ {
v1PersonGroup.GET("/detection", v1.GetPersonDetection) v1StorageGroup.POST("", v1.PostDiskAddPartition)
v1PersonGroup.GET("/users", v1.GetPersonFriend)
v1PersonGroup.POST("/user/:shareids", v1.PostAddPersonFriend)
v1PersonGroup.DELETE("/user/:shareid", v1.DeletePersonFriend)
v1PersonGroup.GET("/directory", v1.GetPersonDirectory)
v1PersonGroup.GET("/file", v1.GetPersonFile)
v1PersonGroup.GET("/refile/:uuid", v1.GetPersonReFile)
v1PersonGroup.PUT("/remarks/:shareid", v1.PutPersonRemarks)
v1PersonGroup.GET("/list", v1.GetPersonDownloadList)
v1PersonGroup.DELETE("/file/:uuid", v1.DeletePersonDownloadFile)
v1PersonGroup.POST("/share", v1.PostPersonShare) v1StorageGroup.PUT("", v1.PostDiskFormat)
v1PersonGroup.POST("/file/:shareid", v1.PostPersonFile)
v1PersonGroup.GET("/share", v1.GetPersonShare)
v1PersonGroup.POST("/down/dir", v1.PostPersonDownDir)
v1PersonGroup.GET("/down/dir", v1.GetPersonDownDir)
v1PersonGroup.PUT("/block/:shareid", v1.PutPersonBlock)
v1PersonGroup.GET("/public", v1.GetPersonPublic)
v1PersonGroup.PUT("/friend/:shareid", v1.PutPersonAgreeFriend)
v1PersonGroup.PUT("/write/:shareid", v1.PutPersonWrite)
v1PersonGroup.GET("/image/thumbnail/:shareid", v1.GetPersonImageThumbnail)
v1StorageGroup.DELETE("", v1.PostDiskUmount)
} }
v1AnalyseGroup := v1Group.Group("/analyse")
v1AnalyseGroup.Use()
{
v1AnalyseGroup.POST("/app", v1.PostAppAnalyse)
}
v1Group.GET("/sync/config", v1.GetSyncConfig)
v1Group.Any("/syncthing/*url", v1.SyncToSyncthing)
} }
return r return r
} }

60
route/socket.go Normal file
View File

@@ -0,0 +1,60 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-23 17:18:56
* @LastEditors: LinkLeong
* @LastEditTime: 2022-06-09 21:48:10
* @FilePath: /CasaOS/route/socket.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package route
import (
"strconv"
"time"
"github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/service"
f "github.com/ambelovsky/gosf"
)
func SocketInit(msg chan notify.Message) {
// set socket port
socketPort := 0
if len(config.ServerInfo.SocketPort) == 0 {
socketPort, _ = port.GetAvailablePort("tcp")
config.ServerInfo.SocketPort = strconv.Itoa(socketPort)
config.Cfg.Section("server").Key("SocketPort").SetValue(strconv.Itoa(socketPort))
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
} else {
socketPort, _ = strconv.Atoi(config.ServerInfo.SocketPort)
if !port.IsPortAvailable(socketPort, "tcp") {
socketPort, _ := port.GetAvailablePort("tcp")
config.ServerInfo.SocketPort = strconv.Itoa(socketPort)
config.Cfg.Section("server").Key("SocketPort").SetValue(strconv.Itoa(socketPort))
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
}
}
f.OnConnect(func(c *f.Client, request *f.Request) {
service.ClientCount += 1
})
f.OnDisconnect(func(c *f.Client, request *f.Request) {
service.ClientCount -= 1
})
go func(msg chan notify.Message) {
for v := range msg {
f.Broadcast("", v.Path, &v.Msg)
time.Sleep(time.Millisecond * 100)
}
}(msg)
f.Startup(map[string]interface{}{
"port": socketPort})
}

View File

@@ -1,9 +1,20 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-06-23 17:27:43
* @LastEditors: LinkLeong
* @LastEditTime: 2022-06-23 17:27:48
* @FilePath: /CasaOS/route/ui.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package route package route
import ( import (
"html/template"
"github.com/IceWhaleTech/CasaOS/web" "github.com/IceWhaleTech/CasaOS/web"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"html/template"
) )
func WebUIHome(c *gin.Context) { func WebUIHome(c *gin.Context) {

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

@@ -3,12 +3,12 @@ package v1
import ( import (
"encoding/json" "encoding/json"
"io/ioutil" "io/ioutil"
"net/http"
"strconv" "strconv"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"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 +35,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 +63,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 +86,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 +102,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 +120,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 +136,7 @@ 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})
} }
// @Summary 应用详情 // @Summary 应用详情
@@ -144,7 +151,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) {
@@ -209,9 +220,9 @@ func AppInfo(c *gin.Context) {
// 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.MaxMemory = service.MyService.ZiMa().GetMemInfo().Total >> 20 info.MaxMemory = (service.MyService.System().GetMemInfo()["total"]).(uint64) >> 20
c.JSON(http.StatusOK, &model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info}) c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info})
} }
// @Summary 获取远程分类列表 // @Summary 获取远程分类列表
@@ -222,16 +233,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 +259,5 @@ 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))
} }

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

@@ -9,9 +9,10 @@ import (
"time" "time"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/model/notify"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
@@ -28,7 +29,42 @@ var diskMap = make(map[string]string)
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /disk/list [get] // @Router /disk/list [get]
func GetDiskList(c *gin.Context) { func GetDiskList(c *gin.Context) {
path := c.Query("path")
if len(path) > 0 {
m := service.MyService.Disk().GetDiskInfo(path)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
return
}
t := c.DefaultQuery("type", "")
list := service.MyService.Disk().LSBLK(false) list := service.MyService.Disk().LSBLK(false)
if t == "usb" {
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(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
return
}
dbList := service.MyService.Disk().GetSerialAll() dbList := service.MyService.Disk().GetSerialAll()
part := make(map[string]int64, len(dbList)) part := make(map[string]int64, len(dbList))
for _, v := range dbList { for _, v := range dbList {
@@ -111,7 +147,7 @@ func GetDiskList(c *gin.Context) {
continue continue
} }
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" { if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
temp := service.MyService.Disk().SmartCTL(list[i].Path) temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) { if reflect.DeepEqual(temp, model.SmartctlA{}) {
temp.SmartStatus.Passed = true temp.SmartStatus.Passed = true
@@ -154,7 +190,7 @@ func GetDiskList(c *gin.Context) {
data["storage"] = storage data["storage"] = storage
data["avail"] = avail data["avail"] = avail
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
} }
// @Summary get disk list // @Summary get disk list
@@ -171,7 +207,7 @@ func GetPlugInDisks(c *gin.Context) {
for _, item := range list { for _, item := range list {
result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path)) 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}) c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: result})
} }
// @Summary disk detail // @Summary disk detail
@@ -185,53 +221,10 @@ func GetPlugInDisks(c *gin.Context) {
func GetDiskInfo(c *gin.Context) { func GetDiskInfo(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{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)}) c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
} }
m := service.MyService.Disk().GetDiskInfo(path) 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}) c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
}
// @Summary format storage
// @Produce application/json
// @Accept multipart/form-data
// @Tags disk
// @Security ApiKeyAuth
// @Param path formData string true "e.g. /dev/sda1"
// @Param pwd formData string true "user password"
// @Param volume formData string true "mount point"
// @Success 200 {string} string "ok"
// @Router /disk/format [post]
func 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 获取支持的格式 // @Summary 获取支持的格式
@@ -243,7 +236,7 @@ func FormatDisk(c *gin.Context) {
// @Router /disk/type [get] // @Router /disk/type [get]
func FormatDiskType(c *gin.Context) { func FormatDiskType(c *gin.Context) {
var strArr = [4]string{"fat32", "ntfs", "ext4", "exfat"} 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}) c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: strArr})
} }
@@ -256,15 +249,17 @@ func FormatDiskType(c *gin.Context) {
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /disk/delpart [delete] // @Router /disk/delpart [delete]
func RemovePartition(c *gin.Context) { func RemovePartition(c *gin.Context) {
path := c.PostForm("path") js := make(map[string]string)
c.ShouldBind(&js)
path := js["path"]
if len(path) == 0 { if len(path) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)}) c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
} }
var p = path[:len(path)-1] var p = path[:len(path)-1]
var n = path[len(path)-1:] var n = path[len(path)-1:]
service.MyService.Disk().DelPartition(p, n) service.MyService.Disk().DelPartition(p, n)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary add storage // @Summary add storage
@@ -278,32 +273,42 @@ func RemovePartition(c *gin.Context) {
// @Param format formData bool true "need format(true)" // @Param format formData bool true "need format(true)"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /disk/storage [post] // @Router /disk/storage [post]
func AddPartition(c *gin.Context) { func PostDiskAddPartition(c *gin.Context) {
name := c.PostForm("name")
path := c.PostForm("path") js := make(map[string]interface{})
format, _ := strconv.ParseBool(c.PostForm("format")) c.ShouldBind(&js)
path := js["path"].(string)
name := js["name"].(string)
format := js["format"].(bool)
if len(name) == 0 || len(path) == 0 { 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)}) c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return return
} }
if _, ok := diskMap[path]; ok { if _, ok := diskMap[path]; ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
return return
} }
if !file.CheckNotExist("/DATA/" + name) { if !file.CheckNotExist("/DATA/" + name) {
// /mnt/name exist // /mnt/name exist
c.JSON(http.StatusOK, model.Result{Success: oasis_err.NAME_NOT_AVAILABLE, Message: oasis_err.GetMsg(oasis_err.NAME_NOT_AVAILABLE)}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
return return
} }
diskMap[path] = "busying" diskMap[path] = "busying"
currentDisk := service.MyService.Disk().GetDiskInfo(path) currentDisk := service.MyService.Disk().GetDiskInfo(path)
if !format { if !format {
if len(currentDisk.Children) != 1 || !(len(currentDisk.Children) > 0 && currentDisk.Children[0].FsType == "ext4") { 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) delete(diskMap, path)
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
return return
} }
} else { } else {
// format := service.MyService.Disk().FormatDisk(path+"1", "ext4")
// if len(format) == 0 {
// delete(diskMap, path)
// c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
// return
// }
service.MyService.Disk().AddPartition(path) service.MyService.Disk().AddPartition(path)
} }
@@ -319,7 +324,7 @@ func AddPartition(c *gin.Context) {
} }
currentDisk = service.MyService.Disk().GetDiskInfo(path) currentDisk = service.MyService.Disk().GetDiskInfo(path)
if len(currentDisk.Children) != 1 { 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)}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
return return
} }
@@ -338,47 +343,61 @@ func AddPartition(c *gin.Context) {
service.MyService.Disk().RemoveLSBLKCache() service.MyService.Disk().RemoveLSBLKCache()
delete(diskMap, path) delete(diskMap, path)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
//send notify to client
msg := notify.StorageMessage{}
msg.Action = "ADDED"
msg.Path = currentDisk.Children[0].Path
msg.Volume = mountPath
msg.Size = currentDisk.Children[0].Size
msg.Type = currentDisk.Children[0].Tran
service.MyService.Notify().SendStorageBySocket(msg)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary add mount point // @Param pwd formData string true "user password"
// @Produce application/json // @Param volume formData string true "mount point"
// @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" // @Success 200 {string} string "ok"
// @Router /disk/mount [post] // @Router /disk/format [post]
func PostMountDisk(c *gin.Context) { func PostDiskFormat(c *gin.Context) {
// for example: path=/dev/sda1 id := c.GetHeader("user_id")
path := c.PostForm("path") js := make(map[string]string)
serial := c.PostForm("serial") c.ShouldBind(&js)
path := js["path"]
mountPath := "/DATA/volume" t := "ext4"
var list = service.MyService.Disk().GetSerialAll() pwd := js["password"]
var pathMapList = make(map[string]string, len(list)) volume := js["volume"]
for _, v := range list { user := service.MyService.User().GetUserAllInfoById(id)
pathMapList[v.MountPoint] = "1" if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
if encryption.GetMD5ByStr(pwd) != user.Password {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
return
} }
for i := 0; i < len(list)+1; i++ { if len(path) == 0 || len(t) == 0 {
if _, ok := pathMapList[mountPath+strconv.Itoa(i)]; !ok { c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
mountPath = mountPath + strconv.Itoa(i) return
break
}
} }
if _, ok := diskMap[path]; ok {
//mount dir c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
service.MyService.Disk().MountDisk(path, mountPath) return
}
m := model2.SerialDisk{} diskMap[path] = "busying"
m.MountPoint = mountPath service.MyService.Disk().UmountPointAndRemoveDir(path)
m.Path = path format := service.MyService.Disk().FormatDisk(path, t)
m.UUID = serial if len(format) == 0 {
m.State = 0 delete(diskMap, path)
//service.MyService.Disk().SaveMountPoint(m) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) return
}
service.MyService.Disk().MountDisk(path, volume)
service.MyService.Disk().RemoveLSBLKCache()
delete(diskMap, path)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary remove mount point // @Summary remove mount point
@@ -392,22 +411,30 @@ func PostMountDisk(c *gin.Context) {
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /disk/umount [post] // @Router /disk/umount [post]
func PostDiskUmount(c *gin.Context) { func PostDiskUmount(c *gin.Context) {
id := c.GetHeader("user_id")
js := make(map[string]string)
c.ShouldBind(&js)
path := c.PostForm("path") path := js["path"]
mountPoint := c.PostForm("volume") mountPoint := js["volume"]
pwd := c.PostForm("pwd") pwd := js["password"]
if len(path) == 0 || len(mountPoint) == 0 { 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)}) c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return return
} }
if pwd != config.UserInfo.PWD { user := service.MyService.User().GetUserAllInfoById(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.PWD_INVALID, Message: oasis_err.GetMsg(oasis_err.PWD_INVALID)}) if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
if encryption.GetMD5ByStr(pwd) != user.Password {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
return return
} }
if _, ok := diskMap[path]; ok { if _, ok := diskMap[path]; ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.DISK_BUSYING, Message: oasis_err.GetMsg(oasis_err.DISK_BUSYING)}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
return return
} }
@@ -415,7 +442,16 @@ func PostDiskUmount(c *gin.Context) {
//delete data //delete data
service.MyService.Disk().DeleteMountPoint(path, mountPoint) service.MyService.Disk().DeleteMountPoint(path, mountPoint)
service.MyService.Disk().RemoveLSBLKCache() service.MyService.Disk().RemoveLSBLKCache()
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
//send notify to client
msg := notify.StorageMessage{}
msg.Action = "REMOVED"
msg.Path = path
msg.Volume = mountPoint
msg.Size = 0
msg.Type = ""
service.MyService.Notify().SendStorageBySocket(msg)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary confirm delete disk // @Summary confirm delete disk
@@ -429,7 +465,7 @@ func PostDiskUmount(c *gin.Context) {
func DeleteDisk(c *gin.Context) { func DeleteDisk(c *gin.Context) {
id := c.Param("id") id := c.Param("id")
service.MyService.Disk().DeleteMount(id) service.MyService.Disk().DeleteMount(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary check mount point // @Summary check mount point
@@ -453,45 +489,10 @@ func GetDiskCheck(c *gin.Context) {
for _, v := range dbList { for _, v := range dbList {
if _, ok := mapList[v.UUID]; !ok { if _, ok := mapList[v.UUID]; !ok {
//disk undefind //disk undefind
c.JSON(http.StatusOK, model.Result{Success: oasis_err.ERROR, Message: oasis_err.GetMsg(oasis_err.ERROR), Data: "disk undefind"}) c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "disk undefind"})
return return
} }
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
// @Summary check mount point
// @Produce application/json
// @Accept application/json
// @Tags disk
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /disk/usb [get]
func GetUSBList(c *gin.Context) {
list := service.MyService.Disk().LSBLK(false)
data := []model.DriveUSB{}
for _, v := range list {
if v.Tran == "usb" {
temp := model.DriveUSB{}
temp.Model = v.Model
temp.Name = v.Name
temp.Size = v.Size
mountTemp := true
if len(v.Children) == 0 {
mountTemp = false
}
for _, child := range v.Children {
if len(child.MountPoint) > 0 {
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
temp.Avail += avail
} else {
mountTemp = false
}
}
temp.Mount = mountTemp
data = append(data, temp)
}
}
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
} }

File diff suppressed because it is too large Load Diff

View File

@@ -1,71 +1,28 @@
package v1 package v1
import ( import (
"bufio"
"encoding/csv"
"fmt"
"io" "io"
"io/ioutil" "io/ioutil"
"log"
"net/http" "net/http"
"net/url"
url2 "net/url" url2 "net/url"
"os" "os"
"path" "path"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"sync"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "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"
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"
"github.com/spf13/afero" 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])
}
}
func downloadWriteFile(c *gin.Context) {
//写文件
var filename = "./output1.csv"
file, err := os.Create(filename) //创建文件
if err != nil {
c.String(400, err.Error())
return
}
buf := bufio.NewWriter(file) //创建新的 Writer 对象
buf.WriteString("test")
buf.Flush()
defer file.Close()
//返回文件流
c.File(filename)
}
// @Summary 读取文件 // @Summary 读取文件
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
@@ -77,35 +34,34 @@ func downloadWriteFile(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,
}) })
} }
@@ -114,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
} }
@@ -135,82 +91,120 @@ func GetLocalFile(c *gin.Context) {
// @Accept application/json // @Accept application/json
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path query string true "path of file" // @Param format query string false "Compression format" Enums(zip,tar,targz)
// @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) {
filePath := c.Query("path")
if len(filePath) == 0 { t := c.Query("format")
c.JSON(http.StatusOK, model.Result{
Success: oasis_err2.INVALID_PARAMS, files := c.Query("files")
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS),
if len(files) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{
Success: common_err.INVALID_PARAMS,
Message: common_err.GetMsg(common_err.INVALID_PARAMS),
}) })
return return
} }
if !file.Exists(filePath) { list := strings.Split(files, ",")
c.JSON(http.StatusOK, model.Result{ for _, v := range list {
Success: oasis_err2.FILE_DOES_NOT_EXIST, if !file.Exists(v) {
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST), c.JSON(common_err.SERVICE_ERROR, model.Result{
}) Success: common_err.FILE_DOES_NOT_EXIST,
return Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
})
return
}
} }
//打开文件
fileTmp, _ := os.Open(filePath)
defer fileTmp.Close()
//获取文件的名称
fileName := path.Base(filePath)
c.Header("Content-Type", "application/octet-stream") c.Header("Content-Type", "application/octet-stream")
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
c.Header("Content-Transfer-Encoding", "binary") c.Header("Content-Transfer-Encoding", "binary")
c.Header("Cache-Control", "no-cache") c.Header("Cache-Control", "no-cache")
// handles only single files not folders and multiple files
if len(list) == 1 {
filePath := list[0]
info, err := os.Stat(filePath)
if err != nil {
c.JSON(http.StatusOK, model.Result{
Success: common_err.FILE_DOES_NOT_EXIST,
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
})
return
}
if !info.IsDir() {
//打开文件
fileTmp, _ := os.Open(filePath)
defer fileTmp.Close()
//获取文件的名称
fileName := path.Base(filePath)
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
c.File(filePath)
return
}
}
extension, ar, err := file.GetCompressionAlgorithm(t)
if err != nil {
c.JSON(common_err.CLIENT_ERROR, model.Result{
Success: common_err.INVALID_PARAMS,
Message: common_err.GetMsg(common_err.INVALID_PARAMS),
})
return
}
err = ar.Create(c.Writer)
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
}
defer ar.Close()
commonDir := file.CommonPrefix(filepath.Separator, list...)
currentPath := filepath.Base(commonDir)
name := "_" + currentPath
name += extension
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name))
for _, fname := range list {
err = file.AddFile(ar, fname, commonDir)
if err != nil {
log.Printf("Failed to archive %s: %v", fname, err)
}
}
c.File(filePath)
} }
// @Summary download func GetDownloadSingleFile(c *gin.Context) {
// @Produce application/json
// @Accept application/json
// @Tags file
// @Security ApiKeyAuth
// @Param path query string true "path of file"
// @Success 200 {string} string "ok"
// @Router /file/new/download [get]
func GetFileDownloadNew(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(service.ClientCount, 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) { fileTmp, err := os.Open(filePath)
c.JSON(http.StatusOK, model.Result{ if err != nil {
Success: oasis_err2.FILE_DOES_NOT_EXIST, c.JSON(common_err.SERVICE_ERROR, model.Result{
Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST), Success: common_err.FILE_DOES_NOT_EXIST,
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
}) })
return return
} }
//打开文件 defer fileTmp.Close()
fileStat, _ := os.Stat(filePath)
var AppFs = afero.NewOsFs()
fileT, _ := AppFs.Open(filePath)
//fileTmp, _ := os.Open(filePath)
//defer fileTmp.Close()
//获取文件的名称
//fileName := path.Base(filePath)
//c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName)) fileName := path.Base(filePath)
//在线
//c.Header("Content-Disposition", "inline") //c.Header("Content-Disposition", "inline")
// extraHeaders := map[string]string{ c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
// "Content-Disposition": `attachment; filename="` + url2.PathEscape(fileName) + `"`, c.File(filePath)
// }
//c.Header("Cache-Control", "private")
//c.Header("Content-Type", "application/octet-stream")
http.ServeContent(c.Writer, c.Request, fileStat.Name(), fileStat.ModTime(), fileT)
} }
// @Summary 获取目录列表 // @Summary 获取目录列表
@@ -223,7 +217,7 @@ func GetFileDownloadNew(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)
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))
@@ -264,7 +258,30 @@ func DirPath(c *gin.Context) {
} }
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info}) //Hide the files or folders in operation
fileQueue := make(map[string]string)
if len(service.OpStrArr) > 0 {
for _, v := range service.OpStrArr {
v, ok := service.FileQueue.Load(v)
if !ok {
continue
}
vt := v.(model.FileOperate)
for _, i := range vt.Item {
lastPath := i.From[strings.LastIndex(i.From, "/")+1:]
fileQueue[vt.To+"/"+lastPath] = i.From
}
}
}
pathList := []model.Path{}
for i := 0; i < len(info); i++ {
if _, ok := fileQueue[info[i].Path]; !ok {
pathList = append(pathList, info[i])
}
}
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
@@ -272,62 +289,78 @@ func DirPath(c *gin.Context) {
// @Accept application/json // @Accept application/json
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param oldpath formData string true "path of old" // @Param oldpath body string true "path of old"
// @Param newpath formData string true "path of new" // @Param newpath body string true "path of new"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/rename [put] // @Router /file/rename [put]
func RenamePath(c *gin.Context) { func RenamePath(c *gin.Context) {
op := c.PostForm("oldpath") json := make(map[string]string)
np := c.PostForm("newpath") c.ShouldBind(&json)
op := json["old_path"]
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
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept application/json
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path formData string true "path of folder" // @Param path body string true "path of folder"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/mkdir [post] // @Router /file/mkdir [post]
func MkdirAll(c *gin.Context) { func MkdirAll(c *gin.Context) {
path := c.PostForm("path") json := make(map[string]string)
c.ShouldBind(&json)
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
} }
code, _ = service.MyService.ZiMa().MkdirAll(path) // decodedPath, err := url.QueryUnescape(path)
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)}) // if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return
// }
code, _ = service.MyService.System().MkdirAll(path)
c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
} }
// @Summary create file // @Summary create file
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept application/json
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path formData string false "路径" // @Param path body string true "path of folder (path need to url encode)"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/create [post] // @Router /file/create [post]
func PostCreateFile(c *gin.Context) { func PostCreateFile(c *gin.Context) {
path := c.PostForm("path") json := make(map[string]string)
c.ShouldBind(&json)
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
} }
code, _ = service.MyService.ZiMa().CreateFile(path) // decodedPath, err := url.QueryUnescape(path)
c.JSON(http.StatusOK, model.Result{Success: code, Message: oasis_err2.GetMsg(code)}) // if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return
// }
code, _ = service.MyService.System().CreateFile(path)
c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
} }
// @Summary upload file // @Summary upload file
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept application/json
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path formData string false "file path" // @Param path formData string false "file path"
@@ -343,7 +376,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 := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/"
if fileName != relative { if fileName != relative {
dirPath = strings.TrimSuffix(relative, fileName) dirPath = strings.TrimSuffix(relative, fileName)
tempDir += dirPath tempDir += dirPath
@@ -351,11 +384,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
@@ -379,10 +412,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 := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/"
if fileName != relative { if fileName != relative {
dirPath = strings.TrimSuffix(relative, fileName) dirPath = strings.TrimSuffix(relative, fileName)
@@ -403,7 +436,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 {
@@ -411,15 +444,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) {
@@ -427,101 +460,122 @@ 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
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept application/json
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param from formData string true "from path" // @Param body body model.FileOperate true "type:move,copy"
// @Param to formData string true "to path"
// @Param type formData string true "action" Enums(move,copy)
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/operate [post] // @Router /file/operate [post]
func PostOperateFileOrDir(c *gin.Context) { func PostOperateFileOrDir(c *gin.Context) {
from := c.PostForm("from")
to := c.PostForm("to") list := model.FileOperate{}
t := c.PostForm("type") c.ShouldBind(&list)
if len(from) == 0 || len(t) == 0 || len(to) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) if len(list.Item) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return return
} }
if t == "move" { if list.To == list.Item[0].From[:strings.LastIndex(list.Item[0].From, "/")] {
lastPath := from[strings.LastIndex(from, "/")+1:] c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SOURCE_DES_SAME, Message: common_err.GetMsg(common_err.SOURCE_DES_SAME)})
if !file.CheckNotExist(to + "/" + lastPath) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_OR_DIR_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
return
}
err := os.Rename(from, to+"/"+lastPath)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
} else if t == "copy" {
err := file.CopyDir(from, to)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
} else {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
var total int64 = 0
for i := 0; i < len(list.Item); i++ {
size, err := file.GetFileOrDirSize(list.Item[i].From)
if err != nil {
continue
}
list.Item[i].Size = size
total += size
}
list.TotalSize = total
list.ProcessedSize = 0
uid := uuid.NewV4().String()
service.FileQueue.Store(uid, list)
service.OpStrArr = append(service.OpStrArr, uid)
if len(service.OpStrArr) == 1 {
go service.ExecOpFile()
go service.CheckFileStatus()
go service.MyService.Notify().SendFileOperateNotify(false)
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary delete file // @Summary delete file
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept application/json
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path query string true "path" // @Param body body string true "paths eg ["/a/b/c","/d/e/f"]"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/delete [delete] // @Router /file/delete [delete]
func DeleteFile(c *gin.Context) { func DeleteFile(c *gin.Context) {
path := c.Query("path")
//err := os.Remove(path) paths := []string{}
err := os.RemoveAll(path) c.ShouldBind(&paths)
if err != nil { if len(paths) == 0 {
fmt.Println(err) c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
return return
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) // path := c.Query("path")
// paths := strings.Split(path, ",")
for _, v := range paths {
err := os.RemoveAll(v)
if err != nil {
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
}
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary update file // @Summary update file
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept application/json
// @Tags file // @Tags file
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param path formData string true "path" // @Param path body string true "path"
// @Param content formData string true "content" // @Param content body string true "content"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/update [put] // @Router /file/update [put]
func PutFileContent(c *gin.Context) { func PutFileContent(c *gin.Context) {
path := c.PostForm("path")
content := c.PostForm("content") fi := model.FileUpdate{}
if !file.Exists(path) { c.ShouldBind(&fi)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
// path := c.PostForm("path")
// content := c.PostForm("content")
if !file.Exists(fi.FilePath) {
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(path) err := os.RemoveAll(fi.FilePath)
if err != nil { if err != nil {
fmt.Println(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})
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DELETE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.FILE_DELETE_ERROR), Data: err})
return return
} }
err = file.CreateFileAndWriteContent(path, content) err = file.CreateFileAndWriteContent(fi.FilePath, fi.FileContent)
if err != nil { if err != nil {
fmt.Println(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()})
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.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 image thumbnail/original image // @Summary image thumbnail/original image
@@ -537,13 +591,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))
@@ -551,14 +605,36 @@ 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))
} }
func DeleteOperateFileOrDir(c *gin.Context) {
id := c.Param("id")
if id == "0" {
service.FileQueue = sync.Map{}
service.OpStrArr = []string{}
} else {
service.FileQueue.Delete(id)
tempList := []string{}
for _, v := range service.OpStrArr {
if v != id {
tempList = append(tempList, v)
}
}
service.OpStrArr = tempList
}
go service.MyService.Notify().SendFileOperateNotify(true)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}

View File

@@ -1,803 +0,0 @@
package v1
import (
"bytes"
"encoding/base64"
"encoding/gob"
"encoding/json"
"io/ioutil"
"net"
"net/http"
"os"
"reflect"
"strconv"
"strings"
"time"
natType "github.com/Curtis-Milo/nat-type-identifier-go"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"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/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin"
uuid "github.com/satori/go.uuid"
)
// @Summary Retry the file that failed to download
// @Produce application/json
// @Accept application/json
// @Tags person
// @Param uui path string true "download uuid"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/refile/{uuid} [get]
func GetPersonReFile(c *gin.Context) {
uid := c.Param("uuid")
_, err := uuid.FromString(uid)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
task := service.MyService.Download().GetDownloadById(uid)
if reflect.DeepEqual(task, model2.PersonDownloadDBModel{}) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
return
}
token := task.From
if _, ok := service.UDPAddressMap[token]; !ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
return
}
m := model.MessageModel{}
m.Data = task.Path
m.From = config.ServerInfo.Token
m.To = token
m.Type = types.PERSONDOWNLOAD
m.UUId = uid
go service.Dial(m, false)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary download file
// @Produce application/json
// @Accept application/json
// @Tags person
// @Param share_id query string true "opponent share_id"
// @Param path query string true "file path"
// @Param file_name query string true "file name"
// @Param local_path query string true "local_path"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/file [get]
func GetPersonFile(c *gin.Context) {
path := c.Query("path")
localPath := c.Query("local_path")
token := c.Query("share_id")
fileName := c.Query("file_name")
_, err := uuid.FromString(token)
if len(path) == 0 || err != nil || len(localPath) == 0 || len(fileName) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
if file.CheckNotExist(localPath) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DIR_NOT_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.DIR_NOT_EXISTS)})
return
}
if _, ok := service.UDPAddressMap[token]; !ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
return
}
if _, ok := service.UDPAddressMap[token]; !ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
return
}
// task id
uuid := uuid.NewV4().String()
task := model2.PersonDownloadDBModel{}
task.UUID = uuid
task.Name = fileName
task.Length = 0
task.From = token
task.Path = path
task.Size = 0
task.State = types.DOWNLOADAWAIT
task.Created = time.Now().Unix()
task.Type = types.PERSONFILEDOWNLOAD
task.LocalPath = localPath
if service.MyService.Download().GetDownloadListByPath(task) > 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_EXIST_DOWNLOAD, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_DOWNLOAD)})
return
}
service.MyService.Download().AddDownloadTask(task)
m := model.MessageModel{}
m.Data = path
m.From = config.ServerInfo.Token
m.To = token
m.Type = types.PERSONDOWNLOAD
m.UUId = uuid
go service.Dial(m, false)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary delete download file records
// @Produce application/json
// @Accept application/json
// @Tags person
// @Param uuid path string true "download uuid"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/file/{uuid} [delete]
func DeletePersonDownloadFile(c *gin.Context) {
id := c.Param("uuid")
_, err := uuid.FromString(id)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
task := service.MyService.Download().GetDownloadById(id)
if task.State == types.DOWNLOADING {
m := model.MessageModel{}
m.Data = ""
m.From = config.ServerInfo.Token
m.To = task.From
m.Type = types.PERSONCANCEL
m.UUId = task.UUID
service.CancelList[task.UUID] = task.UUID
service.Dial(m, false)
}
service.MyService.Download().DelDownload(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary Get file download list
// @Produce application/json
// @Accept application/json
// @Tags person
// @Param state query int false "wait:0,downloading:1,pause:2,finish:3,error:4,finished:5" Enums(0,1,2,3,4,5)
// @Security ApiKeyAuth
// @Success 200 {object} []model2.PersonDownloadDBModel
// @Router /person/list [get]
func GetPersonDownloadList(c *gin.Context) {
state := c.DefaultQuery("state", "")
list := service.MyService.Download().GetDownloadListByState(state, types.PERSONFILEDOWNLOAD)
//if it is downloading, it need to add 'already'
for i := 0; i < len(list); i++ {
if list[i].State == types.DOWNLOADING {
tempDir := config.AppInfo.RootPath + "/temp" + "/" + list[i].UUID
files, err := ioutil.ReadDir(tempDir)
if err == nil {
list[i].Already = len(files)
}
}
list[i].Duration = time.Now().Unix() - list[i].Created
}
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
}
// @Summary edit friend's remarks
// @Produce application/json
// @Accept application/json
// @Tags person
// @Param remarks formData string true "remarks name"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/remarks/{shareid} [put]
func PutPersonRemarks(c *gin.Context) {
token := c.Param("shareid")
_, err := uuid.FromString(token)
mark := c.PostForm("remarks")
if err != nil || len(mark) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
friend := model2.FriendModel{}
friend.Token = token
friend.Mark = mark
service.MyService.Friend().EditFriendMark(friend)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary edit friend's
// @Produce application/json
// @Accept application/json
// @Tags person
// @Param write formData bool true "write"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/write/{shareid} [put]
func PutPersonWrite(c *gin.Context) {
token := c.Param("shareid")
_, err := uuid.FromString(token)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
write, _ := strconv.ParseBool(c.PostForm("write"))
friend := model2.FriendModel{}
friend.Token = token
friend.Write = write
service.MyService.Friend().EditFriendMark(friend)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary image thumbnail
// @Produce application/json
// @Accept application/json
// @Tags person
// @Param write formData bool true "write"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/image/thumbnail/{shareid} [get]
func GetPersonImageThumbnail(c *gin.Context) {
token := c.Param("shareid")
path := c.Query("path")
_, err := uuid.FromString(token)
if err != nil || len(path) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
uuid := uuid.NewV4().String()
m := model.MessageModel{}
m.Data = path
m.From = config.ServerInfo.Token
m.To = token
m.Type = types.PERSONIMAGETHUMBNAIL
m.UUId = uuid
img, err := service.Dial(m, false)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
// var buf bytes.Buffer
//err = gob.NewEncoder(&buf).Encode(img.Data)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
var buf bytes.Buffer
err = gob.NewEncoder(&buf).Encode(img.Data)
if err != nil {
c.JSON(http.StatusInternalServerError, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
imageBuffer, _ := base64.StdEncoding.DecodeString(img.Data.(string))
c.Writer.WriteString(string(imageBuffer))
// c.String(http.StatusOK, "data:image/"+filesuffix+";base64,"+img.Data.(string))
//c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: img.Data.(string)})
}
// @Summary get my friend list
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {object} []model2.FriendModel
// @Router /person/users [get]
func GetPersonFriend(c *gin.Context) {
list := service.MyService.Friend().GetFriendList()
for i := 0; i < len(list); i++ {
if v, ok := service.UDPAddressMap[list[i].Token]; ok && len(v) > 0 {
list[i].OnLine = true
if ip_helper.HasLocalIP(net.ParseIP(strings.Split(v, ":")[0])) {
list[i].LocalIP = strings.Split(v, ":")[0]
}
}
}
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
}
// @Summary network type detection
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/detection [get]
func GetPersonDetection(c *gin.Context) {
// - Blocked
// - Open Internet
// - Full Cone
// - Symmetric UDP Firewall
// - Restric NAT
// - Restric Port NAT
// - Symmetric NAT
result, err := natType.GetDeterminedNatType(true, 5, "stun.l.google.com")
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
//result := service.MyService.Person().GetPersionNetWorkTypeDetection()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: result})
}
// @Summary add friend
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/user/{shareids} [post]
func PostAddPersonFriend(c *gin.Context) {
token := c.Param("shareids")
tokenList := strings.Split(token, ",")
for _, v := range tokenList {
_, err := uuid.FromString(v)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
if v == config.ServerInfo.Token {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_MYSELF, Message: oasis_err2.GetMsg(oasis_err2.PERSON_MYSELF)})
return
}
udb := service.MyService.Friend().GetFriendById(model2.FriendModel{Token: v})
if !reflect.DeepEqual(udb, model2.FriendModel{Token: v}) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_EXIST_FRIEND, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_FRIEND)})
return
}
user := service.MyService.Casa().GetUserInfoByShareId(v)
if reflect.DeepEqual(user, model.UserInfo{}) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_NOT_EXIST_USER, Message: oasis_err2.GetMsg(oasis_err2.PERSON_NOT_EXIST_USER)})
return
}
message := model.MessageModel{}
message.Type = types.PERSONCONNECTION
message.Data = v
message.From = config.ServerInfo.Token
message.To = v
message.UUId = uuid.NewV4().String()
go service.Dial(message, true)
msg := model.MessageModel{}
msg.Type = types.PERSONGETIP
msg.Data = ""
msg.From = config.ServerInfo.Token
msg.To = v
msg.UUId = uuid.NewV4().String()
service.Dial(msg, true)
friend := model2.FriendModel{}
friend.Token = v
friend.Avatar = user.Avatar
friend.Block = false
friend.State = types.FRIENDSTATEWAIT
friend.NickName = user.NickName
friend.Profile = user.Desc
friend.Version = user.Version
service.MyService.Friend().AddFriend(friend)
}
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary Get a list of directories
// @Produce application/json
// @Accept application/json
// @Tags person
// @Param share_id query string true "Opponent share_id"
// @Param path query string true "dir path"
// @Security ApiKeyAuth
// @Success 200 {object} []model.Path
// @Router /person/directory [get]
func GetPersonDirectory(c *gin.Context) {
path := c.Query("path")
token := c.Query("share_id")
_, err := uuid.FromString(token)
if len(path) == 0 || err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
if _, ok := service.UDPAddressMap[token]; !ok {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_REMOTE_ERROR, Message: oasis_err2.GetMsg(oasis_err2.PERSON_REMOTE_ERROR)})
return
}
uuid := uuid.NewV4().String()
m := model.MessageModel{}
m.Data = path
m.From = config.ServerInfo.Token
m.To = token
m.Type = types.PERSONDIRECTORY
m.UUId = uuid
result, err := service.Dial(m, false)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
return
}
dataModel := []model.Path{}
if uuid == m.UUId {
dataModelByte, _ := json.Marshal(result.Data)
err := json.Unmarshal(dataModelByte, &dataModel)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: 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), Data: dataModel})
}
// @Summary Modify the download storage directory
// @Produce application/json
// @Accept multipart/form-data
// @Tags person
// @Security ApiKeyAuth
// @Param path formData string true "path"
// @Success 200 {string} string "ok"
// @Router /person/down/dir [post]
func PostPersonDownDir(c *gin.Context) {
downPath := c.PostForm("path")
if len(downPath) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
if file.CheckNotExist(downPath) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.DIR_NOT_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.DIR_NOT_EXISTS)})
return
}
config.Cfg.Section("file").Key("DownloadDir").SetValue(downPath)
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
config.FileSettingInfo.DownloadDir = downPath
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary Get the download storage directory
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/down/dir [get]
func GetPersonDownDir(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.FileSettingInfo.DownloadDir})
}
// @Summary Modify the shared directory
// @Produce application/json
// @Accept multipart/form-data
// @Tags person
// @Security ApiKeyAuth
// @Param share formData string true "share"
// @Success 200 {string} string "ok"
// @Router /person/share [post]
func PostPersonShare(c *gin.Context) {
share := c.PostForm("share")
if len(share) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
var list []string
json.Unmarshal([]byte(share), &list)
if len(list) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
for _, v := range list {
if !file.Exists(v) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_ALREADY_EXISTS, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
return
}
}
config.Cfg.Section("file").Key("ShareDir").SetValue(strings.Join(list, "|"))
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
config.FileSettingInfo.ShareDir = list
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary Get the shared directory
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/share [get]
func GetPersonShare(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.FileSettingInfo.ShareDir})
}
// @Summary Get the shareid
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/shareid [get]
func GetPersonShareId(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.ServerInfo.Token})
}
// @Summary Modify disabled status
// @Produce application/json
// @Accept application/json
// @Tags person
// @Param block formData bool false "Disable or not,Default:false "
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/block/{shareid} [put]
func PutPersonBlock(c *gin.Context) {
token := c.Param("shareid")
_, err := uuid.FromString(token)
block, _ := strconv.ParseBool(c.PostForm("block"))
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
friend := model2.FriendModel{}
friend.Token = token
friend.Block = block
service.MyService.Friend().EditFriendBlock(friend)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary Delete my friend
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/user/{shareid} [delete]
func DeletePersonFriend(c *gin.Context) {
token := c.Param("shareid")
_, err := uuid.FromString(token)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
friend := model2.FriendModel{}
friend.Token = token
service.MyService.Friend().DeleteFriend(friend)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary Get public person
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/public [get]
func GetPersonPublic(c *gin.Context) {
list := service.MyService.Casa().GetPersonPublic()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: list})
}
// @Summary upload file to friend
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Param path formData string true "Destination path"
// @Param local_path formData string true "Full path of the file to be uploaded"
// @Success 200 {string} string "ok"
// @Router /person/file/{shareid} [post]
func PostPersonFile(c *gin.Context) {
token := c.Param("shareid")
_, err := uuid.FromString(token)
path := c.PostForm("path")
localPath := c.PostForm("local_path")
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
if !file.Exists(localPath) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.FILE_DOES_NOT_EXIST, Message: oasis_err2.GetMsg(oasis_err2.FILE_DOES_NOT_EXIST)})
return
}
uuid := uuid.NewV4().String()
m := model.MessageModel{}
m.Data = path
m.From = config.ServerInfo.Token
m.To = token
m.Type = types.PERSONUPLOAD
m.UUId = uuid
go service.UDPSendData(m, localPath)
f, _ := os.Stat(localPath)
task := model2.PersonDownloadDBModel{}
task.UUID = uuid
task.Name = f.Name()
task.Length = 0
task.From = token
task.Path = path
task.Size = f.Size()
task.State = types.DOWNLOADFINISHED
task.Created = time.Now().Unix()
task.Type = types.PERSONFILEUPLOAD
task.LocalPath = localPath
if service.MyService.Download().GetDownloadListByPath(task) > 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PERSON_EXIST_DOWNLOAD, Message: oasis_err2.GetMsg(oasis_err2.PERSON_EXIST_DOWNLOAD)})
return
}
service.MyService.Download().AddDownloadTask(task)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// @Summary agree add friend
// @Produce application/json
// @Accept application/json
// @Tags person
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /person/friend/{shareid} [put]
func PutPersonAgreeFriend(c *gin.Context) {
token := c.Param("shareid")
_, err := uuid.FromString(token)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
user := service.MyService.Friend().GetFriendById(model2.FriendModel{Token: token})
if user.State != types.FRIENDSTATEREQUEST {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.COMMAND_ERROR_INVALID_OPERATION, Message: oasis_err2.GetMsg(oasis_err2.COMMAND_ERROR_INVALID_OPERATION)})
return
}
service.MyService.Friend().AgreeFrined(user.Token)
uuid := uuid.NewV4().String()
m := model.MessageModel{}
m.Data = ""
m.From = config.ServerInfo.Token
m.To = token
m.Type = types.PERSONAGREEFRIEND
m.UUId = uuid
go service.Dial(m, true)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
}
// // @Summary upload file
// // @Produce application/json
// // @Accept multipart/form-data
// // @Tags person
// // @Security ApiKeyAuth
// // @Param path formData string false "file path"
// // @Param file formData file true "file"
// // @Success 200 {string} string "ok"
// // @Router /person/upload/{shareid} [get]
// func GetPersonFileUpload(c *gin.Context) {
// token := c.Param("shareid")
// _, err := uuid.FromString(token)
// path := c.Query("path")
// if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
// relative := c.Query("relativePath")
// fileName := c.Query("filename")
// chunkNumber := c.Query("chunkNumber")
// totalChunks, _ := strconv.Atoi(c.DefaultQuery("totalChunks", "0"))
// dirPath := ""
// hash := file.GetHashByContent([]byte(fileName))
// tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
// if fileName != relative {
// dirPath = strings.TrimSuffix(relative, fileName)
// tempDir += dirPath
// file.MkDir(path + "/" + dirPath)
// }
// tempDir += chunkNumber
// if !file.CheckNotExist(tempDir) {
// c.JSON(200, model.Result{Success: 200, Message: oasis_err2.GetMsg(oasis_err2.FILE_ALREADY_EXISTS)})
// return
// }
// c.JSON(204, model.Result{Success: 204, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
// }
// // @Summary upload file
// // @Produce application/json
// // @Accept multipart/form-data
// // @Tags person
// // @Security ApiKeyAuth
// // @Param path formData string false "file path"
// // @Param file formData file true "file"
// // @Success 200 {string} string "ok"
// // @Router /person/upload [post]
// func PostPersonFileUpload(c *gin.Context) {
// token := c.Param("shareid")
// _, err := uuid.FromString(token)
// if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
// f, _, _ := c.Request.FormFile("file")
// relative := c.PostForm("relativePath")
// fileName := c.PostForm("filename")
// totalChunks, _ := strconv.Atoi(c.DefaultPostForm("totalChunks", "0"))
// chunkNumber := c.PostForm("chunkNumber")
// dirPath := ""
// path := c.PostForm("path")
// hash := file.GetHashByContent([]byte(fileName))
// if len(path) == 0 {
// c.JSON(oasis_err2.INVALID_PARAMS, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
// return
// }
// tempDir := "/casaOS/temp/" + hash + strconv.Itoa(totalChunks) + "/"
// if fileName != relative {
// dirPath = strings.TrimSuffix(relative, fileName)
// tempDir += dirPath
// file.MkDir(path + "/" + dirPath)
// }
// path += "/" + relative
// if !file.CheckNotExist(tempDir + chunkNumber) {
// file.RMDir(tempDir + chunkNumber)
// }
// if totalChunks > 1 {
// file.IsNotExistMkDir(tempDir)
// out, _ := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0644)
// defer out.Close()
// _, err := io.Copy(out, f)
// if err != nil {
// c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
// return
// }
// } else {
// out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
// defer out.Close()
// _, err := io.Copy(out, f)
// if err != nil {
// c.JSON(oasis_err2.ERROR, 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)})
// return
// }
// fileNum, err := ioutil.ReadDir(tempDir)
// if err != nil {
// c.JSON(oasis_err2.ERROR, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR), Data: err.Error()})
// return
// }
// if totalChunks == len(fileNum) {
// file.RMDir(tempDir)
// }
// c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
// }

View File

@@ -1,22 +0,0 @@
package v1
import (
"net/http"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
)
func GetSearchList(c *gin.Context) {
key := c.DefaultQuery("key", "")
if len(key) == 0 {
return
}
list, err := service.MyService.Search().SearchList(key)
if err != nil {
}
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: list})
}

View File

@@ -1,144 +0,0 @@
package v1
import (
"github.com/IceWhaleTech/CasaOS/model"
"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"
"net/http"
"strconv"
)
// @Summary 获取列表
// @Produce application/json
// @Accept application/json
// @Tags share
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /share/list [get]
func GetShareDirList(c *gin.Context) {
list := service.MyService.ShareDirectory().List(true)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: list})
}
// @Summary 添加文件共享
// @Produce application/json
// @Accept multipart/form-data
// @Tags share
// @Security ApiKeyAuth
// @Param path formData string true "要分享的文件路径"
// @Param name formData string true "名称"
// @Param comment formData string true "描述"
// @Param read_only formData bool false "是否只读"
// @Param writeable formData bool false "是否可写"
// @Param browseable formData bool false "是否可浏览"
// @Param user formData string false "用户"
// @Success 200 {string} string "ok"
// @Router /share/add [post]
func PostShareDirAdd(c *gin.Context) {
name := c.PostForm("name")
comment := c.PostForm("comment")
path := c.PostForm("path")
readOnly, _ := strconv.ParseBool(c.DefaultPostForm("read_only", "false"))
writeable, _ := strconv.ParseBool(c.DefaultPostForm("writeable", "true"))
browse, _ := strconv.ParseBool(c.DefaultPostForm("browseable", "true"))
user := c.PostForm("user")
if len(name) == 0 || len(comment) == 0 || len(path) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
return
}
var m model2.ShareDirDBModel
m.Name = name
m.Comment = comment
m.Path = path
m.ReadOnly = readOnly
m.Writeable = writeable
m.Browseable = browse
m.ValidUsers = user
service.MyService.ShareDirectory().Add(&m)
service.MyService.ShareDirectory().UpConfig()
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 share
// @Security ApiKeyAuth
// @Param id path string true "id"
// @Success 200 {string} string "ok"
// @Router /share/del/{id} [delete]
func DeleteShareDirDel(c *gin.Context) {
id := c.Param("id")
service.MyService.ShareDirectory().Delete(id)
service.MyService.ShareDirectory().UpConfig()
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 share
// @Security ApiKeyAuth
// @Param id path string true "id"
// @Success 200 {string} string "ok"
// @Router /share/info/{id} [get]
func GetShareDirInfo(c *gin.Context) {
id := c.Param("id")
info := service.MyService.ShareDirectory().Info(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: info})
}
// @Summary 更新分享详情
// @Produce application/json
// @Accept application/json
// @Tags share
// @Security ApiKeyAuth
// @Param id path string true "id"
// @Param path formData string true "要分享的文件路径"
// @Param name formData string true "名称"
// @Param comment formData string true "描述"
// @Param read_only formData bool false "是否只读"
// @Param writeable formData bool false "是否可写"
// @Param browseable formData bool false "是否可浏览"
// @Param user formData string false "用户"
// @Success 200 {string} string "ok"
// @Router /share/update/{id} [put]
func PutShareDirEdit(c *gin.Context) {
id, err := strconv.ParseUint(c.Param("id"), 10, 32)
if err != nil || id == 0 {
//todo 报错出去
}
name := c.PostForm("name")
comment := c.PostForm("comment")
path := c.PostForm("path")
readOnly, _ := strconv.ParseBool(c.DefaultPostForm("read_only", "false"))
writeable, _ := strconv.ParseBool(c.DefaultPostForm("writeable", "true"))
browse, _ := strconv.ParseBool(c.DefaultPostForm("browseable", "true"))
user := c.PostForm("user")
if len(name) == 0 || len(comment) == 0 || len(path) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
return
}
var m model2.ShareDirDBModel
m.Id = uint(id)
m.Name = name
m.Comment = comment
m.Path = path
m.ReadOnly = readOnly
m.Writeable = writeable
m.Browseable = browse
m.ValidUsers = user
service.MyService.ShareDirectory().Update(&m)
service.MyService.ShareDirectory().UpConfig()
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
}

View File

@@ -1,96 +0,0 @@
package v1
import (
"github.com/IceWhaleTech/CasaOS/model"
"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"
"net/http"
"net/url"
)
// @Summary 获取短链列表
// @Produce application/json
// @Accept application/json
// @Tags shortcuts
// @Param username formData string true "User name"
// @Param pwd formData string true "password"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /shortcuts/list [get]
func GetShortcutsList(c *gin.Context) {
list := service.MyService.Shortcuts().GetList()
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: list})
}
// @Summary 添加shortcuts
// @Produce application/json
// @Accept application/json
// @Tags shortcuts
// @Param title formData string true "title"
// @Param url formData string true "url"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /shortcuts/add [post]
func PostShortcutsAdd(c *gin.Context) {
var m model2.ShortcutsDBModel
c.BindJSON(&m)
if len(m.Url) == 0 || len(m.Title) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
return
}
u, err := url.Parse(m.Url)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SHORTCUTS_URL_ERROR, Message: oasis_err.GetMsg(oasis_err.SHORTCUTS_URL_ERROR), Data: err.Error()})
return
}
m.Icon = "https://api.faviconkit.com/" + u.Host + "/57"
service.MyService.Shortcuts().AddData(m)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
}
// @Summary 删除shortcuts
// @Produce application/json
// @Accept application/json
// @Tags shortcuts
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /shortcuts/del/{id} [post]
func DeleteShortcutsDelete(c *gin.Context) {
id := c.Param("id")
service.MyService.Shortcuts().DeleteData(id)
c.JSON(http.StatusOK, model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
Data: "",
})
}
// @Summary 编辑shortcuts
// @Produce application/json
// @Accept application/json
// @Tags shortcuts
// @Param title formData string true "title"
// @Param url formData string true "url"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /shortcuts/edit [put]
func PutShortcutsEdit(c *gin.Context) {
var m model2.ShortcutsDBModel
c.BindJSON(&m)
if len(m.Url) == 0 || len(m.Title) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
return
}
u, err := url.Parse(m.Url)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SHORTCUTS_URL_ERROR, Message: oasis_err.GetMsg(oasis_err.SHORTCUTS_URL_ERROR), Data: err.Error()})
return
}
m.Icon = "https://api.faviconkit.com/" + u.Host + "/57"
service.MyService.Shortcuts().EditData(m)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: ""})
}

17
route/v1/storage.go Normal file
View File

@@ -0,0 +1,17 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-07-11 16:02:29
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-11 16:02:55
* @FilePath: /CasaOS/route/v1/storage.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package v1
import "github.com/gin-gonic/gin"
func GetStorageList(c *gin.Context) {
}

View File

@@ -1,35 +0,0 @@
package v1
import (
"net/http"
"net/http/httputil"
"net/url"
"strings"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/gin-gonic/gin"
)
func SyncToSyncthing(c *gin.Context) {
u := c.Param("url")
target := "http://" + strings.Split(c.Request.Host, ":")[0] + ":" + config.SystemConfigInfo.SyncPort
remote, err := url.Parse(target)
if err != nil {
return
}
proxy := httputil.NewSingleHostReverseProxy(remote)
c.Request.Header.Add("X-API-Key", config.SystemConfigInfo.SyncKey)
//c.Request.Header.Add("X-API-Key", config.SystemConfigInfo.SyncKey)
c.Request.URL.Path = u
proxy.ServeHTTP(c.Writer, c.Request)
}
func GetSyncConfig(c *gin.Context) {
data := make(map[string]string)
data["key"] = config.SystemConfigInfo.SyncKey
data["port"] = config.SystemConfigInfo.SyncPort
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
}

View File

@@ -1,7 +1,6 @@
package v1 package v1
import ( import (
"encoding/json"
"fmt" "fmt"
"net/http" "net/http"
"os" "os"
@@ -13,14 +12,15 @@ import (
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port" port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
"github.com/IceWhaleTech/CasaOS/pkg/utils/version" "github.com/IceWhaleTech/CasaOS/pkg/utils/version"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types" "github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
"go.uber.org/zap"
) )
// @Summary check version // @Summary check version
@@ -29,9 +29,9 @@ import (
// @Tags sys // @Tags sys
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/chackversion [get] // @Router /sys/version/check [get]
func CheckVersion(c *gin.Context) { func GetSystemCheckVersion(c *gin.Context) {
need, version := version.IsNeedUpdate() need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion())
if need { if need {
installLog := model2.AppNotify{} installLog := model2.AppNotify{}
installLog.State = 0 installLog.State = 0
@@ -42,38 +42,11 @@ func CheckVersion(c *gin.Context) {
installLog.Name = "CasaOS System" installLog.Name = "CasaOS System"
service.MyService.Notify().AddLog(installLog) service.MyService.Notify().AddLog(installLog)
} }
data := make(map[string]interface{}, 1) data := make(map[string]interface{}, 3)
data["is_need"] = need data["need_update"] = need
data["version"] = version data["version"] = version
data["current_version"] = types.CURRENTVERSION data["current_version"] = types.CURRENTVERSION
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
return
}
// @Summary check client version
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/client/version [get]
func GetClientVersion(c *gin.Context) {
need, version := version.IsClientNeedUpdate()
if need {
installLog := model2.AppNotify{}
installLog.State = 0
installLog.Message = "New version " + version.Version + " is ready, ready to upgrade"
installLog.Type = types.NOTIFY_TYPE_NEED_CONFIRM
installLog.CreatedAt = strconv.FormatInt(time.Now().Unix(), 10)
installLog.UpdatedAt = strconv.FormatInt(time.Now().Unix(), 10)
installLog.Name = "CasaOS System"
service.MyService.Notify().AddLog(installLog)
}
data := make(map[string]interface{}, 1)
data["is_need"] = need
data["version"] = version
data["current_version"] = types.CURRENTVERSION
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: data})
} }
// @Summary 系统信息 // @Summary 系统信息
@@ -84,16 +57,11 @@ func GetClientVersion(c *gin.Context) {
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/update [post] // @Router /sys/update [post]
func SystemUpdate(c *gin.Context) { func SystemUpdate(c *gin.Context) {
need, version := version.IsNeedUpdate() need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion())
if need { if need {
service.MyService.System().UpdateSystemVersion(version.Version) service.MyService.System().UpdateSystemVersion(version.Version)
} }
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
//系统配置
func GetSystemConfig(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: json.RawMessage(config.SystemConfigInfo.ConfigStr)})
} }
// @Summary get logs // @Summary get logs
@@ -105,86 +73,29 @@ func GetSystemConfig(c *gin.Context) {
// @Router /sys/error/logs [get] // @Router /sys/error/logs [get]
func GetCasaOSErrorLogs(c *gin.Context) { func GetCasaOSErrorLogs(c *gin.Context) {
line, _ := strconv.Atoi(c.DefaultQuery("line", "100")) line, _ := strconv.Atoi(c.DefaultQuery("line", "100"))
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
}
// @Summary 修改配置文件
// @Produce application/json
// @Accept multipart/form-data
// @Tags sys
// @Param config formData string true "config json string"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/changhead [post]
func PostSetSystemConfig(c *gin.Context) {
buf := make([]byte, 1024)
n, _ := c.Request.Body.Read(buf)
service.MyService.System().UpSystemConfig(string(buf[0:n]), "")
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
Data: json.RawMessage(config.SystemConfigInfo.ConfigStr),
})
} }
//系统配置 //系统配置
func GetSystemConfigDebug(c *gin.Context) { func GetSystemConfigDebug(c *gin.Context) {
array := service.MyService.System().GetSystemConfigDebug() array := service.MyService.System().GetSystemConfigDebug()
disk := service.MyService.ZiMa().GetDiskInfo() disk := service.MyService.System().GetDiskInfo()
sys := service.MyService.ZiMa().GetSysInfo() sys := service.MyService.System().GetSysInfo()
//todo 准备sync需要显示的数据(镜像,容器) version := service.MyService.Casa().GetCasaosVersion()
var systemAppStatus string
images := service.MyService.Docker().IsExistImage("linuxserver/syncthing")
systemAppStatus += "Sync img: " + strconv.FormatBool(images) + "\n\t"
list := service.MyService.App().GetSystemAppList()
for _, v := range list {
systemAppStatus += v.Image + ",\n\t"
}
systemAppStatus += "Sync Key length: " + strconv.Itoa(len(config.SystemConfigInfo.SyncKey))
var bugContent string = fmt.Sprintf(` var bugContent string = fmt.Sprintf(`
- OS: %s - OS: %s
- CasaOS Version: %s - CasaOS Version: %s
- Disk Total: %v - Disk Total: %v
- Disk Used: %v - Disk Used: %v
- Sync State: %s
- System Info: %s - System Info: %s
- Remote Version: %s
- Browser: $Browser$ - Browser: $Browser$
- Version: $Version$ - Version: $Version$
`, sys.OS, types.CURRENTVERSION, disk.Total>>20, disk.Used>>20, systemAppStatus, array) `, sys.OS, types.CURRENTVERSION, disk.Total>>20, disk.Used>>20, array, version.Version)
// array = append(array, fmt.Sprintf("disk,total:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent)) // array = append(array, fmt.Sprintf("disk,total:%v,used:%v,UsedPercent:%v", disk.Total>>20, disk.Used>>20, disk.UsedPercent))
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: bugContent}) c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: bugContent})
}
//widget配置
func GetWidgetConfig(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: json.RawMessage(config.SystemConfigInfo.WidgetList)})
}
// @Summary 修改组件配置文件
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/widget/config [post]
func PostSetWidgetConfig(c *gin.Context) {
buf := make([]byte, 1024)
n, _ := c.Request.Body.Read(buf)
service.MyService.System().UpSystemConfig("", string(buf[0:n]))
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
Data: json.RawMessage(config.SystemConfigInfo.WidgetList),
})
} }
// @Summary get casaos server port // @Summary get casaos server port
@@ -195,10 +106,10 @@ func PostSetWidgetConfig(c *gin.Context) {
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/port [get] // @Router /sys/port [get]
func GetCasaOSPort(c *gin.Context) { func GetCasaOSPort(c *gin.Context) {
c.JSON(http.StatusOK, c.JSON(common_err.SUCCESS,
model.Result{ model.Result{
Success: oasis_err.SUCCESS, Success: common_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS), Message: common_err.GetMsg(common_err.SUCCESS),
Data: config.ServerInfo.HttpPort, Data: config.ServerInfo.HttpPort,
}) })
} }
@@ -208,15 +119,18 @@ func GetCasaOSPort(c *gin.Context) {
// @Accept application/json // @Accept application/json
// @Tags sys // @Tags sys
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Param port formData string true "port" // @Param port json string true "port"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/port [put] // @Router /sys/port [put]
func PutCasaOSPort(c *gin.Context) { func PutCasaOSPort(c *gin.Context) {
port, err := strconv.Atoi(c.PostForm("port")) json := make(map[string]string)
c.ShouldBind(&json)
portStr := json["port"]
port, err := strconv.Atoi(portStr)
if err != nil { if err != nil {
c.JSON(http.StatusOK, c.JSON(common_err.SERVICE_ERROR,
model.Result{ model.Result{
Success: oasis_err.ERROR, Success: common_err.SERVICE_ERROR,
Message: err.Error(), Message: err.Error(),
}) })
return return
@@ -224,40 +138,18 @@ func PutCasaOSPort(c *gin.Context) {
isAvailable := port2.IsPortAvailable(port, "tcp") isAvailable := port2.IsPortAvailable(port, "tcp")
if !isAvailable { if !isAvailable {
c.JSON(http.StatusOK, c.JSON(common_err.SERVICE_ERROR,
model.Result{ model.Result{
Success: oasis_err.PORT_IS_OCCUPIED, Success: common_err.PORT_IS_OCCUPIED,
Message: oasis_err.GetMsg(oasis_err.PORT_IS_OCCUPIED), Message: common_err.GetMsg(common_err.PORT_IS_OCCUPIED),
}) })
return return
} }
service.MyService.System().UpSystemPort(strconv.Itoa(port)) service.MyService.System().UpSystemPort(strconv.Itoa(port))
c.JSON(http.StatusOK, c.JSON(common_err.SUCCESS,
model.Result{ model.Result{
Success: oasis_err.SUCCESS, Success: common_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS), Message: common_err.GetMsg(common_err.SUCCESS),
})
}
// @Summary 检查是否进入引导状态
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /guide/check [get]
func GetGuideCheck(c *gin.Context) {
initUser := false
if !config.UserInfo.Initialized {
initUser = true
}
data := make(map[string]interface{}, 1)
data["need_init_user"] = initUser
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
Data: data,
}) })
} }
@@ -267,7 +159,7 @@ func GetGuideCheck(c *gin.Context) {
// @Tags sys // @Tags sys
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/kill [post] // @Router /sys/restart [post]
func PostKillCasaOS(c *gin.Context) { func PostKillCasaOS(c *gin.Context) {
os.Exit(0) os.Exit(0)
} }
@@ -279,13 +171,22 @@ func PostKillCasaOS(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/usb/off [put] // @Router /sys/usb/off [put]
func PutSystemOffUSBAutoMount(c *gin.Context) { func PutSystemUSBAutoMount(c *gin.Context) {
service.MyService.System().UpdateUSBAutoMount("False") js := make(map[string]string)
service.MyService.System().ExecUSBAutoMountShell("False") c.ShouldBind(&js)
c.JSON(http.StatusOK, status := js["status"]
if status == "on" {
service.MyService.System().UpdateUSBAutoMount("True")
service.MyService.System().ExecUSBAutoMountShell("True")
} else {
service.MyService.System().UpdateUSBAutoMount("False")
service.MyService.System().ExecUSBAutoMountShell("False")
}
c.JSON(common_err.SUCCESS,
model.Result{ model.Result{
Success: oasis_err.SUCCESS, Success: common_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS), Message: common_err.GetMsg(common_err.SUCCESS),
}) })
} }
@@ -302,14 +203,48 @@ func GetSystemUSBAutoMount(c *gin.Context) {
state = "False" state = "False"
} }
c.JSON(http.StatusOK, c.JSON(common_err.SUCCESS,
model.Result{ model.Result{
Success: oasis_err.SUCCESS, Success: common_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS), Message: common_err.GetMsg(common_err.SUCCESS),
Data: state, Data: state,
}) })
} }
func GetSystemAppsStatus(c *gin.Context) {
systemAppList := service.MyService.App().GetSystemAppList()
appList := []model2.MyAppList{}
for _, v := range systemAppList {
name := strings.ReplaceAll(v.Names[0], "/", "")
if len(v.Labels["name"]) > 0 {
name = v.Labels["name"]
}
appList = append(appList, model2.MyAppList{
Name: name,
Icon: v.Labels["icon"],
State: v.State,
CustomId: v.Labels["custom_id"],
Id: v.ID,
Port: v.Labels["web"],
Index: v.Labels["index"],
//Order: m.Labels["order"],
Image: v.Image,
Latest: false,
//Type: m.Labels["origin"],
//Slogan: m.Slogan,
//Rely: m.Rely,
Host: v.Labels["host"],
Protocol: v.Labels["protocol"],
})
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: appList,
})
}
// @Summary get system hardware info // @Summary get system hardware info
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
@@ -320,40 +255,23 @@ func GetSystemUSBAutoMount(c *gin.Context) {
func GetSystemHardwareInfo(c *gin.Context) { func GetSystemHardwareInfo(c *gin.Context) {
data := make(map[string]string, 1) data := make(map[string]string, 1)
data["drive_model"] = service.MyService.ZiMa().GetDeviceTree() data["drive_model"] = service.MyService.System().GetDeviceTree()
c.JSON(http.StatusOK, c.JSON(common_err.SUCCESS,
model.Result{ model.Result{
Success: oasis_err.SUCCESS, Success: common_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS), Message: common_err.GetMsg(common_err.SUCCESS),
Data: data, Data: data,
}) })
} }
// @Summary Turn off usb auto-mount // @Summary system utilization
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags sys // @Tags sys
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/usb/on [put] // @Router /sys/utilization [get]
func PutSystemOnUSBAutoMount(c *gin.Context) { func GetSystemUtilization(c *gin.Context) {
service.MyService.System().UpdateUSBAutoMount("True")
service.MyService.System().ExecUSBAutoMountShell("True")
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err.SUCCESS,
Message: oasis_err.GetMsg(oasis_err.SUCCESS),
})
}
// @Summary system info
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/info [get]
func Info(c *gin.Context) {
var data = make(map[string]interface{}, 6) var data = make(map[string]interface{}, 6)
list := service.MyService.Disk().LSBLK(true) list := service.MyService.Disk().LSBLK(true)
@@ -373,6 +291,8 @@ func Info(c *gin.Context) {
s, _ := strconv.ParseUint(v.FSSize, 10, 64) s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64) a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64) u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
loger.Info("disk info", zap.Any("/ total:", s))
loger.Info("disk path", zap.Any("path", v.Path))
summary.Size += s summary.Size += s
summary.Avail += a summary.Avail += a
summary.Used += u summary.Used += u
@@ -385,6 +305,8 @@ func Info(c *gin.Context) {
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64) s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64) a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64) u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
loger.Info("disk info", zap.Any("/ total:", s))
loger.Info("disk path", zap.Any("path", list[i].Path))
summary.Size += s summary.Size += s
summary.Avail += a summary.Avail += a
summary.Used += u summary.Used += u
@@ -399,21 +321,20 @@ func Info(c *gin.Context) {
findSystem += 1 findSystem += 1
continue continue
} }
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" { if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
temp := service.MyService.Disk().SmartCTL(list[i].Path) temp := service.MyService.Disk().SmartCTL(list[i].Path)
if reflect.DeepEqual(temp, model.SmartctlA{}) { if reflect.DeepEqual(temp, model.SmartctlA{}) {
continue healthy = true
} } else {
healthy = temp.SmartStatus.Passed
//list[i].Temperature = temp.Temperature.Current
if !temp.SmartStatus.Passed {
healthy = false
} }
if len(list[i].Children) > 0 { if len(list[i].Children) > 0 {
for _, v := range list[i].Children { for _, v := range list[i].Children {
s, _ := strconv.ParseUint(v.FSSize, 10, 64) s, _ := strconv.ParseUint(v.FSSize, 10, 64)
a, _ := strconv.ParseUint(v.FSAvail, 10, 64) a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
u, _ := strconv.ParseUint(v.FSUsed, 10, 64) u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
loger.Info("disk info", zap.Any("/ total:", s))
loger.Info("disk path", zap.Any("path", list[i].Path))
summary.Size += s summary.Size += s
summary.Avail += a summary.Avail += a
summary.Used += u summary.Used += u
@@ -452,23 +373,23 @@ func Info(c *gin.Context) {
} }
} }
data["usb"] = usb data["usb"] = usb
cpu := service.MyService.ZiMa().GetCpuPercent() cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.ZiMa().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
data["cpu"] = cpuData data["cpu"] = cpuData
data["mem"] = service.MyService.ZiMa().GetMemInfo() data["mem"] = service.MyService.System().GetMemInfo()
//拼装网络信息 //拼装网络信息
netList := service.MyService.ZiMa().GetNetInfo() netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{} newNet := []model.IOCountersStat{}
nets := service.MyService.ZiMa().GetNet(true) nets := service.MyService.System().GetNet(true)
for _, n := range netList { for _, n := range netList {
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
@@ -478,5 +399,89 @@ func Info(c *gin.Context) {
data["net"] = newNet data["net"] = newNet
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 Get notification port
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/socket/port [get]
func GetSystemSocketPort(c *gin.Context) {
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: config.ServerInfo.SocketPort, // @tiger 这里最好封装成 {'port': ...} 的形式,来体现出参的上下文
})
}
// @Summary get cpu info
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/cpu [get]
func GetSystemCupInfo(c *gin.Context) {
cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum()
data := make(map[string]interface{})
data["percent"] = cpu
data["num"] = num
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
// @Summary get mem info
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/mem [get]
func GetSystemMemInfo(c *gin.Context) {
mem := service.MyService.System().GetMemInfo()
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mem})
}
// @Summary get disk info
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/disk [get]
func GetSystemDiskInfo(c *gin.Context) {
disk := service.MyService.System().GetDiskInfo()
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: disk})
}
// @Summary get Net info
// @Produce application/json
// @Accept application/json
// @Tags sys
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /sys/net [get]
func GetSystemNetInfo(c *gin.Context) {
netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{}
for _, n := range netList {
for _, netCardName := range service.MyService.System().GetNet(true) {
if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.System().GetNetState(n.Name))
item.Time = time.Now().Unix()
newNet = append(newNet, item)
break
}
}
}
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: newNet})
} }

View File

@@ -1,58 +0,0 @@
package v1
import (
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin"
"net/http"
"strconv"
)
// @Summary 获取task列表
// @Produce application/json
// @Accept application/json
// @Tags task
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /task/list [get]
func GetTaskList(c *gin.Context) {
//list := service.MyService.Task().List(true)
list := service.MyService.Task().GetServerTasks()
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS), Data: list})
}
func PutTaskUpdate(c *gin.Context) {
service.MyService.Task().SyncTaskService()
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
}
// @Summary 标记task已完成
// @Produce application/json
// @Accept application/json
// @Tags task
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /task/completion/{id} [put]
func PutTaskMarkerCompletion(c *gin.Context) {
id, _ := strconv.Atoi(c.Param("id"))
if id == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
return
}
var m model2.TaskDBModel
m.Id = uint(id)
m.State = types.TASK_STATE_COMPLETED
service.MyService.Task().Update(&m)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
}
func PostTaskAdd(c *gin.Context) {
var m model2.TaskDBModel
c.BindJSON(&m)
service.MyService.Task().Add(&m)
c.JSON(http.StatusOK, model.Result{Success: oasis_err.SUCCESS, Message: oasis_err.GetMsg(oasis_err.SUCCESS)})
}

View File

@@ -1,225 +1,278 @@
package v1 package v1
import ( import (
"fmt" json2 "encoding/json"
"io/ioutil"
"net/http" "net/http"
url2 "net/url"
"os"
"path"
"path/filepath"
"strconv"
"strings"
"time"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/model/system_model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
uuid "github.com/satori/go.uuid"
"github.com/tidwall/gjson"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin" "github.com/gin-gonic/gin"
) )
var user_service service.UserService // @Summary register user
// @Router /user/register/ [post]
func PostUserRegister(c *gin.Context) {
json := make(map[string]string)
c.ShouldBind(&json)
func init() { username := json["username"]
user_service = service.NewUserService() pwd := json["password"]
} key := json["key"]
if _, ok := service.UserRegisterHash[key]; !ok {
// @Summary 设置用户名和密码 c.JSON(common_err.CLIENT_ERROR,
// @Produce application/json model.Result{Success: common_err.KEY_NOT_EXIST, Message: common_err.GetMsg(common_err.KEY_NOT_EXIST)})
// @Accept multipart/form-data
// @Tags user
// @Param username formData string true "User name"
// @Param pwd formData string true "password"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /user/setusernamepwd [post]
func Set_Name_Pwd(c *gin.Context) {
//json := make(map[string]string)
//c.BindJSON(&json)
username := c.PostForm("username")
pwd := c.PostForm("pwd")
//老用户名是否存在即新用户名和密码的验证
if config.UserInfo.Initialized || len(username) == 0 || len(pwd) == 0 {
c.JSON(http.StatusOK,
model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return return
} }
//开始设置
err := user_service.SetUser(username, pwd, "", "", "", "") if len(username) == 0 || len(pwd) == 0 {
if err != nil { c.JSON(common_err.CLIENT_ERROR,
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: fmt.Sprintf("%v", err)}) model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
} else {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)})
return return
} }
if len(pwd) < 6 {
c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.PWD_IS_TOO_SIMPLE, Message: common_err.GetMsg(common_err.PWD_IS_TOO_SIMPLE)})
return
}
oldUser := service.MyService.User().GetUserInfoByUserName(username)
if oldUser.Id > 0 {
c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.USER_EXIST, Message: common_err.GetMsg(common_err.USER_EXIST)})
return
}
user := model2.UserDBModel{}
user.Username = username
user.Password = encryption.GetMD5ByStr(pwd)
user.Role = "admin"
user = service.MyService.User().CreateUser(user)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
return
}
file.MkDir(config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id))
delete(service.UserRegisterHash, key)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary 登录 // @Summary login
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept application/json
// @Tags user // @Tags user
// @Param username formData string true "User name" // @Param user_name query string true "User name"
// @Param pwd formData string true "password" // @Param pwd query string true "password"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /user/login [post] // @Router /user/login [post]
func Login(c *gin.Context) { func PostUserLogin(c *gin.Context) {
username := c.PostForm("username") json := make(map[string]string)
pwd := c.PostForm("pwd") c.ShouldBind(&json)
//检查参数是否正确
if len(username) == 0 || len(pwd) == 0 { username := json["username"]
c.JSON(http.StatusOK,
password := json["password"]
//check params is empty
if len(username) == 0 || len(password) == 0 {
c.JSON(common_err.CLIENT_ERROR,
model.Result{ model.Result{
Success: oasis_err2.ERROR, Success: common_err.CLIENT_ERROR,
Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS), Message: common_err.GetMsg(common_err.INVALID_PARAMS),
}) })
return return
} }
user := service.MyService.User().GetUserAllInfoByName(username)
if config.UserInfo.UserName == username && config.UserInfo.PWD == pwd { if user.Id == 0 {
//if username == "admin" && pwd == "admin" { c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
data := make(map[string]string, 2)
data["token"] = jwt2.GetToken(username, pwd)
data["version"] = types.CURRENTVERSION
//user_service.SetUser("", "", token, "", "")
c.JSON(http.StatusOK,
model.Result{
Success: oasis_err2.SUCCESS,
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS),
Data: data,
})
return return
} }
c.JSON(http.StatusOK, if user.Password != encryption.GetMD5ByStr(password) {
c.JSON(common_err.CLIENT_ERROR,
model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
return
}
token := system_model.VerifyInformation{}
token.AccessToken = jwt.GetAccessToken(user.Username, user.Password, user.Id)
token.RefreshToken = jwt.GetRefreshToken(user.Username, user.Password, user.Id)
token.ExpiresAt = time.Now().Add(3 * time.Hour * time.Duration(1)).Unix()
data := make(map[string]interface{}, 2)
user.Password = ""
data["token"] = token
// TODO:1 Database fields cannot be external
data["user"] = user
c.JSON(common_err.SUCCESS,
model.Result{ model.Result{
Success: oasis_err2.ERROR, Success: common_err.SUCCESS,
Message: oasis_err2.GetMsg(oasis_err2.ERROR), Message: common_err.GetMsg(common_err.SUCCESS),
Data: data,
}) })
} }
// @Summary 修改头像 // @Summary edit user head
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept multipart/form-data
// @Tags user // @Tags user
// @Param file formData file true "用户头像" // @Param file formData file true "用户头像"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /user/changhead [post] // @Router /user/avatar [put]
func PostUserHead(c *gin.Context) { func PutUserAvatar(c *gin.Context) {
file, _, _ := c.Request.FormFile("file") id := c.GetHeader("user_id")
user_service.UpLoadFile(file, config.UserInfo.Head) user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
f, err := c.FormFile("file")
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: err.Error()})
return
}
if len(user.Avatar) > 0 {
os.RemoveAll(config.AppInfo.UserDataPath + "/" + id + "/" + user.Avatar)
}
ext := filepath.Ext(f.Filename)
avatarPath := config.AppInfo.UserDataPath + "/" + id + "/avatar" + ext
c.SaveUploadedFile(f, avatarPath)
user.Avatar = avatarPath
service.MyService.User().UpdateUser(user)
c.JSON(http.StatusOK, c.JSON(http.StatusOK,
model.Result{ model.Result{
Success: oasis_err2.SUCCESS, Success: common_err.SUCCESS,
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Message: common_err.GetMsg(common_err.SUCCESS),
Data: config.UserInfo.Head, Data: user,
}) })
} }
// @Summary 修改用户名 // @Summary edit user name
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept application/json
// @Tags user // @Tags user
// @Param username formData string true "User name" // @Param old_name query string true "Old user name"
// @Param oldname formData string true "Old user name"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /user/username [put] // @Router /user/name/:id [put]
func PutUserName(c *gin.Context) { func PutUserInfo(c *gin.Context) {
if config.ServerInfo.LockAccount { id := c.GetHeader("user_id")
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ACCOUNT_LOCK, Message: oasis_err2.GetMsg(oasis_err2.ACCOUNT_LOCK)}) json := model2.UserDBModel{}
c.ShouldBind(&json)
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return return
} }
oldname := c.PostForm("oldname") if len(json.Username) > 0 {
username := c.PostForm("username") u := service.MyService.User().GetUserInfoByUserName(json.Username)
if len(username) == 0 || config.UserInfo.UserName != oldname { if u.Id > 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ERROR, Message: oasis_err2.GetMsg(oasis_err2.ERROR)}) c.JSON(common_err.CLIENT_ERROR,
return model.Result{Success: common_err.USER_EXIST, Message: common_err.GetMsg(common_err.USER_EXIST)})
return
}
} }
user_service.SetUser(username, "", "", "", "", "")
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) if len(json.Email) == 0 {
json.Email = user.Email
}
if len(json.Avatar) == 0 {
json.Avatar = user.Avatar
}
if len(json.Role) == 0 {
json.Role = user.Role
}
if len(json.Description) == 0 {
json.Description = user.Description
}
if len(json.Nickname) == 0 {
json.Nickname = user.Nickname
}
service.MyService.User().UpdateUser(json)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json})
} }
// @Summary 修改密码 // @Summary edit user password
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept application/json
// @Tags user // @Tags user
// @Param pwd formData string true "Password"
// @Param old_pwd formData string true "Old password"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /user/password [put] // @Router /user/password/:id [put]
func PutUserPwd(c *gin.Context) { func PutUserPassword(c *gin.Context) {
oldPwd := c.PostForm("old_pwd") id := c.GetHeader("user_id")
pwd := c.PostForm("pwd") json := make(map[string]string)
if config.UserInfo.PWD != oldPwd { c.ShouldBind(&json)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID_OLD, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID_OLD)}) oldPwd := json["old_password"]
pwd := json["password"]
if len(oldPwd) == 0 || len(pwd) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return return
} }
if config.ServerInfo.LockAccount { user := service.MyService.User().GetUserAllInfoById(id)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.ACCOUNT_LOCK, Message: oasis_err2.GetMsg(oasis_err2.ACCOUNT_LOCK)}) if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return return
} }
if len(pwd) == 0 { if user.Password != encryption.GetMD5ByStr(oldPwd) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_IS_EMPTY, Message: oasis_err2.GetMsg(oasis_err2.PWD_IS_EMPTY)}) c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID_OLD, Message: common_err.GetMsg(common_err.PWD_INVALID_OLD)})
return return
} }
user_service.SetUser("", pwd, "", "", "", "") user.Password = encryption.GetMD5ByStr(pwd)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS)}) service.MyService.User().UpdateUserPassword(user)
} user.Password = ""
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
// @Summary edit user info
// @Produce application/json
// @Accept multipart/form-data
// @Tags user
// @Param user_name formData string false "User Name"
// @Param email formData string false "Email"
// @Param description formData string false "Description"
// @Param pwd formData string false "Password"
// @Param old_pwd formData string false "Old password"
// @Param nick_name formData string false "nick name"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /user/info [post]
func PostUserChangeInfo(c *gin.Context) {
username := c.PostForm("user_name")
email := c.PostForm("email")
description := c.PostForm("description")
nickName := c.PostForm("nick_name")
oldpwd := c.PostForm("old_pwd")
pwd := c.PostForm("pwd")
if len(pwd) > 0 && config.UserInfo.PWD != oldpwd {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.PWD_INVALID, Message: oasis_err2.GetMsg(oasis_err2.PWD_INVALID)})
return
}
user_service.SetUser(username, pwd, "", email, description, nickName)
data := make(map[string]string, 4)
data["token"] = jwt2.GetToken(username, pwd)
data["user_name"] = username
data["head"] = config.UserInfo.Head
data["nick_name"] = config.UserInfo.NickName
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
} }
// @Summary edit user nick // @Summary edit user nick
// @Produce application/json // @Produce application/json
// @Accept multipart/form-data // @Accept application/json
// @Tags user // @Tags user
// @Param nick_name formData string false "nick name" // @Param nick_name query string false "nick name"
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /user/nick [put] // @Router /user/nick [put]
func PutUserChangeNick(c *gin.Context) { func PutUserNick(c *gin.Context) {
nickName := c.PostForm("nick_name") id := c.GetHeader("user_id")
json := make(map[string]string)
if len(nickName) == 0 { c.ShouldBind(&json)
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)}) Nickname := json["nick_name"]
if len(Nickname) == 0 {
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return return
} }
user_service.SetUser("", "", "", "", "", nickName) user := service.MyService.User().GetUserInfoById(id)
data := make(map[string]string, 1) if user.Id == 0 {
data["nick_name"] = config.UserInfo.NickName c.JSON(http.StatusOK,
go service.MyService.Casa().PushUserInfo() model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) return
}
user.Nickname = Nickname
service.MyService.User().UpdateUser(user)
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
} }
// @Summary edit user description // @Summary edit user description
@@ -230,72 +283,401 @@ func PutUserChangeNick(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /user/desc [put] // @Router /user/desc [put]
func PutUserChangeDesc(c *gin.Context) { func PutUserDesc(c *gin.Context) {
desc := c.PostForm("description") id := c.GetHeader("user_id")
json := make(map[string]string)
c.ShouldBind(&json)
desc := json["description"]
if len(desc) == 0 { if len(desc) == 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
} }
user_service.SetUser("", "", "", "", desc, "") user := service.MyService.User().GetUserInfoById(id)
data := make(map[string]string, 1) if user.Id == 0 {
data["description"] = config.UserInfo.Description c.JSON(http.StatusOK,
go service.MyService.Casa().PushUserInfo() model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data}) return
} }
user.Description = desc
// @Summary Modify user person information (Initialization use) service.MyService.User().UpdateUser(user)
// @Produce application/json
// @Accept multipart/form-data c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
// @Tags user
// @Param nick_name formData string false "user nick name"
// @Param description formData string false "Description"
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /user/person/info [post]
func PostUserPersonInfo(c *gin.Context) {
desc := c.PostForm("description")
nickName := c.PostForm("nick_name")
if len(desc) == 0 || len(nickName) == 0 {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.INVALID_PARAMS, Message: oasis_err2.GetMsg(oasis_err2.INVALID_PARAMS)})
return
}
user_service.SetUser("", "", "", "", desc, nickName)
data := make(map[string]string, 2)
data["description"] = config.UserInfo.Description
data["nick_name"] = config.UserInfo.NickName
go service.MyService.Casa().PushUserInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
} }
// @Summary get user info // @Summary get user info
// @Produce application/json // @Produce application/json
// @Accept mapplication/json // @Accept application/json
// @Tags user // @Tags user
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /user/info [get] // @Router /user/info/:id [get]
func GetUserInfo(c *gin.Context) { func GetUserInfo(c *gin.Context) {
var u = make(map[string]string, 5) id := c.GetHeader("user_id")
u["user_name"] = config.UserInfo.UserName user := service.MyService.User().GetUserInfoById(id)
u["head"] = config.UserInfo.Head
u["email"] = config.UserInfo.Email c.JSON(common_err.SUCCESS,
u["description"] = config.UserInfo.Description
u["nick_name"] = config.UserInfo.NickName
c.JSON(http.StatusOK,
model.Result{ model.Result{
Success: oasis_err2.SUCCESS, Success: common_err.SUCCESS,
Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Message: common_err.GetMsg(common_err.SUCCESS),
Data: u, Data: user,
}) })
} }
// @Summary Get my shareId /**
* @description:
* @param {*gin.Context} c
* @param {string} Username
* @return {*}
* @method:
* @router:
*/
func GetUserInfoByUsername(c *gin.Context) {
username := c.Param("username")
if len(username) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
user := service.MyService.User().GetUserInfoByUserName(username)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: user,
})
}
/**
* @description: get all Usernames
* @method:GET
* @router:/user/all/name
*/
func GetUserAllUsername(c *gin.Context) {
users := service.MyService.User().GetAllUserName()
names := []string{}
for _, v := range users {
names = append(names, v.Username)
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: names,
})
}
/**
* @description:get custom file by user
* @param {path} name string "file name"
* @method: GET
* @router: /user/custom/:key
*/
func GetUserCustomConf(c *gin.Context) {
name := c.Param("key")
if len(name) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
id := c.GetHeader("user_id")
user := service.MyService.User().GetUserInfoById(id)
// user := service.MyService.User().GetUserInfoByUsername(Username)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
filePath := config.AppInfo.UserDataPath + "/" + id + "/" + name + ".json"
data := file.ReadFullFile(filePath)
if !gjson.ValidBytes(data) {
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(data)})
return
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))})
}
/**
* @description:create or update custom conf by user
* @param {path} name string "file name"
* @method:POST
* @router:/user/custom/:key
*/
func PostUserCustomConf(c *gin.Context) {
name := c.Param("key")
if len(name) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
id := c.GetHeader("user_id")
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
data, _ := ioutil.ReadAll(c.Request.Body)
filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id)
file.WriteToPath(data, filePath, name+".json")
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))})
}
/**
* @description: delete user custom config
* @param {path} key string
* @method:delete
* @router:/user/custom/:key
*/
func DeleteUserCustomConf(c *gin.Context) {
name := c.Param("key")
if len(name) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
id := c.GetHeader("user_id")
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR,
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + name + ".json"
err := os.Remove(filePath)
if err != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
return
}
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
/**
* @description:
* @param {path} id string "user id"
* @method:DELETE
* @router:/user/delete/:id
*/
func DeleteUser(c *gin.Context) {
id := c.Param("id")
service.MyService.User().DeleteUserById(id)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
}
/**
* @description:update user image
* @method:POST
* @router:/user/current/image/:key
*/
func PutUserImage(c *gin.Context) {
id := c.GetHeader("user_id")
json := make(map[string]string)
c.ShouldBind(&json)
path := json["path"]
key := c.Param("key")
if len(path) == 0 || len(key) == 0 {
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
if !file.Exists(path) {
c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
return
}
_, err := file.GetImageExt(path)
if err != nil {
c.JSON(http.StatusOK, model.Result{Success: common_err.NOT_IMAGE, Message: common_err.GetMsg(common_err.NOT_IMAGE)})
return
}
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(http.StatusOK, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
fstat, _ := os.Stat(path)
if fstat.Size() > 10<<20 {
c.JSON(http.StatusOK, model.Result{Success: common_err.IMAGE_TOO_LARGE, Message: common_err.GetMsg(common_err.IMAGE_TOO_LARGE)})
return
}
ext := file.GetExt(path)
filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + key + ext
file.CopySingleFile(path, filePath, "overwrite")
data := make(map[string]string, 3)
data["path"] = filePath
data["file_name"] = key + ext
data["online_path"] = "/v1/users/image?path=" + filePath
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
/**
* @description:
* @param {*gin.Context} c
* @param {file} file
* @param {string} key
* @param {string} type:avatar,background
* @return {*}
* @method:
* @router:
*/
func PostUserUploadImage(c *gin.Context) {
id := c.GetHeader("user_id")
f, err := c.FormFile("file")
key := c.Param("key")
t := c.PostForm("type")
if len(key) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
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: err.Error()})
return
}
_, err = file.GetImageExtByName(f.Filename)
if err != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NOT_IMAGE, Message: common_err.GetMsg(common_err.NOT_IMAGE)})
return
}
ext := filepath.Ext(f.Filename)
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
if t == "avatar" {
key = "avatar"
}
path := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + key + ext
c.SaveUploadedFile(f, path)
data := make(map[string]string, 3)
data["path"] = path
data["file_name"] = key + ext
data["online_path"] = "/v1/users/image?path=" + path
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
}
/**
* @description: get current user's image
* @method:GET
* @router:/user/image/:id
*/
func GetUserImage(c *gin.Context) {
filePath := c.Query("path")
if len(filePath) == 0 {
c.JSON(http.StatusNotFound, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
if !file.Exists(filePath) {
c.JSON(http.StatusNotFound, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
return
}
if !strings.Contains(filePath, config.AppInfo.UserDataPath) {
c.JSON(http.StatusNotFound, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
return
}
fileTmp, _ := os.Open(filePath)
defer fileTmp.Close()
fileName := path.Base(filePath)
// @tiger - RESTful 规范下不应该返回文件本身内容而是返回文件的静态URL由前端去解析
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
c.File(filePath)
}
func DeleteUserImage(c *gin.Context) {
id := c.GetHeader("user_id")
path := c.Query("path")
if len(path) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
}
user := service.MyService.User().GetUserInfoById(id)
if user.Id == 0 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
return
}
if !file.Exists(path) {
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
}
if !strings.Contains(path, config.AppInfo.UserDataPath+"/"+strconv.Itoa(user.Id)) {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
return
}
os.Remove(path)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
/**
* @description:
* @param {*gin.Context} c
* @param {string} refresh_token
* @return {*}
* @method:
* @router:
*/
func PostUserRefreshToken(c *gin.Context) {
js := make(map[string]string)
c.ShouldBind(&js)
refresh := js["refresh_token"]
claims, err := jwt.ParseToken(refresh, true)
if err != nil {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.VERIFICATION_FAILURE, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE), Data: err.Error()})
return
}
if !claims.VerifyExpiresAt(time.Now(), true) || !claims.VerifyIssuer("refresh", true) {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.VERIFICATION_FAILURE, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE)})
return
}
newToken := jwt.GetAccessToken(claims.Username, claims.PassWord, claims.Id)
verifyInfo := system_model.VerifyInformation{}
verifyInfo.AccessToken = newToken
verifyInfo.RefreshToken = jwt.GetRefreshToken(claims.Username, claims.PassWord, claims.Id)
verifyInfo.ExpiresAt = time.Now().Add(3 * time.Hour * time.Duration(1)).Unix()
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: verifyInfo})
}
func DeleteUserAll(c *gin.Context) {
service.MyService.User().DeleteAllUser()
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
}
// @Summary 检查是否进入引导状态
// @Produce application/json // @Produce application/json
// @Accept application/json // @Accept application/json
// @Tags user // @Tags sys
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /user/shareid [get] // @Router /sys/init/check [get]
func GetUserShareID(c *gin.Context) { func GetUserStatus(c *gin.Context) {
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: config.ServerInfo.Token}) data := make(map[string]interface{}, 2)
if service.MyService.User().GetUserCount() > 0 {
data["initialized"] = true
data["key"] = ""
} else {
key := uuid.NewV4().String()
service.UserRegisterHash[key] = key
data["key"] = key
data["initialized"] = false
}
c.JSON(common_err.SUCCESS,
model.Result{
Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS),
Data: data,
})
} }

View File

@@ -1,96 +0,0 @@
package v1
import (
"net/http"
"strings"
"time"
"unsafe"
"github.com/IceWhaleTech/CasaOS/model"
oasis_err2 "github.com/IceWhaleTech/CasaOS/pkg/utils/oasis_err"
"github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin"
)
// @Summary 获取cpu信息
// @Produce application/json
// @Accept application/json
// @Tags zima
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zima/getcpuinfo [get]
func CupInfo(c *gin.Context) {
//检查参数是否正确
cpu := service.MyService.ZiMa().GetCpuPercent()
num := service.MyService.ZiMa().GetCpuCoreNum()
data := make(map[string]interface{})
data["percent"] = cpu
data["num"] = num
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: data})
}
// @Summary 获取内存信息
// @Produce application/json
// @Accept application/json
// @Tags zima
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zima/getmeminfo [get]
func MemInfo(c *gin.Context) {
//检查参数是否正确
mem := service.MyService.ZiMa().GetMemInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: mem})
}
// @Summary 获取硬盘信息
// @Produce application/json
// @Accept application/json
// @Tags zima
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zima/getdiskinfo [get]
func DiskInfo(c *gin.Context) {
disk := service.MyService.ZiMa().GetDiskInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: disk})
}
// @Summary 获取网络信息
// @Produce application/json
// @Accept application/json
// @Tags zima
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zima/getnetinfo [get]
func NetInfo(c *gin.Context) {
netList := service.MyService.ZiMa().GetNetInfo()
newNet := []model.IOCountersStat{}
for _, n := range netList {
for _, netCardName := range service.MyService.ZiMa().GetNet(true) {
if n.Name == netCardName {
item := *(*model.IOCountersStat)(unsafe.Pointer(&n))
item.State = strings.TrimSpace(service.MyService.ZiMa().GetNetState(n.Name))
item.Time = time.Now().Unix()
newNet = append(newNet, item)
break
}
}
}
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: newNet})
}
// @Summary 获取信息系统信息
// @Produce application/json
// @Accept application/json
// @Tags zima
// @Security ApiKeyAuth
// @Success 200 {string} string "ok"
// @Router /zima/sysinfo [get]
func SysInfo(c *gin.Context) {
info := service.MyService.ZiMa().GetSysInfo()
c.JSON(http.StatusOK, model.Result{Success: oasis_err2.SUCCESS, Message: oasis_err2.GetMsg(oasis_err2.SUCCESS), Data: info})
}

View File

@@ -7,7 +7,6 @@ import (
"io" "io"
"io/ioutil" "io/ioutil"
"runtime" "runtime"
"strconv"
"strings" "strings"
"sync" "sync"
"time" "time"
@@ -15,33 +14,29 @@ import (
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command" "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/docker/docker/api/types" "github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/filters" "github.com/docker/docker/api/types/filters"
client2 "github.com/docker/docker/client" client2 "github.com/docker/docker/client"
"github.com/pkg/errors" "github.com/pkg/errors"
uuid "github.com/satori/go.uuid" uuid "github.com/satori/go.uuid"
"go.uber.org/zap"
"gorm.io/gorm" "gorm.io/gorm"
) )
type AppService interface { type AppService interface {
CreateApplication(m model2.ApplicationModel) model2.ApplicationModel
GetApplicationList() (m []model2.ApplicationModel)
GetApplicationById(id string) (m model2.ApplicationModel)
UpdateApplicationOrderById(id string, order int)
GetMyList(index, size int, position bool) (*[]model2.MyAppList, *[]model2.MyAppList) GetMyList(index, size int, position bool) (*[]model2.MyAppList, *[]model2.MyAppList)
GetCasaOSCount() int
SaveContainer(m model2.AppListDBModel) SaveContainer(m model2.AppListDBModel)
GetUninstallInfo(id string) model2.AppListDBModel GetUninstallInfo(id string) model2.AppListDBModel
DeleteApp(id string) DeleteApp(id string)
GetContainerInfo(name string) (types.Container, error) GetContainerInfo(id string) (types.Container, error)
GetAppDBInfo(id string) model2.AppListDBModel GetAppDBInfo(id string) model2.AppListDBModel
UpdateApp(m model2.AppListDBModel) UpdateApp(m model2.AppListDBModel)
GetSimpleContainerInfo(name string) (types.Container, error) GetSimpleContainerInfo(id string) (types.Container, error)
DelAppConfigDir(path string) DelAppConfigDir(path string)
GetSystemAppList() []types.Container GetSystemAppList() []types.Container
GetHardwareUsageSteam() GetHardwareUsageStream()
GetHardwareUsage() []model.DockerStatsModel GetHardwareUsage() []model.DockerStatsModel
GetAppStats(id string) string GetAppStats(id string) string
GetAllDBApps() []model2.AppListDBModel GetAllDBApps() []model2.AppListDBModel
@@ -50,26 +45,7 @@ type AppService interface {
} }
type appStruct struct { type appStruct struct {
db *gorm.DB db *gorm.DB
log loger2.OLog
}
func (a *appStruct) GetApplicationById(id string) (m model2.ApplicationModel) {
a.db.Where("id = ?", id).First(&m)
return
}
func (a *appStruct) UpdateApplicationOrderById(id string, order int) {
a.db.Model(&model2.ApplicationModel{}).Where("id = ?", id).Update("order", order)
}
func (a *appStruct) CreateApplication(m model2.ApplicationModel) model2.ApplicationModel {
a.db.Create(&m)
return m
}
func (a *appStruct) GetApplicationList() (m []model2.ApplicationModel) {
a.db.Find(&m)
return
} }
func (a *appStruct) CheckNewImage() { func (a *appStruct) CheckNewImage() {
@@ -155,37 +131,13 @@ func (a *appStruct) ImportApplications(casaApp bool) {
// } // }
// MyService.Docker().DockerContainerStart(container_id) // MyService.Docker().DockerContainerStart(container_id)
//} //}
}
func (a *appStruct) GetCasaOSCount() int {
//获取docker应用
cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
if err != nil {
a.log.Error("初始化client失败", "app.getmylist", "line:36", err)
return 0
}
defer cli.Close()
fts := filters.NewArgs()
fts.Add("label", "casaos=casaos")
//fts.Add("label", "casaos:casaos")
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{Filters: fts, Limit: 200})
if err != nil {
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err)
return 0
}
systemApp := MyService.App().GetApplicationList()
return len(containers) + len(systemApp)
} }
//获取我的应用列表 //获取我的应用列表
func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppList, *[]model2.MyAppList) { func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppList, *[]model2.MyAppList) {
//获取docker应用
cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5)) cli, err := client2.NewClientWithOpts(client2.FromEnv, client2.WithTimeout(time.Second*5))
if err != nil { if err != nil {
a.log.Error("初始化client失败", "app.getmylist", "line:36", err) loger.Error("Failed to init client", zap.Any("err", err))
} }
defer cli.Close() defer cli.Close()
// fts := filters.NewArgs() // fts := filters.NewArgs()
@@ -194,7 +146,7 @@ func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppLi
//fts.Add("casaos", "casaos") //fts.Add("casaos", "casaos")
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true}) containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true})
if err != nil { if err != nil {
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err) loger.Error("Failed to get container_list", zap.Any("err", err))
} }
//获取本地数据库应用 //获取本地数据库应用
@@ -202,54 +154,51 @@ func (a *appStruct) GetMyList(index, size int, position bool) (*[]model2.MyAppLi
list := []model2.MyAppList{} list := []model2.MyAppList{}
systemApp := MyService.App().GetApplicationList()
for _, v := range systemApp {
list = append(list, model2.MyAppList{
Name: v.Name,
Icon: v.Icon,
State: strconv.Itoa(v.State),
Id: strconv.Itoa(v.Id),
CustomId: strconv.Itoa(v.Id),
Port: "",
//Order: strconv.Itoa(v.Order),
Index: "/",
Image: "",
Type: v.Type,
NewVersion: false,
})
}
for _, m := range containers { for _, m := range containers {
if m.Labels["casaos"] == "casaos" { if m.Labels["casaos"] == "casaos" {
if m.Labels["origin"] == "system" {
continue
}
_, newVersion := NewVersionApp[m.ID] _, newVersion := NewVersionApp[m.ID]
name := strings.ReplaceAll(m.Names[0], "/", "")
icon := m.Labels["icon"]
if len(m.Labels["name"]) > 0 {
name = m.Labels["name"]
}
if m.Labels["origin"] == "system" {
name = strings.Split(m.Image, ":")[0]
if len(strings.Split(name, "/")) > 1 {
icon = "https://icon.casaos.io/main/all/" + strings.Split(name, "/")[1] + ".png"
}
}
list = append(list, model2.MyAppList{ list = append(list, model2.MyAppList{
Name: strings.ReplaceAll(m.Names[0], "/", ""), Name: name,
Icon: m.Labels["icon"], Icon: icon,
State: m.State, State: m.State,
CustomId: m.Labels["custom_id"], CustomId: m.Labels["custom_id"],
Id: m.ID, Id: m.ID,
Port: m.Labels["web"], Port: m.Labels["web"],
Index: m.Labels["index"], Index: m.Labels["index"],
//Order: m.Labels["order"], //Order: m.Labels["order"],
Image: m.Image, Image: m.Image,
NewVersion: newVersion, Latest: newVersion,
Type: m.Labels["origin"], //Type: m.Labels["origin"],
//Slogan: m.Slogan, //Slogan: m.Slogan,
//Rely: m.Rely, //Rely: m.Rely,
Host: m.Labels["host"],
Protocol: m.Labels["protocol"],
}) })
} else { } else {
unTranslation = append(unTranslation, model2.MyAppList{ unTranslation = append(unTranslation, model2.MyAppList{
Name: strings.ReplaceAll(m.Names[0], "/", ""), Name: strings.ReplaceAll(m.Names[0], "/", ""),
Icon: "", Icon: "",
State: m.State, State: m.State,
CustomId: m.ID, CustomId: m.ID,
Id: m.ID, Id: m.ID,
Port: "", Port: "",
NewVersion: false, Latest: false,
Image: m.Image, Host: "",
Protocol: "",
Image: m.Image,
}) })
} }
} }
@@ -304,14 +253,14 @@ func (a *appStruct) GetSystemAppList() []types.Container {
//获取docker应用 //获取docker应用
cli, err := client2.NewClientWithOpts(client2.FromEnv) cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil { if err != nil {
a.log.Error("初始化client失败", "app.getmylist", "line:36", err) loger.Error("Failed to init client", zap.Any("err", err))
} }
defer cli.Close() defer cli.Close()
fts := filters.NewArgs() fts := filters.NewArgs()
fts.Add("label", "origin=system") fts.Add("label", "origin=system")
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts}) containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
if err != nil { if err != nil {
a.log.Error("获取docker容器失败", "app.sys", "line:123", err) loger.Error("Failed to get container_list", zap.Any("err", err))
} }
//获取本地数据库应用 //获取本地数据库应用
@@ -335,17 +284,17 @@ func (a *appStruct) GetAllDBApps() []model2.AppListDBModel {
} }
//获取我的应用列表 //获取我的应用列表
func (a *appStruct) GetContainerInfo(name string) (types.Container, error) { func (a *appStruct) GetContainerInfo(id string) (types.Container, error) {
//获取docker应用 //获取docker应用
cli, err := client2.NewClientWithOpts(client2.FromEnv) cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil { if err != nil {
a.log.Error("初始化client失败", "app.getmylist", "line:36", err) loger.Error("Failed to init client", zap.Any("err", err))
} }
filters := filters.NewArgs() filters := filters.NewArgs()
filters.Add("name", name) filters.Add("id", id)
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters}) containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
if err != nil { if err != nil {
a.log.Error("获取docker容器失败", "app.getcontainerinfo", "line:182", err) loger.Error("Failed to get container_list", zap.Any("err", err))
} }
if len(containers) > 0 { if len(containers) > 0 {
@@ -355,7 +304,7 @@ func (a *appStruct) GetContainerInfo(name string) (types.Container, error) {
} }
func (a *appStruct) GetSimpleContainerInfo(name string) (types.Container, error) { func (a *appStruct) GetSimpleContainerInfo(id string) (types.Container, error) {
//获取docker应用 //获取docker应用
cli, err := client2.NewClientWithOpts(client2.FromEnv) cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil { if err != nil {
@@ -363,7 +312,7 @@ func (a *appStruct) GetSimpleContainerInfo(name string) (types.Container, error)
} }
defer cli.Close() defer cli.Close()
filters := filters.NewArgs() filters := filters.NewArgs()
filters.Add("name", name) filters.Add("id", id)
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters}) containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: filters})
if err != nil { if err != nil {
return types.Container{}, err return types.Container{}, err
@@ -399,7 +348,7 @@ func (a *appStruct) UpdateApp(m model2.AppListDBModel) {
} }
func (a *appStruct) DelAppConfigDir(path string) { func (a *appStruct) DelAppConfigDir(path string) {
command.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelAppConfigDir " + path) command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;DelAppConfigDir " + path)
} }
func (a *appStruct) DeleteApp(id string) { func (a *appStruct) DeleteApp(id string) {
@@ -427,12 +376,12 @@ func (a *appStruct) GetAppStats(id string) string {
func (a *appStruct) GetHardwareUsage() []model.DockerStatsModel { func (a *appStruct) GetHardwareUsage() []model.DockerStatsModel {
steam := true stream := true
for !isFinish { for !isFinish {
if steam { if stream {
steam = false stream = false
go func() { go func() {
a.GetHardwareUsageSteam() a.GetHardwareUsageStream()
}() }()
} }
runtime.Gosched() runtime.Gosched()
@@ -447,7 +396,7 @@ func (a *appStruct) GetHardwareUsage() []model.DockerStatsModel {
} }
func (a *appStruct) GetHardwareUsageSteam() { func (a *appStruct) GetHardwareUsageStream() {
cli, err := client2.NewClientWithOpts(client2.FromEnv) cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil { if err != nil {
@@ -460,23 +409,33 @@ func (a *appStruct) GetHardwareUsageSteam() {
fts := filters.NewArgs() fts := filters.NewArgs()
fts.Add("label", "casaos=casaos") fts.Add("label", "casaos=casaos")
//fts.Add("label", "casaos") //fts.Add("status", "running")
//fts.Add("casaos", "casaos")
containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts}) containers, err := cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
if err != nil { if err != nil {
a.log.Error("获取docker容器失败", "app.getmylist", "line:42", err) loger.Error("Failed to get container_list", zap.Any("err", err))
} }
for i := 0; i < 100; i++ { for i := 0; i < 100; i++ {
if i%10 == 0 {
containers, err = cli.ContainerList(context.Background(), types.ContainerListOptions{All: true, Filters: fts})
if err != nil {
loger.Error("Failed to get container_list", zap.Any("err", err))
continue
}
}
if config.CasaOSGlobalVariables.AppChange { if config.CasaOSGlobalVariables.AppChange {
config.CasaOSGlobalVariables.AppChange = false config.CasaOSGlobalVariables.AppChange = false
dataStats.Range(func(key, value interface{}) bool { dataStats.Range(func(key, value interface{}) bool {
dataStats.Delete(key) dataStats.Delete(key)
return true return true
}) })
} }
var temp sync.Map
var wg sync.WaitGroup var wg sync.WaitGroup
for _, v := range containers { for _, v := range containers {
if v.State != "running" {
continue
}
wg.Add(1) wg.Add(1)
go func(v types.Container, i int) { go func(v types.Container, i int) {
defer wg.Done() defer wg.Done()
@@ -492,25 +451,30 @@ func (a *appStruct) GetHardwareUsageSteam() {
m, _ := dataStats.Load(v.ID) m, _ := dataStats.Load(v.ID)
dockerStats := model.DockerStatsModel{} dockerStats := model.DockerStatsModel{}
if m != nil { if m != nil {
dockerStats.Pre = m.(model.DockerStatsModel).Data dockerStats.Previous = m.(model.DockerStatsModel).Data
} }
dockerStats.Data = data dockerStats.Data = data
dockerStats.Icon = v.Labels["icon"] dockerStats.Icon = v.Labels["icon"]
dockerStats.Title = strings.ReplaceAll(v.Names[0], "/", "") dockerStats.Title = strings.ReplaceAll(v.Names[0], "/", "")
dataStats.Store(v.ID, dockerStats)
// @tiger - 不建议直接把依赖的数据结构封装返回。
// 如果依赖的数据结构有变化,应该在这里适配或者保存,这样更加对客户端负责
temp.Store(v.ID, dockerStats)
if i == 99 { if i == 99 {
stats.Body.Close() stats.Body.Close()
} }
}(v, i) }(v, i)
} }
wg.Wait() wg.Wait()
dataStats = temp
isFinish = true isFinish = true
time.Sleep(time.Second * 3)
time.Sleep(time.Second * 1)
} }
isFinish = false isFinish = false
cancel() cancel()
} }
func NewAppService(db *gorm.DB, logger loger2.OLog) AppService { func NewAppService(db *gorm.DB) AppService {
return &appStruct{db: db, log: logger} return &appStruct{db: db}
} }

View File

@@ -4,28 +4,29 @@ import (
"encoding/json" "encoding/json"
json2 "encoding/json" json2 "encoding/json"
"fmt" "fmt"
"sort"
"strconv" "strconv"
"time"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper" httper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
model2 "github.com/IceWhaleTech/CasaOS/service/model" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/types" "github.com/pkg/errors"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"go.uber.org/zap"
) )
type CasaService interface { type CasaService interface {
GetServerList(index, size, tp, categoryId, key, language string) (recommend, list, community []model.ServerAppList) GetServerList(index, size, tp, categoryId, key string) (model.ServerAppListCollection, error)
GetServerCategoryList() []model.ServerCategoryList GetServerCategoryList() (list []model.CategoryList, err error)
GetTaskList(size int) []model2.TaskDBModel GetServerAppInfo(id, t string, language string) (model.ServerAppList, error)
GetServerAppInfo(id, t string, language string) model.ServerAppList
ShareAppFile(body []byte) string ShareAppFile(body []byte) string
PushHeart(id, t string, language string) GetCasaosVersion() model.Version
PushAppAnalyse(uuid, t string, name, language string) AsyncGetServerList() (collection model.ServerAppListCollection, err error)
PushConnectionStatus(uuid, err string, from, to, event string) AsyncGetServerCategoryList() ([]model.CategoryList, error)
PushUserInfo()
GetUserInfoByShareId(shareId string) model.UserInfo
GetPersonPublic() (list []model.FriendsModel)
} }
type casaService struct { type casaService struct {
@@ -40,63 +41,194 @@ func (o *casaService) ShareAppFile(body []byte) string {
return content return content
} }
func (o *casaService) GetTaskList(size int) []model2.TaskDBModel { func (o *casaService) GetServerList(index, size, tp, categoryId, key string) (model.ServerAppListCollection, error) {
head := make(map[string]string)
head["Authorization"] = GetToken()
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/task/list/"+strconv.Itoa(size), head)
list := []model2.TaskDBModel{}
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
return list
}
func (o *casaService) GetServerList(index, size, tp, categoryId, key, language string) (recommend, list, community []model.ServerAppList) {
keyName := fmt.Sprintf("list_%s_%s_%s_%s_%s", index, size, tp, categoryId, language)
keyName := fmt.Sprintf("list_%s_%s_%s_%s_%s", index, size, tp, categoryId, "en")
collection := model.ServerAppListCollection{}
if result, ok := Cache.Get(keyName); ok { if result, ok := Cache.Get(keyName); ok {
res, ok := result.(string) res, ok := result.(string)
if ok { if ok {
json2.Unmarshal([]byte(gjson.Get(res, "data.list").String()), &list) json2.Unmarshal([]byte(res), &collection)
json2.Unmarshal([]byte(gjson.Get(res, "data.recommend").String()), &recommend) return collection, nil
json2.Unmarshal([]byte(gjson.Get(res, "data.community").String()), &community)
return
} }
} }
collectionStr := file.ReadFullFile(config.AppInfo.DBPath + "/app_list.json")
err := json2.Unmarshal(collectionStr, &collection)
if err != nil {
loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(collectionStr)))
collection, err = o.AsyncGetServerList()
if err != nil {
return collection, err
}
}
go o.AsyncGetServerList()
if categoryId != "0" {
categoryInt, _ := strconv.Atoi(categoryId)
nList := []model.ServerAppList{}
for _, v := range collection.List {
if v.CategoryId == categoryInt {
nList = append(nList, v)
}
}
collection.List = nList
nCommunity := []model.ServerAppList{}
for _, v := range collection.Community {
if v.CategoryId == categoryInt {
nCommunity = append(nCommunity, v)
}
}
collection.Community = nCommunity
}
if tp != "name" {
if tp == "new" {
sort.Slice(collection.List, func(i, j int) bool {
return collection.List[i].CreatedAt.After(collection.List[j].CreatedAt)
})
sort.Slice(collection.Community, func(i, j int) bool {
return collection.Community[i].CreatedAt.After(collection.Community[j].CreatedAt)
})
} else if tp == "rank" {
sort.Slice(collection.List, func(i, j int) bool {
return collection.List[i].QueryCount > collection.List[j].QueryCount
})
sort.Slice(collection.Community, func(i, j int) bool {
return collection.Community[i].QueryCount > collection.Community[j].QueryCount
})
}
}
sizeInt, _ := strconv.Atoi(size)
if index != "1" {
indexInt, _ := strconv.Atoi(index)
collection.List = collection.List[(indexInt-1)*sizeInt : indexInt*sizeInt]
collection.Community = collection.Community[(indexInt-1)*sizeInt : indexInt*sizeInt]
} else {
if len(collection.List) > sizeInt {
collection.List = collection.List[:sizeInt]
}
if len(collection.Community) > sizeInt {
collection.Community = collection.Community[:sizeInt]
}
}
if len(collection.List) > 0 {
by, _ := json.Marshal(collection)
Cache.Set(keyName, string(by), time.Minute*10)
}
return collection, nil
}
func (o *casaService) AsyncGetServerList() (collection model.ServerAppListCollection, err error) {
results := file.ReadFullFile(config.AppInfo.DBPath + "/app_list.json")
err = json2.Unmarshal(results, &collection)
if err != nil {
loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
}
if collection.Version == o.GetCasaosVersion().Version {
return collection, err
}
head := make(map[string]string) head := make(map[string]string)
head["Authorization"] = GetToken() head["Authorization"] = GetToken()
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/newlist?index="+index+"&size="+size+"&rank="+tp+"&category_id="+categoryId+"&key="+key+"&language="+language, head) listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/newlist?index=1&size=1000&rank=name&category_id=0&key=&language=en", head)
listModel := []model.ServerAppList{}
communityModel := []model.ServerAppList{}
recommendModel := []model.ServerAppList{}
json2.Unmarshal([]byte(gjson.Get(listS, "data.list").String()), &listModel)
json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommendModel)
json2.Unmarshal([]byte(gjson.Get(listS, "data.community").String()), &communityModel)
json2.Unmarshal([]byte(gjson.Get(listS, "data.list").String()), &list) if len(listModel) > 0 {
json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommend) collection.Community = communityModel
json2.Unmarshal([]byte(gjson.Get(listS, "data.community").String()), &community) collection.List = listModel
collection.Recommend = recommendModel
if len(list) > 0 { collection.Version = o.GetCasaosVersion().Version
Cache.SetDefault(keyName, listS) by, err := json.Marshal(collection)
if err != nil {
loger.Error("marshal error", zap.Any("err", err))
}
file.WriteToPath(by, config.AppInfo.DBPath, "app_list.json")
} }
return return
} }
func (o *casaService) GetServerCategoryList() []model.ServerCategoryList { // func (o *casaService) GetServerCategoryList() (list []model.ServerCategoryList) {
// keyName := fmt.Sprintf("category_list")
// if result, ok := Cache.Get(keyName); ok {
// res, ok := result.(string)
// if ok {
// json2.Unmarshal([]byte(gjson.Get(res, "data").String()), &list)
// return list
// }
// }
// head := make(map[string]string)
// head["Authorization"] = GetToken()
// listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head)
// json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
// if len(list) > 0 {
// Cache.Set(keyName, listS, time.Hour*24)
// }
// return list
// }
func (o *casaService) GetServerCategoryList() (list []model.CategoryList, err error) {
category := model.ServerCategoryList{}
results := file.ReadFullFile(config.AppInfo.DBPath + "/app_category.json")
err = json2.Unmarshal(results, &category)
if err != nil {
loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
return o.AsyncGetServerCategoryList()
}
go o.AsyncGetServerCategoryList()
return category.Item, err
}
func (o *casaService) AsyncGetServerCategoryList() ([]model.CategoryList, error) {
list := model.ServerCategoryList{}
results := file.ReadFullFile(config.AppInfo.DBPath + "/app_category.json")
err := json2.Unmarshal(results, &list)
if err != nil {
loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
} else {
if list.Version == o.GetCasaosVersion().Version {
return list.Item, nil
}
}
item := []model.CategoryList{}
head := make(map[string]string) head := make(map[string]string)
head["Authorization"] = GetToken() head["Authorization"] = GetToken()
listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head) listS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/category", head)
if len(listS) == 0 {
list := []model.ServerCategoryList{} return item, errors.New("server error")
}
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list) json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &item)
if len(item) > 0 {
return list list.Version = o.GetCasaosVersion().Version
list.Item = item
by, err := json.Marshal(list)
if err != nil {
loger.Error("marshal error", zap.Any("err", err))
}
file.WriteToPath(by, config.AppInfo.DBPath, "app_category.json")
}
return item, nil
} }
func (o *casaService) GetServerAppInfo(id, t string, language string) model.ServerAppList {
func (o *casaService) GetServerAppInfo(id, t string, language string) (model.ServerAppList, error) {
head := make(map[string]string) head := make(map[string]string)
@@ -104,9 +236,12 @@ func (o *casaService) GetServerAppInfo(id, t string, language string) model.Serv
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/info/"+id+"?t="+t+"&language="+language, head) infoS := httper2.Get(config.ServerInfo.ServerApi+"/v2/app/info/"+id+"?t="+t+"&language="+language, head)
info := model.ServerAppList{} info := model.ServerAppList{}
if infoS == "" {
return info, errors.New("server error")
}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info) json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
return info return info, nil
} }
func GetToken() string { func GetToken() string {
t := make(chan string) t := make(chan string)
@@ -130,106 +265,34 @@ func GetToken() string {
return auth return auth
} }
func (o *casaService) PushHeart(id, t string, language string) { /**
* @description: get remote version
* @return {model.Version}
*/
func (o *casaService) GetCasaosVersion() model.Version {
keyName := "casa_version"
var dataStr string
var version model.Version
if result, ok := Cache.Get(keyName); ok {
dataStr, ok = result.(string)
if ok {
data := gjson.Get(dataStr, "data")
json2.Unmarshal([]byte(data.String()), &version)
return version
}
}
m := model.CasaOSHeart{} v := httper.OasisGet(config.ServerInfo.ServerApi + "/v1/sys/version")
m.UuId = id data := gjson.Get(v, "data")
m.Type = t json2.Unmarshal([]byte(data.String()), &version)
b, _ := json.Marshal(m)
head := make(map[string]string) if len(version.Version) > 0 {
Cache.Set(keyName, v, time.Minute*20)
head["Authorization"] = GetToken() }
infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/analyse/heart", b, "application/json", head)
info := model.ServerAppList{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
return version
} }
func (o *casaService) PushAppAnalyse(uuid, t string, name, language string) {
m := model.AppAnalyse{}
m.UUId = uuid
m.Type = t
m.Name = name
m.Language = language
m.Version = types.CURRENTVERSION
b, _ := json.Marshal(m)
head := make(map[string]string)
head["Authorization"] = GetToken()
infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/analyse/app", b, "application/json", head)
info := model.ServerAppList{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
}
func (o *casaService) PushConnectionStatus(uuid, err string, from, to, event string) {
m := model.ConnectionStatus{}
m.UUId = uuid
m.Error = err
m.From = from
m.To = to
m.Event = event
b, _ := json.Marshal(m)
head := make(map[string]string)
head["Authorization"] = GetToken()
infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/analyse/connect", b, "application/json", head)
info := model.ServerAppList{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
}
func (o *casaService) PushUserInfo() {
m := model.UserInfo{}
m.Desc = config.UserInfo.Description
m.Avatar = config.UserInfo.Avatar
m.NickName = config.UserInfo.NickName
m.ShareId = config.ServerInfo.Token
b, _ := json.Marshal(m)
head := make(map[string]string)
head["Authorization"] = GetToken()
infoS := httper2.Post(config.ServerInfo.ServerApi+"/v1/user/info", b, "application/json", head)
info := model.ServerAppList{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
}
func (o *casaService) GetUserInfoByShareId(shareId string) model.UserInfo {
head := make(map[string]string)
head["Authorization"] = GetToken()
infoS := httper2.Get(config.ServerInfo.ServerApi+"/v1/user/info/"+shareId, head)
info := model.UserInfo{}
json2.Unmarshal([]byte(gjson.Get(infoS, "data").String()), &info)
return info
}
func (o *casaService) GetPersonPublic() (list []model.FriendsModel) {
head := make(map[string]string)
head["Authorization"] = GetToken()
listS := httper2.Get(config.ServerInfo.ServerApi+"/v1/person/public", head)
json2.Unmarshal([]byte(gjson.Get(listS, "data").String()), &list)
return list
}
func NewCasaService() CasaService { func NewCasaService() CasaService {
return &casaService{} return &casaService{}
} }

View File

@@ -1,118 +0,0 @@
package service
import (
"os/exec"
ip_helper2 "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"github.com/IceWhaleTech/CasaOS/service/ddns"
"github.com/IceWhaleTech/CasaOS/service/model"
"gorm.io/gorm"
)
type ddnsStruct struct {
db *gorm.DB
log loger2.OLog
}
type DDNSService interface {
IsExis(t int, domain string, host string) bool
GetExternalIP() (string, string)
GetConfigList() *[]model.DDNSList
DeleteConfig(id uint) bool
GetType(name string) (uint, string)
SaveConfig(model model.DDNSUpdateDBModel) error
}
//判断当前添加的是否存在
func (d *ddnsStruct) IsExis(t int, domain string, host string) bool {
var count int64
d.db.Table(model.DDNSLISTTABLENAME).Where("type=? AND domain=? AND host=?", t, domain, host).Count(&count)
return count > 0
}
//前台获取已配置的ddns列表
func (d *ddnsStruct) GetConfigList() *[]model.DDNSList {
var s []model.DDNSList
d.db.Table(model.DDNSLISTTABLENAME).Select("o_ddns_type.name as name,o_ddns.id,host,domain,created_at,updated_at,message,state").Joins("left join o_ddns_type on o_ddns.type=o_ddns_type.id").Scan(&s)
return &s
}
func (d *ddnsStruct) DeleteConfig(id uint) bool {
d.db.Delete(&model.DDNSUpdateDBModel{Id: id})
return true
}
func (d *ddnsStruct) GetExternalIP() (string, string) {
ipv4 := make(chan string)
ipv6 := make(chan string)
go func() { ipv4 <- ip_helper2.GetExternalIPV4() }()
go func() { ipv6 <- ip_helper2.GetExternalIPV6() }()
return <-ipv4, <-ipv6
}
func NewDDNSService(db *gorm.DB, log loger2.OLog) DDNSService {
return &ddnsStruct{db, log}
}
//根据名称获取类型
func (d *ddnsStruct) GetType(name string) (uint, string) {
var result model.DDNSTypeDBModel
d.db.Model(&model.DDNSTypeDBModel{}).Where("name = ?", name).First(&result)
return result.Id, result.Name
}
//保存配置到数据库
func (d *ddnsStruct) GetDockerRootDir(model model.DDNSUpdateDBModel) error {
return d.db.Create(&model).Error
}
//保存配置到数据库
func (d *ddnsStruct) SaveConfig(model model.DDNSUpdateDBModel) error {
return d.db.Create(&model).Error
}
//更新数据库ping状态
func chackPing(b chan bool, url string) {
cmd := exec.Command("ping", url, "-c", "1", "-W", "5")
err := cmd.Run()
if err != nil {
b <- false
} else {
b <- true
}
}
//更新列表
func UpdateDDNSList(db *gorm.DB) {
var s []model.DDNSCoreList
db.Table(model.DDNSLISTTABLENAME).Select("o_ddns_type.name as name,o_ddns_type.api_host as api_host,o_ddns.id,`host`,domain,user_name,`password`,`key`,secret,type").Joins("left join o_ddns_type on o_ddns.type=o_ddns_type.id").Scan(&s)
for _, item := range s {
var msg string
switch item.Type {
case 1:
var godaddy = &ddns.GoDaddy{
Host: item.Host,
Key: item.Key,
Secret: item.Secret,
Domain: item.Domain,
IPV4: ip_helper2.GetExternalIPV4(),
IPV6: ip_helper2.GetExternalIPV6(),
ApiHost: item.ApiHost,
}
msg = godaddy.Update()
}
b := make(chan bool)
//获取ping状态
go chackPing(b, item.Host+"."+item.Domain)
item.State = <-b
item.Message = msg
db.Table(model.DDNSLISTTABLENAME).Model(&item).Select("state", "message").Updates(&item)
}
}

View File

@@ -1,33 +0,0 @@
package ddns
import (
"net/http"
)
func SetUserAgent(request *http.Request) {
request.Header.Set("User-Agent", "Oasis lauren.pan@icewhale.org")
}
func SetContentType(request *http.Request, contentType string) {
request.Header.Set("Content-Type", contentType)
}
func SetAccept(request *http.Request, acceptContent string) {
request.Header.Set("Accept", acceptContent)
}
func SetAuthBearer(request *http.Request, token string) {
request.Header.Set("Authorization", "Bearer "+token)
}
func SetAuthSSOKey(request *http.Request, key, secret string) {
request.Header.Set("Authorization", "sso-key "+key+":"+secret)
}
func SetOauth(request *http.Request, value string) {
request.Header.Set("oauth", value)
}
func SetXFilter(request *http.Request, value string) {
request.Header.Set("X-Filter", value)
}

View File

@@ -1,87 +0,0 @@
package ddns
import (
"bytes"
"context"
"fmt"
"github.com/IceWhaleTech/CasaOS/pkg/ddns"
"github.com/tidwall/gjson"
"io/ioutil"
"net/http"
"time"
)
type GoDaddyService interface {
Update(ctx context.Context, client *http.Client)
}
type GoDaddy struct {
Host string `json:"host"`
Key string `json:"key"`
Secret string `json:"secret"`
Domain string `json:"domain"`
IPV4 string `json:"ipv_4"`
IPV6 string `json:"ipv_6"`
ApiHost string `json:"api_host"`
}
func (g *GoDaddy) Update() string {
client := &http.Client{Timeout: 30 * time.Second}
recordType := ddns.A
buffer1 := bytes.NewBuffer(nil)
buffer1.WriteString(`[{"data":"`)
buffer1.WriteString(g.IPV4)
buffer1.WriteString(`"}]`)
request, err := http.NewRequest(http.MethodPut, fmt.Sprintf("%s/v1/domains/%s/records/%s/%s", g.ApiHost, g.Domain, recordType, g.Host), buffer1)
if err != nil {
return err.Error()
}
g.setHead(request)
response, err := client.Do(request)
if err != nil {
return err.Error()
}
defer response.Body.Close()
b, err := ioutil.ReadAll(response.Body)
if err != nil {
return err.Error()
}
defer response.Body.Close()
if len(b) > 0 {
r := gjson.GetBytes(b, "message")
return r.String()
}
if len(g.IPV6) > 0 {
recordType = ddns.AAAA
buffer1 := bytes.NewBuffer(nil)
buffer1.WriteString(`[{"data":"`)
buffer1.WriteString(g.IPV6)
buffer1.WriteString(`"}]`)
request6, err := http.NewRequest(http.MethodPut, fmt.Sprintf("%s/v1/domains/%s/records/%s/%s", ddns.GODADDYAPIURL, g.Domain, recordType, g.Host), buffer1)
if err != nil {
return err.Error()
}
g.setHead(request6)
response6, err := client.Do(request6)
if err != nil {
return err.Error()
}
defer response6.Body.Close()
d, err := ioutil.ReadAll(response6.Body)
if err != nil {
return err.Error()
}
if len(d) > 0 {
r := gjson.GetBytes(d, "message")
return r.String()
}
}
return ""
}
func (g *GoDaddy) setHead(request *http.Request) {
SetUserAgent(request)
SetAuthSSOKey(request, g.Key, g.Secret)
SetContentType(request, "application/json")
SetAccept(request, "application/json")
}

View File

@@ -1,15 +0,0 @@
package ddns
import (
"testing"
)
func TestSetConfig(t *testing.T) {
var model GoDaddy
model.IPV4 = "180.164.179.198"
model.Domain = "link-liang.xyz"
model.Secret = "secret"
model.Key = "key"
//model.Type=ddns.GOGADDY
//model.SetConfig()
}

View File

@@ -11,10 +11,11 @@ import (
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command" command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/shirou/gopsutil/v3/disk" "github.com/shirou/gopsutil/v3/disk"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"go.uber.org/zap"
"gorm.io/gorm" "gorm.io/gorm"
) )
@@ -37,8 +38,7 @@ type DiskService interface {
RemoveLSBLKCache() RemoveLSBLKCache()
} }
type diskService struct { type diskService struct {
log loger2.OLog db *gorm.DB
db *gorm.DB
} }
func (d *diskService) RemoveLSBLKCache() { func (d *diskService) RemoveLSBLKCache() {
@@ -58,47 +58,47 @@ func (d *diskService) SmartCTL(path string) model.SmartctlA {
var m model.SmartctlA var m model.SmartctlA
str := command2.ExecSmartCTLByPath(path) str := command2.ExecSmartCTLByPath(path)
if str == nil { if str == nil {
d.log.Error("smartctl exec error,smartctl") loger.Error("failed to exec shell ", zap.Any("err", "smartctl exec error"))
return m return m
} }
err := json2.Unmarshal([]byte(str), &m) err := json2.Unmarshal([]byte(str), &m)
if err != nil { if err != nil {
d.log.Error("json ummarshal error", err) loger.Error("Failed to unmarshal json", zap.Any("err", err))
} }
if !reflect.DeepEqual(m, model.SmartctlA{}) { if !reflect.DeepEqual(m, model.SmartctlA{}) {
Cache.Add(key, m, time.Second*10) Cache.Add(key, m, time.Hour*24)
} }
return m return m
} }
//通过脚本获取外挂磁盘 //通过脚本获取外挂磁盘
func (d *diskService) GetPlugInDisk() []string { func (d *diskService) GetPlugInDisk() []string {
return command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPlugInDisk") return command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPlugInDisk")
} }
//格式化硬盘 //格式化硬盘
func (d *diskService) FormatDisk(path, format string) []string { func (d *diskService) FormatDisk(path, format string) []string {
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;FormatDisk " + path + " " + format) r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;FormatDisk " + path + " " + format)
return r return r
} }
//移除挂载点,删除目录 //移除挂载点,删除目录
func (d *diskService) UmountPointAndRemoveDir(path string) []string { func (d *diskService) UmountPointAndRemoveDir(path string) []string {
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;UMountPorintAndRemoveDir " + path) r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;UMountPorintAndRemoveDir " + path)
return r return r
} }
//删除分区 //删除分区
func (d *diskService) DelPartition(path, num string) string { func (d *diskService) DelPartition(path, num string) string {
r := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;DelPartition " + path + " " + num) r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;DelPartition " + path + " " + num)
fmt.Println(r) fmt.Println(r)
return "" return ""
} }
//part //part
func (d *diskService) AddPartition(path string) string { func (d *diskService) AddPartition(path string) string {
command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;AddPartition " + path) command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;AddPartition " + path)
return "" return ""
} }
@@ -133,47 +133,13 @@ func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
str := command2.ExecLSBLK() str := command2.ExecLSBLK()
if str == nil { if str == nil {
d.log.Error("lsblk exec error,lsblk") loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error"))
return nil return nil
} }
var m []model.LSBLKModel var m []model.LSBLKModel
// strStr := `{
// "blockdevices": [
// {"name":"loop0", "kname":"loop0", "path":"/dev/loop0", "maj:min":"7:0", "fsavail":"0", "fssize":"62M", "fstype":"squashfs", "fsused":"62M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/core20/1405", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":619, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop1", "kname":"loop1", "path":"/dev/loop1", "maj:min":"7:1", "fsavail":"0", "fssize":"55.6M", "fstype":"squashfs", "fsused":"55.6M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/core18/2344", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":55, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop2", "kname":"loop2", "path":"/dev/loop2", "maj:min":"7:2", "fsavail":"0", "fssize":"44.8M", "fstype":"squashfs", "fsused":"44.8M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/snapd/15314", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":446, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop3", "kname":"loop3", "path":"/dev/loop3", "maj:min":"7:3", "fsavail":"0", "fssize":"78.9M", "fstype":"squashfs", "fsused":"78.9M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/lxd/22754", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":788, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop4", "kname":"loop4", "path":"/dev/loop4", "maj:min":"7:4", "fsavail":"0", "fssize":"43.8M", "fstype":"squashfs", "fsused":"43.8M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/snapd/15177", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":436, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop5", "kname":"loop5", "path":"/dev/loop5", "maj:min":"7:5", "fsavail":"0", "fssize":"55.5M", "fstype":"squashfs", "fsused":"55.5M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/core18/1997", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":554, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"loop6", "kname":"loop6", "path":"/dev/loop6", "maj:min":"7:6", "fsavail":"0", "fssize":"80M", "fstype":"squashfs", "fsused":"80M", "fsuse%":"100%", "fsver":"4.0", "mountpoint":"/snap/lxd/22826", "label":null, "uuid":null, "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":true, "rm":false, "hotplug":false, "model":null, "serial":null, "size":799, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"mq-deadline", "rq-size":256, "type":"loop", "disc-aln":0, "disc-gran":"4K", "disc-max":"4G", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":null, "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"sda", "kname":"sda", "path":"/dev/sda", "maj:min":"8:0", "fsavail":null, "fssize":null, "fstype":null, "fsused":null, "fsuse%":null, "fsver":null, "mountpoint":null, "label":null, "uuid":null, "ptuuid":"1596101a-e20d-4296-96e2-0870efce554a", "pttype":"gpt", "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":"ST1000DM003-1ER1", "serial":"Z4YCS1B6", "size":9315, "state":"running", "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":4096, "opt-io":0, "phy-sec":4096, "log-sec":512, "rota":true, "sched":"mq-deadline", "rq-size":64, "type":"disk", "disc-aln":0, "disc-gran":"0B", "disc-max":"0B", "disc-zero":false, "wsame":"0B", "wwn":"0x5000c50090db103a", "rand":true, "pkname":null, "hctl":"0:0:0:0", "tran":"sata", "subsystems":"block:scsi:pci", "rev":"CC61", "vendor":"ATA ", "zoned":"none", "dax":false,
// "children": [
// {"name":"sda1", "kname":"sda1", "path":"/dev/sda1", "maj:min":"8:1", "fsavail":null, "fssize":null, "fstype":null, "fsused":null, "fsuse%":null, "fsver":null, "mountpoint":null, "label":null, "uuid":null, "ptuuid":"1596101a-e20d-4296-96e2-0870efce554a", "pttype":"gpt", "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":9315, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":3072, "min-io":4096, "opt-io":0, "phy-sec":4096, "log-sec":512, "rota":true, "sched":"mq-deadline", "rq-size":64, "type":"part", "disc-aln":0, "disc-gran":"0B", "disc-max":"0B", "disc-zero":false, "wsame":"0B", "wwn":"0x5000c50090db103a", "rand":true, "pkname":"sda", "hctl":null, "tran":null, "subsystems":"block:scsi:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false}
// ]
// },
// {"name":"sdb", "kname":"sdb", "path":"/dev/sdb", "maj:min":"8:16", "fsavail":null, "fssize":null, "fstype":null, "fsused":null, "fsuse%":null, "fsver":null, "mountpoint":null, "label":null, "uuid":null, "ptuuid":"baed02d0-e92d-4a00-9609-f94f31271a0e", "pttype":"gpt", "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":"ST1000DM003-1ER1", "serial":"W4Y51MFH", "size":9315, "state":"running", "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":4096, "opt-io":0, "phy-sec":4096, "log-sec":512, "rota":true, "sched":"mq-deadline", "rq-size":64, "type":"disk", "disc-aln":0, "disc-gran":"0B", "disc-max":"0B", "disc-zero":false, "wsame":"0B", "wwn":"0x5000c5008acd2f00", "rand":true, "pkname":null, "hctl":"1:0:0:0", "tran":"sata", "subsystems":"block:scsi:pci", "rev":"CC46", "vendor":"ATA ", "zoned":"none", "dax":false,
// "children": [
// {"name":"sdb1", "kname":"sdb1", "path":"/dev/sdb1", "maj:min":"8:17", "fsavail":null, "fssize":null, "fstype":"zfs_member", "fsused":null, "fsuse%":null, "fsver":"5000", "mountpoint":null, "label":null, "uuid":null, "ptuuid":"baed02d0-e92d-4a00-9609-f94f31271a0e", "pttype":"gpt", "parttype":"0fc63daf-8483-4772-8e79-3d69d8477de4", "parttypename":"Linux filesystem", "partlabel":"primary", "partuuid":"57880cc0-2695-41c3-bf14-7161693e5bff", "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":9315, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":3072, "min-io":4096, "opt-io":0, "phy-sec":4096, "log-sec":512, "rota":true, "sched":"mq-deadline", "rq-size":64, "type":"part", "disc-aln":0, "disc-gran":"0B", "disc-max":"0B", "disc-zero":false, "wsame":"0B", "wwn":"0x5000c5008acd2f00", "rand":true, "pkname":"sdb", "hctl":null, "tran":null, "subsystems":"block:scsi:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false}
// ]
// },
// {"name":"nvme0n1", "kname":"nvme0n1", "path":"/dev/nvme0n1", "maj:min":"259:0", "fsavail":null, "fssize":null, "fstype":null, "fsused":null, "fsuse%":null, "fsver":null, "mountpoint":null, "label":null, "uuid":null, "ptuuid":"338abc31-a3d4-4af2-9342-b53268d9e5ac", "pttype":"gpt", "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":"LITEON CL1-8D128-HP", "serial":"UJDJA01PJDH3UI", "size":1192, "state":"live", "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"none", "rq-size":255, "type":"disk", "disc-aln":0, "disc-gran":"512B", "disc-max":"2T", "disc-zero":false, "wsame":"0B", "wwn":"eui.0023035630392fe7", "rand":false, "pkname":null, "hctl":null, "tran":"nvme", "subsystems":"block:nvme:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false,
// "children": [
// {"name":"nvme0n1p1", "kname":"nvme0n1p1", "path":"/dev/nvme0n1p1", "maj:min":"259:1", "fsavail":null, "fssize":null, "fstype":null, "fsused":null, "fsuse%":null, "fsver":null, "mountpoint":null, "label":null, "uuid":null, "ptuuid":"338abc31-a3d4-4af2-9342-b53268d9e5ac", "pttype":"gpt", "parttype":"21686148-6449-6e6f-744e-656564454649", "parttypename":"BIOS boot", "partlabel":null, "partuuid":"b2bac638-9468-449f-9669-79be44e3c80d", "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":1, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"none", "rq-size":255, "type":"part", "disc-aln":0, "disc-gran":"512B", "disc-max":"2T", "disc-zero":false, "wsame":"0B", "wwn":"eui.0023035630392fe7", "rand":false, "pkname":"nvme0n1", "hctl":null, "tran":"nvme", "subsystems":"block:nvme:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"nvme0n1p2", "kname":"nvme0n1p2", "path":"/dev/nvme0n1p2", "maj:min":"259:2", "fsavail":"1.2G", "fssize":"1.4G", "fstype":"ext4", "fsused":"131.5M", "fsuse%":"9%", "fsver":"1.0", "mountpoint":"/boot", "label":null, "uuid":"cd8164e9-bf7a-4684-8a3b-1d9f209b4930", "ptuuid":"338abc31-a3d4-4af2-9342-b53268d9e5ac", "pttype":"gpt", "parttype":"0fc63daf-8483-4772-8e79-3d69d8477de4", "parttypename":"Linux filesystem", "partlabel":null, "partuuid":"42ed9ed6-1221-4bea-901a-bc2f7b7cb9e1", "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":15, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"none", "rq-size":255, "type":"part", "disc-aln":0, "disc-gran":"512B", "disc-max":"2T", "disc-zero":false, "wsame":"0B", "wwn":"eui.0023035630392fe7", "rand":false, "pkname":"nvme0n1", "hctl":null, "tran":"nvme", "subsystems":"block:nvme:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false},
// {"name":"nvme0n1p3", "kname":"nvme0n1p3", "path":"/dev/nvme0n1p3", "maj:min":"259:3", "fsavail":null, "fssize":null, "fstype":"LVM2_member", "fsused":null, "fsuse%":null, "fsver":"LVM2 001", "mountpoint":null, "label":null, "uuid":"0G7ryL-p2Ks-i9HS-wvEO-lXHs-oyZX-1KIlZO", "ptuuid":"338abc31-a3d4-4af2-9342-b53268d9e5ac", "pttype":"gpt", "parttype":"0fc63daf-8483-4772-8e79-3d69d8477de4", "parttypename":"Linux filesystem", "partlabel":null, "partuuid":"f6ae2e8c-14ae-4d94-89f1-2c154e909843", "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":1177, "state":null, "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":"none", "rq-size":255, "type":"part", "disc-aln":0, "disc-gran":"512B", "disc-max":"2T", "disc-zero":false, "wsame":"0B", "wwn":"eui.0023035630392fe7", "rand":false, "pkname":"nvme0n1", "hctl":null, "tran":"nvme", "subsystems":"block:nvme:pci", "rev":null, "vendor":null, "zoned":"none", "dax":false,
// "children": [
// {"name":"ubuntu--vg-ubuntu--lv", "kname":"dm-0", "path":"/dev/mapper/ubuntu--vg-ubuntu--lv", "maj:min":"253:0", "fsavail":"78.6G", "fssize":"115.4G", "fstype":"ext4", "fsused":"30.9G", "fsuse%":"27%", "fsver":"1.0", "mountpoint":"/", "label":null, "uuid":"e8a9082f-3643-4820-a5e5-05817d7738c6", "ptuuid":null, "pttype":null, "parttype":null, "parttypename":null, "partlabel":null, "partuuid":null, "partflags":null, "ra":128, "ro":false, "rm":false, "hotplug":false, "model":null, "serial":null, "size":1177, "state":"running", "owner":"root", "group":"disk", "mode":"brw-rw----", "alignment":0, "min-io":512, "opt-io":0, "phy-sec":512, "log-sec":512, "rota":false, "sched":null, "rq-size":128, "type":"lvm", "disc-aln":0, "disc-gran":"512B", "disc-max":"2T", "disc-zero":false, "wsame":"0B", "wwn":null, "rand":false, "pkname":"nvme0n1p3", "hctl":null, "tran":null, "subsystems":"block", "rev":null, "vendor":null, "zoned":"none", "dax":false}
// ]
// }
// ]
// }
// ]
// }`
// fmt.Println(gjson.Get(strStr, "blockdevices").String())
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &m) err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &m)
if err != nil { if err != nil {
fmt.Println(err) loger.Error("Failed to unmarshal json", zap.Any("err", err))
d.log.Error("json ummarshal error", err)
} }
var c []model.LSBLKModel var c []model.LSBLKModel
@@ -186,7 +152,7 @@ func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
fsused = 0 fsused = 0
for _, child := range i.Children { for _, child := range i.Children {
if child.RM { if child.RM {
child.Health = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDiskHealthState " + child.Path)) child.Health = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskHealthState " + child.Path))
if strings.ToLower(strings.TrimSpace(child.State)) != "ok" { if strings.ToLower(strings.TrimSpace(child.State)) != "ok" {
health = false health = false
} }
@@ -197,7 +163,7 @@ func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
} }
c = append(c, child) c = append(c, child)
} }
i.Format = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDiskType " + i.Path)) //i.Format = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskType " + i.Path))
if health { if health {
i.Health = "OK" i.Health = "OK"
} }
@@ -206,7 +172,7 @@ func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
if fsused > 0 { if fsused > 0 {
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64) i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
if err != nil { if err != nil {
d.log.Fatal("diskservice_lsblk_fsused", err) loger.Error("Failed to parse float", zap.Any("err", err))
} }
} }
n = append(n, i) n = append(n, i)
@@ -224,15 +190,14 @@ func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
func (d *diskService) GetDiskInfo(path string) model.LSBLKModel { func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
str := command2.ExecLSBLKByPath(path) str := command2.ExecLSBLKByPath(path)
if str == nil { if str == nil {
d.log.Error("lsblk exec error,str") loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error"))
return model.LSBLKModel{} return model.LSBLKModel{}
} }
var ml []model.LSBLKModel var ml []model.LSBLKModel
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml) err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
if err != nil { if err != nil {
d.log.Info(string(str)) loger.Error("Failed to unmarshal json", zap.Any("err", err))
d.log.Error("json ummarshal error", err)
return model.LSBLKModel{} return model.LSBLKModel{}
} }
@@ -243,10 +208,9 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
return m return m
// 下面为计算是否可以继续分区的部分,暂时不需要 // 下面为计算是否可以继续分区的部分,暂时不需要
chiArr := make(map[string]string) chiArr := make(map[string]string)
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetPartitionSectors " + m.Path) chiList := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPartitionSectors " + m.Path)
if len(chiList) == 0 { if len(chiList) == 0 {
d.log.Error(m.Path, chiList) loger.Error("chiList length error", zap.Any("err", "chiList length error"))
d.log.Error("chiList length error")
} }
for i := 0; i < len(chiList); i++ { for i := 0; i < len(chiList); i++ {
tempArr := strings.Split(chiList[i], ",") tempArr := strings.Split(chiList[i], ",")
@@ -262,10 +226,10 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
} }
} }
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;GetDiskSizeAndSectors " + m.Path) diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskSizeAndSectors " + m.Path)
if len(diskEndSector) < 2 { if len(diskEndSector) < 2 {
d.log.Error("diskEndSector length error") loger.Error("diskEndSector length error", zap.Any("err", "diskEndSector length error"))
} }
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64) diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 { if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
@@ -278,7 +242,7 @@ func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
} }
func (d *diskService) MountDisk(path, volume string) { func (d *diskService) MountDisk(path, volume string) {
r := command2.ExecResultStr("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_mount " + path + " " + volume) r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
fmt.Print(r) fmt.Print(r)
} }
@@ -300,7 +264,7 @@ func (d *diskService) DeleteMountPoint(path, mountPoint string) {
d.db.Where("path = ? AND mount_point = ?", path, mountPoint).Delete(&model2.SerialDisk{}) d.db.Where("path = ? AND mount_point = ?", path, mountPoint).Delete(&model2.SerialDisk{})
command2.OnlyExec("source " + config.AppInfo.ProjectPath + "/shell/helper.sh ;do_umount " + path) command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;do_umount " + path)
} }
func (d *diskService) GetSerialAll() []model2.SerialDisk { func (d *diskService) GetSerialAll() []model2.SerialDisk {
@@ -309,6 +273,6 @@ func (d *diskService) GetSerialAll() []model2.SerialDisk {
return m return m
} }
func NewDiskService(log loger2.OLog, db *gorm.DB) DiskService { func NewDiskService(db *gorm.DB) DiskService {
return &diskService{log: log, db: db} return &diskService{db: db}
} }

View File

@@ -7,23 +7,22 @@ import (
"encoding/binary" "encoding/binary"
json2 "encoding/json" json2 "encoding/json"
"fmt" "fmt"
"reflect"
"syscall" "syscall"
model2 "github.com/IceWhaleTech/CasaOS/service/model" "github.com/IceWhaleTech/CasaOS/model/notify"
types2 "github.com/IceWhaleTech/CasaOS/types"
"github.com/containerd/containerd" "github.com/containerd/containerd"
"github.com/containerd/containerd/cio" "github.com/containerd/containerd/cio"
"github.com/containerd/containerd/namespaces" "github.com/containerd/containerd/namespaces"
"github.com/containerd/containerd/oci" "github.com/containerd/containerd/oci"
"github.com/pkg/errors" "github.com/pkg/errors"
"go.uber.org/zap"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/docker" "github.com/IceWhaleTech/CasaOS/pkg/docker"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command" command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper" "github.com/IceWhaleTech/CasaOS/pkg/utils/env_helper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger" "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
//"github.com/containerd/containerd/oci" //"github.com/containerd/containerd/oci"
"io" "io"
@@ -44,9 +43,9 @@ import (
) )
type DockerService interface { type DockerService interface {
DockerPullImage(imageName string, m model2.AppNotify) error DockerPullImage(imageName string, icon, name string) error
IsExistImage(imageName string) bool IsExistImage(imageName string) bool
DockerContainerCreate(imageName string, m model.CustomizationPostData, net string) (containerId string, err error) DockerContainerCreate(imageName string, m model.CustomizationPostData) (containerId string, err error)
DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error) DockerContainerCopyCreate(info *types.ContainerJSON) (containerId string, err error)
DockerContainerStart(name string) error DockerContainerStart(name string) error
DockerContainerStats(name string) (string, error) DockerContainerStats(name string) (string, error)
@@ -69,7 +68,6 @@ type DockerService interface {
type dockerService struct { type dockerService struct {
rootDir string rootDir string
log loger2.OLog
} }
func (ds *dockerService) DockerContainerList() []types.Container { func (ds *dockerService) DockerContainerList() []types.Container {
@@ -319,7 +317,7 @@ func (ds *dockerService) IsExistImage(imageName string) bool {
} }
//安装镜像 //安装镜像
func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) error { func (ds *dockerService) DockerPullImage(imageName string, icon, name string) error {
cli, err := client2.NewClientWithOpts(client2.FromEnv) cli, err := client2.NewClientWithOpts(client2.FromEnv)
if err != nil { if err != nil {
return err return err
@@ -334,7 +332,8 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
return err return err
} }
buf := make([]byte, 256) //io.Copy()
buf := make([]byte, 2048*4)
for { for {
n, err := out.Read(buf) n, err := out.Read(buf)
if err != nil { if err != nil {
@@ -343,11 +342,16 @@ func (ds *dockerService) DockerPullImage(imageName string, m model2.AppNotify) e
} }
break break
} }
if !reflect.DeepEqual(m, model2.AppNotify{}) { if len(icon) > 0 && len(name) > 0 {
m.Type = types2.NOTIFY_TYPE_INSTALL_LOG notify := notify.Application{}
m.State = 0 notify.Icon = icon
m.Message = string(buf[:n]) notify.Name = name
MyService.Notify().UpdateLog(m) notify.State = "PULLING"
notify.Type = "INSTALL"
notify.Finished = false
notify.Success = true
notify.Message = string(buf[:n])
MyService.Notify().SendInstallAppBySocket(notify)
} }
} }
@@ -372,9 +376,9 @@ func (ds *dockerService) DockerContainerCopyCreate(info *types.ContainerJSON) (c
//param mapPort 容器主端口映射到外部的端口 //param mapPort 容器主端口映射到外部的端口
//param tcp 容器其他tcp端口 //param tcp 容器其他tcp端口
//param udp 容器其他udp端口 //param udp 容器其他udp端口
func (ds *dockerService) DockerContainerCreate(imageName string, m model.CustomizationPostData, net string) (containerId string, err error) { func (ds *dockerService) DockerContainerCreate(imageName string, m model.CustomizationPostData) (containerId string, err error) {
if len(net) == 0 { if len(m.NetworkModel) == 0 {
net = "bridge" m.NetworkModel = "bridge"
} }
cli, err := client2.NewClientWithOpts(client2.FromEnv) cli, err := client2.NewClientWithOpts(client2.FromEnv)
@@ -398,7 +402,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
tContainer, _ := strconv.Atoi(portMap.ContainerPort) tContainer, _ := strconv.Atoi(portMap.ContainerPort)
if tContainer > 0 { if tContainer > 0 {
ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{} ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
if net != "host" { if m.NetworkModel != "host" {
portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}} portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
} }
} }
@@ -407,7 +411,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
tContainer, _ := strconv.Atoi(portMap.ContainerPort) tContainer, _ := strconv.Atoi(portMap.ContainerPort)
if tContainer > 0 { if tContainer > 0 {
ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{} ports[nat.Port(portMap.ContainerPort+"/tcp")] = struct{}{}
if net != "host" { if m.NetworkModel != "host" {
portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}} portMaps[nat.Port(portMap.ContainerPort+"/tcp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
} }
} }
@@ -415,7 +419,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
uContainer, _ := strconv.Atoi(portMap.ContainerPort) uContainer, _ := strconv.Atoi(portMap.ContainerPort)
if uContainer > 0 { if uContainer > 0 {
ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{} ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
if net != "host" { if m.NetworkModel != "host" {
portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}} portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
} }
} }
@@ -424,7 +428,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
uContainer, _ := strconv.Atoi(portMap.ContainerPort) uContainer, _ := strconv.Atoi(portMap.ContainerPort)
if uContainer > 0 { if uContainer > 0 {
ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{} ports[nat.Port(portMap.ContainerPort+"/udp")] = struct{}{}
if net != "host" { if m.NetworkModel != "host" {
portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}} portMaps[nat.Port(portMap.ContainerPort+"/udp")] = []nat.PortBinding{{HostPort: portMap.CommendPort}}
} }
} }
@@ -433,7 +437,10 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
} }
var envArr []string var envArr []string
var showENV []string
showENV = append(showENV, "casaos")
for _, e := range m.Envs { for _, e := range m.Envs {
showENV = append(showENV, e.Name)
if strings.HasPrefix(e.Value, "$") { if strings.HasPrefix(e.Value, "$") {
envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value, MyService.System().GetTimeZone())) envArr = append(envArr, e.Name+"="+env_helper.ReplaceDefaultENV(e.Value, MyService.System().GetTimeZone()))
continue continue
@@ -476,7 +483,7 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
//if len(result1) == 0 { //if len(result1) == 0 {
err = file.IsNotExistMkDir(path) err = file.IsNotExistMkDir(path)
if err != nil { if err != nil {
ds.log.Error("mkdir error", err) loger.Error("Failed to create a folder", zap.Any("err", err))
continue continue
} }
//} //}
@@ -530,8 +537,11 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
config.Labels["desc"] = m.Description config.Labels["desc"] = m.Description
config.Labels["index"] = m.Index config.Labels["index"] = m.Index
config.Labels["custom_id"] = m.CustomId config.Labels["custom_id"] = m.CustomId
//config.Labels["order"] = strconv.Itoa(MyService.App().GetCasaOSCount() + 1) config.Labels["show_env"] = strings.Join(showENV, ",")
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(net), Privileged: m.Privileged, CapAdd: m.CapAdd} config.Labels["protocol"] = m.Protocol
config.Labels["host"] = m.Host
config.Labels["name"] = m.Label
hostConfig := &container.HostConfig{Resources: res, Mounts: volumes, RestartPolicy: rp, NetworkMode: container.NetworkMode(m.NetworkModel), Privileged: m.Privileged, CapAdd: m.CapAdd}
//if net != "host" { //if net != "host" {
config.ExposedPorts = ports config.ExposedPorts = ports
hostConfig.PortBindings = portMaps hostConfig.PortBindings = portMaps
@@ -540,9 +550,9 @@ func (ds *dockerService) DockerContainerCreate(imageName string, m model.Customi
containerDb, err := cli.ContainerCreate(context.Background(), containerDb, err := cli.ContainerCreate(context.Background(),
config, config,
hostConfig, hostConfig,
&network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{net: {NetworkID: "", Aliases: []string{}}}}, &network.NetworkingConfig{EndpointsConfig: map[string]*network.EndpointSettings{m.NetworkModel: {NetworkID: "", Aliases: []string{}}}},
nil, nil,
m.Label) m.ContainerName)
if err != nil { if err != nil {
return "", err return "", err
} }
@@ -827,8 +837,8 @@ func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{}) networks, _ := cli.NetworkList(context.Background(), types.NetworkListOptions{})
return networks return networks
} }
func NewDockerService(log loger2.OLog) DockerService { func NewDockerService() DockerService {
return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`), log: log} return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`)}
} }
// ---------------------------------------test------------------------------------ // ---------------------------------------test------------------------------------

View File

@@ -1,33 +0,0 @@
package service
import (
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"gorm.io/gorm"
)
type DownRecordService interface {
AddDownRecord(m model2.PersonDownRecordDBModel)
GetDownloadListByFrom(id string) []model2.PersonDownRecordDBModel
GetDownloadListByPath(path string) (list []model2.PersonDownRecordDBModel)
}
type downRecordService struct {
db *gorm.DB
}
func (d *downRecordService) AddDownRecord(m model2.PersonDownRecordDBModel) {
d.db.Create(&m)
}
func (d *downRecordService) GetDownloadListByFrom(id string) []model2.PersonDownRecordDBModel {
var m []model2.PersonDownRecordDBModel
d.db.Model(m).Where("from = ?", id).Find(&m)
return m
}
func (d *downRecordService) GetDownloadListByPath(path string) (list []model2.PersonDownRecordDBModel) {
d.db.Where("path = ?", path).Find(&list)
return
}
func NewDownRecordService(db *gorm.DB) DownRecordService {
return &downRecordService{db: db}
}

View File

@@ -1,66 +0,0 @@
package service
import (
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"gorm.io/gorm"
)
type DownloadService interface {
AddDownloadTask(m model2.PersonDownloadDBModel) //添加下载任务
EditDownloadState(m model2.PersonDownloadDBModel) //只修改状态
SaveDownload(m model2.PersonDownloadDBModel)
DelDownload(uuid string)
GetDownloadById(uuid string) model2.PersonDownloadDBModel
GetDownloadListByState(state string, t int) []model2.PersonDownloadDBModel
SetDownloadError(m model2.PersonDownloadDBModel)
GetDownloadListByPath(m model2.PersonDownloadDBModel) int
}
type downloadService struct {
db *gorm.DB
}
func (d *downloadService) GetDownloadListByPath(m model2.PersonDownloadDBModel) int {
var list []model2.PersonDownloadDBModel
d.db.Select("path").Where("path = ? AND `from` = ? AND state = 0", m.Path, m.From).Find(&list)
return len(list)
}
func (d *downloadService) AddDownloadTask(m model2.PersonDownloadDBModel) {
d.db.Create(&m)
}
func (d *downloadService) EditDownloadState(m model2.PersonDownloadDBModel) {
d.db.Model(&m).Where("uuid = ?", m.UUID).Update("state", m.State)
}
//failed during download
func (d *downloadService) SetDownloadError(m model2.PersonDownloadDBModel) {
d.db.Model(&m).Updates(m)
}
func (d *downloadService) DelDownload(uuid string) {
var m model2.PersonDownloadDBModel
d.db.Where("uuid = ?", uuid).Delete(&m)
}
func (d *downloadService) GetDownloadById(uuid string) model2.PersonDownloadDBModel {
var m model2.PersonDownloadDBModel
d.db.Model(m).Where("uuid = ?", uuid).First(&m)
return m
}
func (d *downloadService) GetDownloadListByState(state string, t int) (list []model2.PersonDownloadDBModel) {
if len(state) == 0 {
d.db.Where("type = ?", t).Find(&list)
} else {
d.db.Where("state = ? AND type= ?", state, t).Find(&list)
}
return
}
func (d *downloadService) SaveDownload(m model2.PersonDownloadDBModel) {
d.db.Save(&m)
}
func NewDownloadService(db *gorm.DB) DownloadService {
return &downloadService{db: db}
}

View File

@@ -1,38 +1,33 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2021-12-20 14:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-04 16:18:23
* @FilePath: /CasaOS/service/file.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package service package service
import ( import (
"context" "context"
"io" "io"
"os"
"path/filepath"
"strings"
"sync"
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
"go.uber.org/zap"
) )
// type InteruptReader struct { var FileQueue sync.Map
// r io.Reader
// interupt chan int
// }
// func NewInteruptReader(r io.Reader) InteruptReader { var OpStrArr []string
// return InteruptReader{
// r,
// make(chan int),
// }
// }
// func (r InteruptReader) Read(p []byte) (n int, err error) {
// if r.r == nil {
// return 0, io.EOF
// }
// select {
// case <-r.interupt:
// return r.r.Read(p)
// default:
// r.r = nil
// return 0, io.EOF
// }
// }
// func (r InteruptReader) Cancel() {
// r.interupt <- 0
// }
type reader struct { type reader struct {
ctx context.Context ctx context.Context
@@ -83,3 +78,99 @@ func (w *writer) Write(p []byte) (n int, err error) {
return w.w.Write(p) return w.w.Write(p)
} }
} }
func FileOperate(k string) {
list, ok := FileQueue.Load(k)
if !ok {
return
}
temp := list.(model.FileOperate)
if temp.ProcessedSize > 0 {
return
}
for i := 0; i < len(temp.Item); i++ {
v := temp.Item[i]
if temp.Type == "move" {
lastPath := v.From[strings.LastIndex(v.From, "/")+1:]
if !file.CheckNotExist(temp.To + "/" + lastPath) {
if temp.Style == "skip" {
temp.Item[i].Finished = true
continue
} else {
os.RemoveAll(temp.To + "/" + lastPath)
}
}
err := os.Rename(v.From, temp.To+"/"+lastPath)
if err != nil {
loger.Error("file move error", zap.Any("err", err))
err = file.MoveFile(v.From, temp.To+"/"+lastPath)
if err != nil {
loger.Error("MoveFile error", zap.Any("err", err))
continue
}
}
} else if temp.Type == "copy" {
err := file.CopyDir(v.From, temp.To, temp.Style)
if err != nil {
continue
}
} else {
continue
}
}
temp.Finished = true
FileQueue.Store(k, temp)
}
func ExecOpFile() {
len := len(OpStrArr)
if len == 0 {
return
}
if len > 1 {
len = 1
}
for i := 0; i < len; i++ {
go FileOperate(OpStrArr[i])
}
}
// file move or copy and send notify
func CheckFileStatus() {
for {
if len(OpStrArr) == 0 {
return
}
for _, v := range OpStrArr {
var total int64 = 0
item, ok := FileQueue.Load(v)
if !ok {
continue
}
temp := item.(model.FileOperate)
for i := 0; i < len(temp.Item); i++ {
if !temp.Item[i].Finished {
size, err := file.GetFileOrDirSize(temp.To + "/" + filepath.Base(temp.Item[i].From))
if err != nil {
continue
}
temp.Item[i].ProcessedSize = size
if size == temp.Item[i].Size {
temp.Item[i].Finished = true
}
total += size
} else {
total += temp.Item[i].ProcessedSize
}
}
temp.ProcessedSize = total
FileQueue.Store(v, temp)
}
time.Sleep(time.Second * 3)
}
}

View File

@@ -1,155 +0,0 @@
package service
import (
"context"
"fmt"
"net"
"reflect"
"strconv"
"time"
"github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/quic_helper"
model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/IceWhaleTech/CasaOS/types"
"github.com/lucas-clemente/quic-go"
uuid "github.com/satori/go.uuid"
"gorm.io/gorm"
)
type FriendService interface {
AddFriend(m model2.FriendModel)
DeleteFriend(m model2.FriendModel)
EditFriendMark(m model2.FriendModel)
EditFriendWrite(m model2.FriendModel)
EditFriendBlock(m model2.FriendModel)
GetFriendById(m model2.FriendModel) model2.FriendModel
GetFriendList() (list []model2.FriendModel)
GetFriendListRemote() (list []model2.FriendModel)
UpdateAddFriendType(m model2.FriendModel)
AgreeFrined(id string)
GetFriendByToken(token string) model2.FriendModel
UpdateOrCreate(m model2.FriendModel)
InternalInspection(ips []string, token string)
}
type friendService struct {
db *gorm.DB
}
func (p *friendService) AgreeFrined(id string) {
var m model2.FriendModel
p.db.Model(&m).Where("token = ?", id).Update("state", types.FRIENDSTATEDEFAULT)
}
func (p *friendService) AddFriend(m model2.FriendModel) {
p.db.Create(&m)
}
func (p *friendService) DeleteFriend(m model2.FriendModel) {
p.db.Where("token = ?", m.Token).Delete(&m)
}
func (p *friendService) EditFriendMark(m model2.FriendModel) {
p.db.Model(&m).Where("token = ?", m.Token).Update("mark", m.Mark)
}
func (p *friendService) EditFriendWrite(m model2.FriendModel) {
p.db.Model(&m).Where("token = ?", m.Token).Update("write", m.Write)
}
func (p *friendService) EditFriendBlock(m model2.FriendModel) {
p.db.Model(&m).Where("token = ?", m.Token).Update("block", m.Block)
}
func (p *friendService) GetFriendById(m model2.FriendModel) model2.FriendModel {
p.db.Model(m).Where("token = ?", m.Token).First(&m)
return m
}
func (p *friendService) GetFriendList() (list []model2.FriendModel) {
p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Find(&list)
return list
}
func (p *friendService) GetFriendListRemote() (list []model2.FriendModel) {
p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Where("internal_ip == '' OR internal_ip is null").Find(&list)
return list
}
func (p *friendService) GetFriendListInternal() (list []model2.FriendModel) {
p.db.Select("nick_name", "avatar", "profile", "token", "state", "mark", "block", "version").Where("internal_ip != ''").Find(&list)
return list
}
func (p *friendService) UpdateOrCreate(m model2.FriendModel) {
friend := model2.FriendModel{}
p.db.Where("token = ?", m.Token).First(&friend)
if reflect.DeepEqual(friend, model2.FriendModel{}) {
p.db.Create(&m)
} else {
p.db.Model(&m).Updates(m)
}
}
func (p *friendService) UpdateAddFriendType(m model2.FriendModel) {
p.db.Model(&m).Updates(m)
}
func (p *friendService) GetFriendByToken(token string) model2.FriendModel {
var m model2.FriendModel
p.db.Model(&m).Where("token = ?", token).First(&m)
return m
}
func (p *friendService) InternalInspection(ips []string, token string) {
for _, v := range ips {
fmt.Println("开始遍历 ip:", v)
ctx, cancel := context.WithTimeout(context.Background(), 5*time.Second)
defer cancel()
dstAddr, err := net.ResolveUDPAddr("udp", v)
if err != nil {
fmt.Println("1", err.Error())
continue
}
port, err := strconv.Atoi(config.ServerInfo.UDPPort)
if err != nil {
fmt.Println("2", err)
continue
}
srcAddr := &net.UDPAddr{
IP: net.IPv4zero, Port: port}
ticket := token
session, err := quic.DialContext(ctx, UDPConn, dstAddr, srcAddr.String(), quic_helper.GetClientTlsConfig(ticket), quic_helper.GetQUICConfig())
if err != nil {
fmt.Println("3", err, v)
continue
}
stream, err := session.OpenStreamSync(ctx)
if err != nil {
fmt.Println("4", err)
continue
}
uuid := uuid.NewV4().String()
SayHello(stream, token)
msg := model.MessageModel{
Type: types.PERSONPING,
Data: "",
From: config.ServerInfo.Token,
To: token,
UUId: uuid,
}
SendData(stream, msg)
go ReadContent(stream)
result := <-Message
fmt.Println("ping返回结果:", result, msg)
stream.Close()
if !reflect.DeepEqual(result, model.MessageModel{}) && result.Data.(string) == token && result.From == token {
fmt.Println("获取到正确的ip", v)
UDPAddressMap[result.From] = v
p.db.Model(&model2.FriendModel{}).Where("token = ?", token).Update("internal_ip", v)
return
}
}
}
func NewFriendService(db *gorm.DB) FriendService {
return &friendService{db: db}
}

View File

@@ -1,35 +0,0 @@
package service
import (
"context"
"fmt"
"github.com/google/go-github/v36/github"
"github.com/tidwall/gjson"
)
type GithubService interface {
GetManifestJsonByRepo() (image, tcp, udp string)
}
type githubService struct {
cl *github.Client
}
func (g *githubService) GetManifestJsonByRepo() (image, tcp, udp string) {
c, _, _, e := g.cl.Repositories.GetContents(context.Background(), "a624669980", "o_test_json", "/OasisManifest.json", &github.RepositoryContentGetOptions{})
if e != nil {
fmt.Println(e)
}
str, e := c.GetContent()
if e != nil {
fmt.Println(e)
}
image = gjson.Get(str, "dockerImage").String()
tcp = gjson.Get(str, "tcp_ports").Raw
udp = gjson.Get(str, "udp_ports").Raw
return
}
func GetNewGithubService(cl *github.Client) GithubService {
return &githubService{cl: cl}
}

View File

@@ -1,20 +0,0 @@
package model
import (
"time"
)
type ApplicationModel struct {
Id int `gorm:"column:id;primary_key" json:"id"`
Name string `json:"name"`
Icon string `json:"icon"`
State int `json:"state"`
Type string `json:"type"`
Order int `json:"order"`
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
}
func (p *ApplicationModel) TableName() string {
return "o_application"
}

View File

@@ -1,3 +1,13 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-13 10:56:34
* @FilePath: /CasaOS/service/model/o_container.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model package model
const CONTAINERTABLENAME = "o_container" const CONTAINERTABLENAME = "o_container"
@@ -57,11 +67,12 @@ type MyAppList struct {
Index string `json:"index"` Index string `json:"index"`
//Order string `json:"order"` //Order string `json:"order"`
Port string `json:"port"` Port string `json:"port"`
UpTime string `json:"up_time"`
Slogan string `json:"slogan"` Slogan string `json:"slogan"`
Type string `json:"type"` Type string `json:"type"`
//Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}] //Rely model.MapStrings `json:"rely"` //[{"mysql":"id"},{"mysql":"id"}]
Image string `json:"image"` Image string `json:"image"`
Volumes string `json:"volumes"` Volumes string `json:"volumes"`
NewVersion bool `json:"new_version"` Latest bool `json:"latest"`
Host string `json:"host"`
Protocol string `json:"protocol"`
} }

View File

@@ -1,56 +0,0 @@
package model
import "time"
func (p *DDNSUpdateDBModel) TableName() string {
return "o_ddns"
}
type DDNSUpdateDBModel struct {
Id uint `gorm:"column:id;primary_key" json:"id"`
Ipv4 string `gorm:"-"`
Ipv6 string `gorm:"-"`
Type uint `json:"type" form:"type"`
Domain string `json:"domain" form:"domain"`
Host string `json:"host" form:"host"`
Key string `json:"key" form:"key"`
Secret string `json:"secret" form:"secret"`
UserName string `json:"user_name" form:"user_name"`
Password string `json:"password" form:"password"`
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
}
const DDNSLISTTABLENAME = "o_ddns"
//返回给前台使用
type DDNSList struct {
Id uint `gorm:"column:id;primary_key" json:"id"`
Name string `json:"name"`
Domain string `json:"domain" form:"domain"`
Host string `json:"host" form:"host"`
IPV4 string `json:"ipv_4" gorm:"-"`
IPV6 string `json:"ipv_6" gorm:"-"`
Message string `json:"message"`
State bool `json:"state"`
CreatedAt time.Time `json:"created_at"`
UpdatedAt time.Time `json:"updated_at"`
}
//定时任务使用
type DDNSCoreList struct {
Id uint `gorm:"column:id;primary_key" json:"id"`
Domain string `json:"domain" form:"domain"`
Name string `json:"name" form:"name"`
Type uint `json:"type"`
Key string `json:"key"`
Message string `json:"message"`
State bool `json:"state"`
Secret string `json:"secret" form:"secret"`
UserName string `json:"user_name" form:"user_name"`
Password string `json:"password" form:"password"`
ApiHost string `json:"api_host"`
Host string `json:"host"`
IPV4 string `json:"ipv_4" gorm:"-"`
IPV6 string `json:"ipv_6" gorm:"-"`
}

View File

@@ -1,11 +0,0 @@
package model
type DDNSTypeDBModel struct {
Id uint `gorm:"column:id;primary_key" json:"id"`
Name string `json:"name"`
ApiHost string `json:"api_host"`
}
func (p *DDNSTypeDBModel) TableName() string {
return "o_ddns_type"
}

View File

@@ -1,16 +0,0 @@
package model
type PersonDownRecordDBModel struct {
UUID string `gorm:"column:uuid;primary_key" json:"uuid"`
Name string `json:"name"` //file name
Type int `json:"type"`
Size int64 `json:"size"` //file size
Downloader string `json:"downloader"` //Error message
Path string `json:"path"`
Created int64 `gorm:"autoCreateTime" json:"created"`
Updated int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated"`
}
func (p *PersonDownRecordDBModel) TableName() string {
return "o_person_down_record"
}

View File

@@ -1,24 +0,0 @@
package model
type PersonDownloadDBModel struct {
UUID string `gorm:"column:uuid;primary_key" json:"uuid"`
State int `json:"state"` //
Type int `json:"type"` //defult 0
Name string `json:"name"` //file name
Size int64 `json:"size"` //file size
BlockSize int `json:"block_size"` //Size of each file block
Length int `json:"length"` //slice length
Hash string `json:"hash"` //File hash value
Error string `json:"error"` //
From string `json:"from"` //Error message
Path string `json:"path"` //Full path to the file
Already int `json:"already" gorm:"-"` //Folder blocks that have been downloaded
LocalPath string `json:"local_path"` //The address where the file is saved after download
Duration int64 `json:"duration" gorm:"-"` //Length of time
Created int64 `gorm:"autoCreateTime" json:"created"`
Updated int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated"`
}
func (p *PersonDownloadDBModel) TableName() string {
return "o_person_download"
}

View File

@@ -1,21 +0,0 @@
package model
type FriendModel struct {
State int `json:"state"`
CreatedAt int64 `gorm:"autoCreateTime" json:"created_at"`
UpdatedAt int64 `gorm:"autoCreateTime;autoUpdateTime" json:"updated_at"`
NickName string `json:"nick_name"`
Mark string `json:"mark"` //Remarks
Block bool `json:"block"` //Disable or not
Avatar string `json:"avatar"` //User avatar
Token string `gorm:"column:token;primary_key" json:"token"`
Profile string `json:"profile"` //Description
OnLine bool `json:"on_line" gorm:"-"`
Version int `json:"version"`
Write bool `json:"write"`
LocalIP string `json:"local_ip"`
}
func (p *FriendModel) TableName() string {
return "o_friend"
}

View File

@@ -1,20 +0,0 @@
package model
import "time"
type ShareDirDBModel struct {
Id uint `gorm:"column:id;primary_key" json:"id"`
Name string `gorm:"size:50" json:"name"`
Comment string `gorm:"size:200" json:"comment"`
Path string `json:"path"`
ReadOnly bool `json:"read_only"`
Writeable bool `json:"writeable"`
Browseable bool `json:"browseable"`
ValidUsers string `gorm:"size:200" json:"valid_users"` //可以访问的用户 多用户用 , 分割
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
}
func (p *ShareDirDBModel) TableName() string {
return "o_share_directory"
}

View File

@@ -1,17 +0,0 @@
package model
import "time"
type ShortcutsDBModel struct {
Id uint `gorm:"column:id;primary_key" json:"id"`
Title string `json:"title"`
Url string `json:"url"`
Icon string `json:"icon"`
Sort int `json:"sort"`
CreatedAt time.Time `gorm:"<-:create" json:"created_at"`
UpdatedAt time.Time `gorm:"<-:create;<-:update" json:"updated_at"`
}
func (p *ShortcutsDBModel) TableName() string {
return "o_shortcuts"
}

View File

@@ -1,17 +0,0 @@
package model
type TaskDBModel struct {
Id uint `gorm:"column:id;primary_key" json:"id"`
Title string `gorm:"size:200" json:"title"`
ImageUrl string `json:"image_url"`
Content string `gorm:"size:255" json:"content"`
Url string `json:"url"`
State int `json:"state"` // 0:未阅读,1:已阅读
Type int `json:"type"`
CreatedAt string `gorm:"<-:create;autoCreateTime" json:"created_at"`
UpdatedAt string `gorm:"<-:create;<-:update;autoUpdateTime" json:"updated_at"`
}
func (p *TaskDBModel) TableName() string {
return "o_task"
}

31
service/model/o_user.go Normal file
View File

@@ -0,0 +1,31 @@
/*
* @Author: LinkLeong link@icewhale.com
* @Date: 2022-05-13 18:15:46
* @LastEditors: LinkLeong
* @LastEditTime: 2022-07-11 17:57:00
* @FilePath: /CasaOS/service/model/o_user.go
* @Description:
* @Website: https://www.casaos.io
* Copyright (c) 2022 by icewhale, All Rights Reserved.
*/
package model
import "time"
//Soon to be removed
type UserDBModel struct {
Id int `gorm:"column:id;primary_key" json:"id"`
Username string `json:"username"`
Password string `json:"password,omitempty"`
Role string `json:"role"`
Email string `json:"email"`
Nickname string `json:"nickname"`
Avatar string `json:"avatar"`
Description string `json:"description"`
CreatedAt time.Time `gorm:"<-:create;autoCreateTime" json:"created_at,omitempty"`
UpdatedAt time.Time `gorm:"<-:create;<-:update;autoUpdateTime" json:"updated_at,omitempty"`
}
func (p *UserDBModel) TableName() string {
return "o_users"
}

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