Compare commits

..

21 Commits
v0.4.9 ... main

Author SHA1 Message Date
U2FsdGVkX1
a6ff39e47d
Add initial RISC-V support (#2206)
Some checks failed
Collect Code Coverage / build (push) Has been cancelled
Auto Publish Website / goreleaser (push) Has been cancelled
It depends upon https://github.com/IceWhaleTech/github/pull/3

resolved https://github.com/IceWhaleTech/CasaOS/issues/1669
2025-04-16 14:16:50 +08:00
CorrectRoad
23eb739f01
Update README.md (#2185)
Some checks failed
Collect Code Coverage / build (push) Has been cancelled
Auto Publish Website / goreleaser (push) Has been cancelled
Signed-off-by: CorrectRoad <a778917369@gmail.com>
2025-03-08 12:38:58 +08:00
Ns2Kracy
ba285cb8bd
fix: update user info retrieval and clean up unused code (#2101)
Some checks failed
Collect Code Coverage / build (push) Has been cancelled
Auto Publish Website / goreleaser (push) Has been cancelled
2024-12-19 11:14:15 +08:00
Ns2Kracy
63f01489a8
update version (#2098)
Some checks failed
Collect Code Coverage / build (push) Has been cancelled
Auto Publish Website / goreleaser (push) Has been cancelled
2024-12-17 15:54:54 +08:00
Ns2Kracy
6bbb0802aa
fix: problem while getting storage type (#2097) 2024-12-17 15:53:04 +08:00
Ns2Kracy
c26cf4dbec
fix: cloud storage (#2096)
Some checks are pending
Collect Code Coverage / build (push) Waiting to run
Auto Publish Website / goreleaser (push) Waiting to run
2024-12-17 15:23:15 +08:00
Ns2Kracy
958a483385
Update constants.go (#2083)
Some checks failed
Collect Code Coverage / build (push) Has been cancelled
Auto Publish Website / goreleaser (push) Has been cancelled
2024-12-10 17:42:46 +08:00
Ns2Kracy
16e97ec66f
fix: too much log (#2078)
Some checks failed
Collect Code Coverage / build (push) Has been cancelled
Auto Publish Website / goreleaser (push) Has been cancelled
2024-12-06 15:43:54 +08:00
David Wood
5ea588b813
chore: fix problematic comments (#2030)
Some checks failed
Collect Code Coverage / build (push) Has been cancelled
Auto Publish Website / goreleaser (push) Has been cancelled
2024-12-04 11:04:17 +08:00
Lauren
7da0f0d49e
Update README.md
Signed-off-by: Lauren <Lauren-ED209@users.noreply.github.com>
2024-10-17 18:59:41 +08:00
Ns2Kracy
2adb795896
Update to 0.4.13 (#2004) 2024-09-18 15:53:41 +08:00
Ns2Kracy
8b251dc407
fix: get file content twice (#2000) 2024-09-14 23:21:03 +08:00
CorrectRoad
e4bf67dad5
chore: bump casaos version (#1999)
Signed-off-by: CorrectRoad <a778917369@gmail.com>
2024-09-14 11:37:28 +08:00
CorrectRoad
e8f9d3aaf5
fix: fix GitHub Action not work (#1996) 2024-09-11 16:04:30 +08:00
CorrectRoad
bb0d9ac25c
feat: add sync OpenAPI workflows (#1995) 2024-09-11 16:00:28 +08:00
link
3a835c00e3
Update constants.go (#1961)
Signed-off-by: link <a624669980@163.com>
2024-08-14 13:35:09 +08:00
link
e4447981cb
Update constants.go (#1950)
Signed-off-by: link <a624669980@163.com>
2024-08-12 14:19:40 +08:00
James Stroud
170b599e86
add instructions to update CasaOS (#1925)
This will help users to updates and determine the version of CasaOS from
a terminal session. I tested all commands multiple times. I hope you
like my suggestions. Take care
2024-07-31 14:26:24 +08:00
Ns2Kracy
18ce1d6342
fix: safe cmd (#1921) 2024-07-24 21:46:08 +08:00
Kian Kasad
1c483a5d9c
Fix typo in README.md: "tutoial" → "tutorial" (#1862)
Just fixing a typo I noticed while reading the README.

Signed-off-by: Kian Kasad <kian@kasad.com>
2024-07-23 10:34:45 +08:00
Ns2Kracy
8f7c99779f
feat: migrate gin to echo (#1854) 2024-06-04 14:14:55 +08:00
35 changed files with 746 additions and 950 deletions

19
.github/sync_openapi.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: Sync OpenAPI
on:
workflow_call:
inputs:
project-name:
required: true
type: string
push:
branches:
- main
jobs:
sync:
uses: IceWhaleTech/github/.github/workflows/sync_openapi.yml@main
with:
project-name: casaos
secrets:
API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }}

19
.github/workflows/sync_openapi.yml vendored Normal file
View File

@ -0,0 +1,19 @@
name: Sync OpenAPI
on:
workflow_call:
inputs:
project-name:
required: true
type: string
push:
branches:
- main
jobs:
sync:
uses: IceWhaleTech/github/.github/workflows/sync_openapi.yml@main
with:
project-name: casaos
secrets:
API_TOKEN_GITHUB: ${{ secrets.API_TOKEN_GITHUB }}

View File

@ -59,6 +59,22 @@ builds:
- arm - arm
goarm: goarm:
- "7" - "7"
- id: casaos-riscv64
binary: build/sysroot/usr/bin/casaos
env:
- CC=riscv64-linux-gnu-gcc
gcflags:
- all=-N -l
ldflags:
- -extldflags "-static"
tags:
- musl
- netgo
- osusergo
goos:
- linux
goarch:
- riscv64
- id: casaos-migration-tool-amd64 - id: casaos-migration-tool-amd64
binary: build/sysroot/usr/bin/casaos-migration-tool binary: build/sysroot/usr/bin/casaos-migration-tool
main: ./cmd/migration-tool main: ./cmd/migration-tool
@ -112,6 +128,23 @@ builds:
- arm - arm
goarm: goarm:
- "7" - "7"
- id: casaos-migration-tool-riscv64
binary: build/sysroot/usr/bin/casaos-migration-tool
main: ./cmd/migration-tool
env:
- CC=riscv64-linux-gnu-gcc
gcflags:
- all=-N -l
ldflags:
- -extldflags "-static"
tags:
- musl
- netgo
- osusergo
goos:
- linux
goarch:
- riscv64
archives: archives:
- name_template: >- - name_template: >-
{{ .Os }}-{{- if eq .Arch "arm" }}arm-7{{- else }}{{ .Arch }}{{- end }}-{{ .ProjectName }}-v{{ .Version }} {{ .Os }}-{{- if eq .Arch "arm" }}arm-7{{- else }}{{ .Arch }}{{- end }}-{{ .ProjectName }}-v{{ .Version }}
@ -120,6 +153,7 @@ archives:
- casaos-amd64 - casaos-amd64
- casaos-arm64 - casaos-arm64
- casaos-arm-7 - casaos-arm-7
- casaos-riscv64
files: files:
- build/**/* - build/**/*
- name_template: >- - name_template: >-
@ -129,6 +163,7 @@ archives:
- casaos-migration-tool-amd64 - casaos-migration-tool-amd64
- casaos-migration-tool-arm64 - casaos-migration-tool-arm64
- casaos-migration-tool-arm-7 - casaos-migration-tool-arm-7
- casaos-migration-tool-riscv64
files: files:
- build/sysroot/etc/**/* - build/sysroot/etc/**/*
checksum: checksum:

View File

@ -92,6 +92,30 @@ builds:
- arm - arm
goarm: goarm:
- "7" - "7"
- id: casaos-riscv64
binary: build/sysroot/usr/bin/casaos
env:
- CC=riscv64-linux-gnu-gcc
ldflags:
- -X main.commit={{.Commit}}
- -X main.date={{.Date}}
- -X github.com/IceWhaleTech/CasaOS/drivers/google_drive.client_id={{.Env.GoogleID}}
- -X github.com/IceWhaleTech/CasaOS/drivers/google_drive.client_secret={{.Env.GoogleSecret}}
- -X github.com/IceWhaleTech/CasaOS/drivers/onedrive.client_id={{.Env.OneDriveID}}
- -X github.com/IceWhaleTech/CasaOS/drivers/onedrive.client_secret={{.Env.OneDriveSecret}}
- -X github.com/IceWhaleTech/CasaOS/drivers/dropbox.app_key={{.Env.DropboxKey}}
- -X github.com/IceWhaleTech/CasaOS/drivers/dropbox.app_secret={{.Env.DropboxSecret}}
- -s
- -w
- -extldflags "-static"
tags:
- musl
- netgo
- osusergo
goos:
- linux
goarch:
- riscv64
- id: casaos-migration-tool-amd64 - id: casaos-migration-tool-amd64
binary: build/sysroot/usr/bin/casaos-migration-tool binary: build/sysroot/usr/bin/casaos-migration-tool
hooks: hooks:
@ -160,6 +184,25 @@ builds:
- arm - arm
goarm: goarm:
- "7" - "7"
- id: casaos-migration-tool-riscv64
binary: build/sysroot/usr/bin/casaos-migration-tool
main: ./cmd/migration-tool
env:
- CC=riscv64-linux-gnu-gcc
ldflags:
- -X main.commit={{.Commit}}
- -X main.date={{.Date}}
- -s
- -w
- -extldflags "-static"
tags:
- musl
- netgo
- osusergo
goos:
- linux
goarch:
- riscv64
archives: archives:
- name_template: >- - name_template: >-
{{ .Os }}-{{- if eq .Arch "arm" }}arm-7{{- else }}{{ .Arch }}{{- end }}-{{ .ProjectName }}-v{{ .Version }} {{ .Os }}-{{- if eq .Arch "arm" }}arm-7{{- else }}{{ .Arch }}{{- end }}-{{ .ProjectName }}-v{{ .Version }}
@ -168,6 +211,7 @@ archives:
- casaos-amd64 - casaos-amd64
- casaos-arm64 - casaos-arm64
- casaos-arm-7 - casaos-arm-7
- casaos-riscv64
files: files:
- build/**/* - build/**/*
- name_template: >- - name_template: >-
@ -177,6 +221,7 @@ archives:
- casaos-migration-tool-amd64 - casaos-migration-tool-amd64
- casaos-migration-tool-arm64 - casaos-migration-tool-arm64
- casaos-migration-tool-arm-7 - casaos-migration-tool-arm-7
- casaos-migration-tool-riscv64
files: files:
- build/sysroot/etc/**/* - build/sysroot/etc/**/*
checksum: checksum:

View File

@ -49,7 +49,7 @@
<br/> <br/>
<!-- CasaOS YouTube --> <!-- CasaOS YouTube -->
<a href="https://www.youtube.com/channel/UC2zMrUYT17AJhIl9XWZzT8g" target="_blank"> <a href="https://www.youtube.com/channel/UC2zMrUYT17AJhIl9XWZzT8g" target="_blank">
<img alt="YouTube Tutoial Views" src="https://img.shields.io/youtube/channel/views/UC2zMrUYT17AJhIl9XWZzT8g?style=for-the-badge&logo=youtube&logoColor=red&label=YouTube%20Tutoial%20Views" /> <img alt="YouTube Tutorial Views" src="https://img.shields.io/youtube/channel/views/UC2zMrUYT17AJhIl9XWZzT8g?style=for-the-badge&logo=youtube&logoColor=red&label=YouTube%20Tutorial%20Views" />
</a> </a>
<br/> <br/>
<!-- CasaOS Links --> <!-- CasaOS Links -->
@ -134,6 +134,30 @@ or
curl -fsSL https://get.casaos.io | sudo bash curl -fsSL https://get.casaos.io | sudo bash
``` ```
### Update CasaOS
CasaOS can be updated from the User Interface (UI), via `Settings ... Update`.
Alternatively it can be updated from a terminal session. To update from a terminal session, it must be done either from a secure shell (ssh) session to the device or from a directly attached terminal and keyboard to the device running CasaOS, this cannot be done from the terminal via the CasaOS User Interface (UI). To update to the latest release of CasaOS from a terminal session run this command:
```sh
wget -qO- https://get.casaos.io/update | sudo bash
```
or
```sh
curl -fsSL https://get.casaos.io/update | sudo bash
```
To determine version of CasaOS from a terminal session run this command:
```sh
casaos -v
```
### Uninstall CasaOS ### Uninstall CasaOS
@ -170,9 +194,6 @@ CasaOS is a community-driven open source project and the people involved are Cas
- See <https://wiki.casaos.io/en/contribute> for ways of contributing to CasaOS - See <https://wiki.casaos.io/en/contribute> for ways of contributing to CasaOS
- See <https://wiki.casaos.io/en/contribute/development> if you want to be involved in code contribution specifically - See <https://wiki.casaos.io/en/contribute/development> if you want to be involved in code contribution specifically
## Donate
<p ><a href="https://www.buymeacoffee.com/icewhaletech"> <img align="center" src="https://cdn.buymeacoffee.com/buttons/v2/default-yellow.png" height="50" width="210" alt="bappi2097" target="_blank" /></a></p>
## Credits ## Credits
@ -187,7 +208,7 @@ Everyone's contribution is greatly appreciated. ([Emoji Key](https://allcontribu
<tr> <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/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/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/tigerinus"><img src="https://avatars.githubusercontent.com/u/7172560?v=4?s=100" width="100px;" alt=""/><br /><sub><b>太戈</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://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://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://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>

View File

@ -111,6 +111,9 @@ aarch64)
armv7l) armv7l)
ARCH="arm-7" ARCH="arm-7"
;; ;;
riscv64)
ARCH="riscv64"
;;
*) *)
__error "Unsupported architecture" __error "Unsupported architecture"
;; ;;

View File

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

View File

@ -26,6 +26,7 @@ func (d *Onedrive) Config() driver.Config {
func (d *Onedrive) GetAddition() driver.Additional { func (d *Onedrive) GetAddition() driver.Additional {
return &d.Addition return &d.Addition
} }
func (d *Onedrive) Init(ctx context.Context) error { func (d *Onedrive) Init(ctx context.Context) error {
if d.ChunkSize < 1 { if d.ChunkSize < 1 {
d.ChunkSize = 5 d.ChunkSize = 5
@ -35,19 +36,20 @@ func (d *Onedrive) Init(ctx context.Context) error {
} }
return d.refreshToken() return d.refreshToken()
} }
func (d *Onedrive) GetUserInfo(ctx context.Context) (string, error) { func (d *Onedrive) GetUserInfo(ctx context.Context) (string, error) {
return "", nil return "", nil
} }
func (d *Onedrive) GetInfo(ctx context.Context) (string, string, string, error) { func (d *Onedrive) GetInfo(ctx context.Context) (string, string, string, error) {
url := d.GetMetaUrl(false, "/") url := d.GetMetaUrl(false, "/")
user := Info{} user := Info{}
resp, err := d.Request(url, http.MethodGet, nil, &user) _, err := d.Request(url, http.MethodGet, nil, &user)
if err != nil { if err != nil {
return "", "", "", err return "", "", "", err
} }
logger.Info("resp", zap.Any("resp", resp)) return user.CreatedBy.User.Email, user.ParentReference.DriveID, user.ParentReference.DriveType, nil
return user.LastModifiedBy.User.DisplayName, user.ParentReference.DriveID, user.ParentReference.DriveType, nil
} }
func (d *Onedrive) GetSpaceSize(ctx context.Context) (used string, total string, err error) { func (d *Onedrive) GetSpaceSize(ctx context.Context) (used string, total string, err error) {
@ -63,6 +65,7 @@ func (d *Onedrive) GetSpaceSize(ctx context.Context) (used string, total string,
total = strconv.Itoa(size.Total) total = strconv.Itoa(size.Total)
return return
} }
func (d *Onedrive) Drop(ctx context.Context) error { func (d *Onedrive) Drop(ctx context.Context) error {
return nil return nil
} }

View File

@ -43,19 +43,12 @@ type About struct {
} }
type Info struct { type Info struct {
LastModifiedBy struct { CreatedBy struct {
Application struct {
DisplayName string `json:"displayName"`
ID string `json:"id"`
} `json:"application"`
Device struct {
ID string `json:"id"`
} `json:"device"`
User struct { User struct {
Email string `json:"email"`
DisplayName string `json:"displayName"` DisplayName string `json:"displayName"`
ID string `json:"id"`
} `json:"user"` } `json:"user"`
} `json:"lastModifiedBy"` } `json:"createdBy"`
ParentReference struct { ParentReference struct {
DriveID string `json:"driveId"` DriveID string `json:"driveId"`
DriveType string `json:"driveType"` DriveType string `json:"driveType"`

View File

@ -3,11 +3,10 @@ package onedrive
import ( import (
"errors" "errors"
"fmt" "fmt"
"net/url"
"strings"
"github.com/IceWhaleTech/CasaOS-Common/utils/logger" "github.com/IceWhaleTech/CasaOS-Common/utils/logger"
"github.com/IceWhaleTech/CasaOS/drivers/base" "github.com/IceWhaleTech/CasaOS/drivers/base"
"github.com/IceWhaleTech/CasaOS/pkg/utils"
"go.uber.org/zap" "go.uber.org/zap"
) )
@ -15,6 +14,7 @@ var (
client_id = "private build" client_id = "private build"
client_secret = "private build" client_secret = "private build"
) )
var onedriveHostMap = map[string]Host{ var onedriveHostMap = map[string]Host{
"global": { "global": {
Oauth: "https://login.microsoftonline.com", Oauth: "https://login.microsoftonline.com",
@ -34,31 +34,9 @@ var onedriveHostMap = map[string]Host{
}, },
} }
func EncodePath(path string, all ...bool) string {
seg := strings.Split(path, "/")
toReplace := []struct {
Src string
Dst string
}{
{Src: "%", Dst: "%25"},
{"%", "%25"},
{"?", "%3F"},
{"#", "%23"},
}
for i := range seg {
if len(all) > 0 && all[0] {
seg[i] = url.PathEscape(seg[i])
} else {
for j := range toReplace {
seg[i] = strings.ReplaceAll(seg[i], toReplace[j].Src, toReplace[j].Dst)
}
}
}
return strings.Join(seg, "/")
}
func (d *Onedrive) GetMetaUrl(auth bool, path string) string { func (d *Onedrive) GetMetaUrl(auth bool, path string) string {
host := onedriveHostMap[d.Region] host := onedriveHostMap[d.Region]
path = EncodePath(path, true) path = utils.EncodePath(path, true)
if auth { if auth {
return host.Oauth return host.Oauth
} }

47
go.mod
View File

@ -1,31 +1,29 @@
module github.com/IceWhaleTech/CasaOS module github.com/IceWhaleTech/CasaOS
go 1.20 go 1.21
require ( require (
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
github.com/IceWhaleTech/CasaOS-Common v0.4.8-alpha3 github.com/IceWhaleTech/CasaOS-Common v0.4.11-alpha4
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
github.com/deckarep/golang-set/v2 v2.3.0 github.com/deckarep/golang-set/v2 v2.3.0
github.com/deepmap/oapi-codegen v1.12.4 github.com/deepmap/oapi-codegen v1.12.4
github.com/disintegration/imaging v1.6.2 github.com/disintegration/imaging v1.6.2
github.com/dsoprea/go-exif/v3 v3.0.1 github.com/dsoprea/go-exif/v3 v3.0.1
github.com/getkin/kin-openapi v0.117.0 github.com/getkin/kin-openapi v0.117.0
github.com/gin-contrib/gzip v0.0.6
github.com/gin-gonic/gin v1.9.1
github.com/glebarez/sqlite v1.8.0 github.com/glebarez/sqlite v1.8.0
github.com/go-ini/ini v1.67.0 github.com/go-ini/ini v1.67.0
github.com/go-resty/resty/v2 v2.7.0 github.com/go-resty/resty/v2 v2.7.0
github.com/golang/mock v1.6.0 github.com/golang/mock v1.6.0
github.com/gomodule/redigo v1.8.9 github.com/gomodule/redigo v1.8.9
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 github.com/google/uuid v1.5.0
github.com/googollee/go-socket.io v1.7.0 github.com/googollee/go-socket.io v1.7.0
github.com/gorilla/websocket v1.5.0 github.com/gorilla/websocket v1.5.0
github.com/h2non/filetype v1.1.3 github.com/h2non/filetype v1.1.3
github.com/hirochachacha/go-smb2 v1.1.0 github.com/hirochachacha/go-smb2 v1.1.0
github.com/json-iterator/go v1.1.12 github.com/json-iterator/go v1.1.12
github.com/labstack/echo/v4 v4.10.2 github.com/labstack/echo/v4 v4.12.0
github.com/maruel/natural v1.1.0 github.com/maruel/natural v1.1.0
github.com/mholt/archiver/v3 v3.5.1 github.com/mholt/archiver/v3 v3.5.1
github.com/mileusna/useragent v1.2.1 github.com/mileusna/useragent v1.2.1
@ -37,14 +35,14 @@ require (
github.com/samber/lo v1.38.1 github.com/samber/lo v1.38.1
github.com/shirou/gopsutil/v3 v3.23.2 github.com/shirou/gopsutil/v3 v3.23.2
github.com/sirupsen/logrus v1.9.3 github.com/sirupsen/logrus v1.9.3
github.com/stretchr/testify v1.8.4 github.com/stretchr/testify v1.9.0
github.com/tidwall/gjson v1.14.4 github.com/tidwall/gjson v1.17.0
go.uber.org/goleak v1.2.1 go.uber.org/goleak v1.2.1
go.uber.org/zap v1.24.0 go.uber.org/zap v1.24.0
golang.org/x/crypto v0.14.0 golang.org/x/crypto v0.23.0
golang.org/x/oauth2 v0.7.0 golang.org/x/oauth2 v0.7.0
golang.org/x/sync v0.3.0 golang.org/x/sync v0.3.0
golang.org/x/sys v0.14.0 golang.org/x/sys v0.20.0
gorm.io/gorm v1.25.0 gorm.io/gorm v1.25.0
gotest.tools v2.2.0+incompatible gotest.tools v2.2.0+incompatible
) )
@ -53,46 +51,38 @@ require (
github.com/andybalholm/brotli v1.0.5 // indirect github.com/andybalholm/brotli v1.0.5 // indirect
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
github.com/benbjohnson/clock v1.3.1 // indirect github.com/benbjohnson/clock v1.3.1 // indirect
github.com/bytedance/sonic v1.9.1 // indirect
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/coreos/go-systemd/v22 v22.5.0 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
github.com/dustin/go-humanize v1.0.1 // indirect github.com/dustin/go-humanize v1.0.1 // indirect
github.com/gabriel-vasile/mimetype v1.4.2 // indirect
github.com/geoffgarside/ber v1.1.0 // indirect github.com/geoffgarside/ber v1.1.0 // indirect
github.com/gin-contrib/sse v0.1.0 // indirect
github.com/glebarez/go-sqlite v1.21.1 // indirect github.com/glebarez/go-sqlite v1.21.1 // indirect
github.com/go-errors/errors v1.4.2 // indirect github.com/go-errors/errors v1.4.2 // indirect
github.com/go-ole/go-ole v1.2.6 // indirect github.com/go-ole/go-ole v1.2.6 // indirect
github.com/go-openapi/jsonpointer v0.19.6 // indirect github.com/go-openapi/jsonpointer v0.19.6 // indirect
github.com/go-openapi/swag v0.22.3 // indirect github.com/go-openapi/swag v0.22.3 // indirect
github.com/go-playground/locales v0.14.1 // indirect
github.com/go-playground/universal-translator v0.18.1 // indirect
github.com/go-playground/validator/v10 v10.14.0 // indirect
github.com/goccy/go-json v0.10.2 // indirect
github.com/godbus/dbus/v5 v5.1.0 // indirect github.com/godbus/dbus/v5 v5.1.0 // indirect
github.com/gofrs/uuid v4.4.0+incompatible // indirect github.com/gofrs/uuid v4.4.0+incompatible // indirect
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
github.com/golang-jwt/jwt/v5 v5.0.0 // indirect
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
github.com/golang/protobuf v1.5.3 // indirect github.com/golang/protobuf v1.5.3 // indirect
github.com/golang/snappy v0.0.4 // indirect github.com/golang/snappy v0.0.4 // indirect
github.com/google/go-cmp v0.6.0 // indirect github.com/google/go-cmp v0.6.0 // indirect
github.com/google/go-querystring v1.1.0 // indirect github.com/google/go-querystring v1.1.0 // indirect
github.com/google/safetext v0.0.0-20240104143208-7a7d9b3d812f // indirect
github.com/gorilla/mux v1.8.0 // indirect github.com/gorilla/mux v1.8.0 // indirect
github.com/invopop/yaml v0.2.0 // indirect github.com/invopop/yaml v0.2.0 // indirect
github.com/jinzhu/inflection v1.0.0 // indirect github.com/jinzhu/inflection v1.0.0 // indirect
github.com/jinzhu/now v1.1.5 // indirect github.com/jinzhu/now v1.1.5 // indirect
github.com/josharian/intern v1.0.0 // indirect github.com/josharian/intern v1.0.0 // indirect
github.com/klauspost/compress v1.16.5 // indirect github.com/klauspost/compress v1.16.7 // indirect
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
github.com/klauspost/pgzip v1.2.5 // indirect github.com/klauspost/pgzip v1.2.5 // indirect
github.com/kr/pretty v0.3.1 // indirect github.com/labstack/echo-jwt/v4 v4.2.0 // indirect
github.com/labstack/gommon v0.4.0 // indirect github.com/labstack/gommon v0.4.2 // indirect
github.com/leodido/go-urn v1.2.4 // indirect
github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de // indirect github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de // indirect
github.com/mailru/easyjson v0.7.7 // indirect github.com/mailru/easyjson v0.7.7 // indirect
github.com/mattn/go-colorable v0.1.13 // indirect github.com/mattn/go-colorable v0.1.13 // indirect
@ -101,18 +91,15 @@ require (
github.com/modern-go/reflect2 v1.0.2 // indirect github.com/modern-go/reflect2 v1.0.2 // indirect
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
github.com/nwaples/rardecode v1.1.3 // indirect github.com/nwaples/rardecode v1.1.3 // indirect
github.com/pelletier/go-toml/v2 v2.0.8 // indirect
github.com/perimeterx/marshmallow v1.1.4 // indirect github.com/perimeterx/marshmallow v1.1.4 // indirect
github.com/pierrec/lz4/v4 v4.1.17 // indirect github.com/pierrec/lz4/v4 v4.1.17 // indirect
github.com/pmezard/go-difflib v1.0.0 // indirect github.com/pmezard/go-difflib v1.0.0 // indirect
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
github.com/rogpeppe/go-internal v1.10.0 // indirect
github.com/tidwall/match v1.1.1 // indirect github.com/tidwall/match v1.1.1 // indirect
github.com/tidwall/pretty v1.2.1 // indirect github.com/tidwall/pretty v1.2.1 // indirect
github.com/tklauser/go-sysconf v0.3.11 // indirect github.com/tklauser/go-sysconf v0.3.11 // indirect
github.com/tklauser/numcpus v0.6.0 // indirect github.com/tklauser/numcpus v0.6.0 // indirect
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
github.com/ugorji/go/codec v1.2.11 // indirect github.com/ugorji/go/codec v1.2.11 // indirect
github.com/ulikunitz/xz v0.5.11 // indirect github.com/ulikunitz/xz v0.5.11 // indirect
github.com/valyala/bytebufferpool v1.0.0 // indirect github.com/valyala/bytebufferpool v1.0.0 // indirect
@ -121,12 +108,11 @@ require (
github.com/yusufpapurcu/wmi v1.2.2 // indirect github.com/yusufpapurcu/wmi v1.2.2 // indirect
go.uber.org/atomic v1.10.0 // indirect go.uber.org/atomic v1.10.0 // indirect
go.uber.org/multierr v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect
golang.org/x/arch v0.3.0 // indirect
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 // indirect
golang.org/x/image v0.6.0 // indirect golang.org/x/image v0.6.0 // indirect
golang.org/x/net v0.17.0 // indirect golang.org/x/net v0.25.0 // indirect
golang.org/x/text v0.13.0 // indirect golang.org/x/text v0.15.0 // indirect
golang.org/x/time v0.3.0 // indirect golang.org/x/time v0.5.0 // indirect
google.golang.org/appengine v1.6.7 // indirect google.golang.org/appengine v1.6.7 // indirect
google.golang.org/protobuf v1.30.0 // indirect google.golang.org/protobuf v1.30.0 // indirect
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
@ -136,4 +122,5 @@ require (
modernc.org/mathutil v1.5.0 // indirect modernc.org/mathutil v1.5.0 // indirect
modernc.org/memory v1.5.0 // indirect modernc.org/memory v1.5.0 // indirect
modernc.org/sqlite v1.21.2 // indirect modernc.org/sqlite v1.21.2 // indirect
mvdan.cc/sh/v3 v3.7.0 // indirect
) )

129
go.sum
View File

@ -1,7 +1,7 @@
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d h1:62lEBImTxZ83pgzywgDNIrPPuQ+j4ep9QjqrWBn1hrU= github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d h1:62lEBImTxZ83pgzywgDNIrPPuQ+j4ep9QjqrWBn1hrU=
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ= github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ=
github.com/IceWhaleTech/CasaOS-Common v0.4.8-alpha3 h1:5E5LAqi2uXpOZqcPOgQ4m6d9MagYyfhKIFXnzd8s3W4= github.com/IceWhaleTech/CasaOS-Common v0.4.11-alpha4 h1:W+kOJ3NcWCEAnZdjqmnjnhAG+aLbiVNXnOvV+1bHsB0=
github.com/IceWhaleTech/CasaOS-Common v0.4.8-alpha3/go.mod h1:2IuYyy5qW1BE6jqC6M+tOU+WtUec1K565rLATBJ9p/0= github.com/IceWhaleTech/CasaOS-Common v0.4.11-alpha4/go.mod h1:513p+6RXPBFr98GQZbY1TCyt6Q0jWiuK6vh+gBTmNwA=
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y= github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs= github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
@ -11,12 +11,6 @@ github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP
github.com/benbjohnson/clock v1.3.1 h1:Heo0FGXzOxUHquZbraxt+tT7UXVDhesUQH5ISbsOkCQ= github.com/benbjohnson/clock v1.3.1 h1:Heo0FGXzOxUHquZbraxt+tT7UXVDhesUQH5ISbsOkCQ=
github.com/benbjohnson/clock v1.3.1/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA= github.com/benbjohnson/clock v1.3.1/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w= github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
github.com/bytedance/sonic v1.9.1 h1:6iJ6NqdoxCDr6mbY8h18oSO+cShGSMRGCEo7F2h0x8s=
github.com/bytedance/sonic v1.9.1/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4= github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs= github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
@ -53,19 +47,12 @@ github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 h1:DilThiXje
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8= github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8=
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY= github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto= github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU= github.com/frankban/quicktest v1.14.5 h1:dfYrrRyLtiqT9GyKXgdh+k4inNeTvmGbuSgZ3lx3GhA=
github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA= github.com/frankban/quicktest v1.14.5/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w= github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w=
github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc= github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc=
github.com/getkin/kin-openapi v0.117.0 h1:QT2DyGujAL09F4NrKDHJGsUoIprlIcFVHWDVDcUFE8A= github.com/getkin/kin-openapi v0.117.0 h1:QT2DyGujAL09F4NrKDHJGsUoIprlIcFVHWDVDcUFE8A=
github.com/getkin/kin-openapi v0.117.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc= github.com/getkin/kin-openapi v0.117.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc=
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
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-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
github.com/gin-gonic/gin v1.9.1 h1:4idEAncQnU5cB7BeOkPtxjfCSye0AAm1R0RVIqJ+Jmg=
github.com/gin-gonic/gin v1.9.1/go.mod h1:hPrL7YrpYKXt5YId3A/Tnip5kqbEAP+KLuI3SUcPTeU=
github.com/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0y5NY= github.com/glebarez/go-sqlite v1.21.1 h1:7MZyUPh2XTrHS7xNEHQbrhfMZuPSzhkm2A1qgg0y5NY=
github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E= github.com/glebarez/go-sqlite v1.21.1/go.mod h1:ISs8MF6yk5cL4n/43rSOmVMGJJjHYr7L2MbZZ5Q4E2E=
github.com/glebarez/sqlite v1.8.0 h1:02X12E2I/4C1n+v90yTqrjRa8yuo7c3KeHI3FRznCvc= github.com/glebarez/sqlite v1.8.0 h1:02X12E2I/4C1n+v90yTqrjRa8yuo7c3KeHI3FRznCvc=
@ -85,24 +72,10 @@ github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaL
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.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g= github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14= github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
github.com/go-playground/validator/v10 v10.14.0 h1:vgvQWe3XCz3gIeFDm/HnTIbj6UGmg/+t63MyGU2n5js=
github.com/go-playground/validator/v10 v10.14.0/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY= github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I= github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM= github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE= github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/goccy/go-json v0.10.2 h1:CrxCmQqYDkv1z7lO7Wbh2HN93uovUHgrECaO5ZrCXAU=
github.com/goccy/go-json v0.10.2/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk= github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA= github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
@ -113,6 +86,8 @@ github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keL
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I= github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg= github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0= github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
github.com/golang-jwt/jwt/v5 v5.0.0 h1:1n1XNM9hk7O9mnQoNBGolZvzebBQ7p93ULHRc28XJUE=
github.com/golang-jwt/jwt/v5 v5.0.0/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
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/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI= github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo= github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
@ -143,8 +118,11 @@ github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU= github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg= github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I= github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo= github.com/google/safetext v0.0.0-20240104143208-7a7d9b3d812f h1:o2yGZLlsOj5H5uvtQNEdi6DeA0GbUP3lm0gWW5RvY0s=
github.com/google/safetext v0.0.0-20240104143208-7a7d9b3d812f/go.mod h1:H3K1Iu/utuCfa10JO+GsmKUYSWi7ug57Rk6GaDRHaaQ=
github.com/google/uuid v1.5.0 h1:1p67kYwdtXjb0gL0BPiP1Av9wiZPo5A8z2cWkTZ+eyU=
github.com/google/uuid v1.5.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
github.com/googollee/go-socket.io v1.7.0 h1:ODcQSAvVIPvKozXtUGuJDV3pLwdpBLDs1Uoq/QHIlY8= github.com/googollee/go-socket.io v1.7.0 h1:ODcQSAvVIPvKozXtUGuJDV3pLwdpBLDs1Uoq/QHIlY8=
github.com/googollee/go-socket.io v1.7.0/go.mod h1:0vGP8/dXR9SZUMMD4+xxaGo/lohOw3YWMh2WRiWeKxg= github.com/googollee/go-socket.io v1.7.0/go.mod h1:0vGP8/dXR9SZUMMD4+xxaGo/lohOw3YWMh2WRiWeKxg=
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI= github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
@ -172,30 +150,25 @@ github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHm
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE= github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A= github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs= github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
github.com/klauspost/compress v1.16.5 h1:IFV2oUNUzZaz+XyusxpLzpzS8Pt5rh0Z16For/djlyI= github.com/klauspost/compress v1.16.7 h1:2mk3MPGNzKyxErAw8YaohYh69+pa4sIQSC0fPGCFR9I=
github.com/klauspost/compress v1.16.5/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE= github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek= github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE= github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs= github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo= github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI= github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE= github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk= github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ= github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI= github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY= github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE= github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M= github.com/labstack/echo-jwt/v4 v4.2.0 h1:odSISV9JgcSCuhgQSV/6Io3i7nUmfM/QkBeR5GVJj5c=
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k= github.com/labstack/echo-jwt/v4 v4.2.0/go.mod h1:MA2RqdXdEn4/uEglx0HcUOgQSyBaTh5JcaHIan3biwU=
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8= github.com/labstack/echo/v4 v4.12.0 h1:IKpw49IMryVB2p1a4dzwlhP1O2Tf2E0Ir/450lH+kI0=
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM= github.com/labstack/echo/v4 v4.12.0/go.mod h1:UP9Cr2DJXbOK3Kr9ONYzNowSh7HP0aG0ShAyycHSJvM=
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY= github.com/labstack/gommon v0.4.2 h1:F8qTUNXgG1+6WQmqoUWnz8WiEU60mXVVw0P4ht1WRA0=
github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q= github.com/labstack/gommon v0.4.2/go.mod h1:QlUFxVM+SNXhDL/Z7YhocGIBYOiwB0mXm1+1bAPHPyU=
github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I= github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de h1:V53FWzU6KAZVi1tPp5UIsMoUWJ2/PNwYIDXnu7QuBCE= github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de h1:V53FWzU6KAZVi1tPp5UIsMoUWJ2/PNwYIDXnu7QuBCE=
github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE= github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
@ -205,10 +178,8 @@ github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc= github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
github.com/maruel/natural v1.1.0 h1:2z1NgP/Vae+gYrtC0VuvrTJ6U35OuyUqDdfluLqMWuQ= github.com/maruel/natural v1.1.0 h1:2z1NgP/Vae+gYrtC0VuvrTJ6U35OuyUqDdfluLqMWuQ=
github.com/maruel/natural v1.1.0/go.mod h1:eFVhYCcUOfZFxXoDZam8Ktya72wa79fNC3lc/leA0DQ= github.com/maruel/natural v1.1.0/go.mod h1:eFVhYCcUOfZFxXoDZam8Ktya72wa79fNC3lc/leA0DQ=
github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA= github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM= github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY= github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y= github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
@ -232,15 +203,11 @@ github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9l
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0= github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc= github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ= github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
github.com/pelletier/go-toml/v2 v2.0.8 h1:0ctb6s9mE31h0/lhu+J6OPmVeDxJn+kYnJc2jZR9tGQ=
github.com/pelletier/go-toml/v2 v2.0.8/go.mod h1:vuYfssBdrU2XDZ9bYydBu6t+6a6PYNcZljzZR9VXg+4=
github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw= github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw=
github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw= github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc= github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4= github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4= github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0= github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM= github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
@ -253,11 +220,8 @@ github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo= github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs= github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro= github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc= github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97 h1:3RPlVWzZ/PDqmVuf/FKHARG5EMid/tl7cv54Sw/QRVY=
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE= github.com/rogpeppe/go-internal v1.10.1-0.20230524175051-ec119421bb97/go.mod h1:ddIwULY96R17DhadqLgMfk9H9tvdUzkipdSkR5nkCZA=
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
github.com/rogpeppe/go-internal v1.10.0 h1:TMyTOH3F/DB16zRVcYyreMH6GnZZrwQVAoYjRBZyWFQ=
github.com/rogpeppe/go-internal v1.10.0/go.mod h1:UQnix2H7Ngw/k4C5ijL5+65zddjncjaFoBhdsK/akog=
github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM= github.com/samber/lo v1.38.1 h1:j2XEAqXKb09Am4ebOg31SpvzUTTs6EN3VfgeLUhPdXM=
github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA= github.com/samber/lo v1.38.1/go.mod h1:+m/ZKRl6ClXCE2Lgf3MsQlWfh4bn1bz6CXEOxnEXnEA=
github.com/shirou/gopsutil/v3 v3.23.2 h1:PAWSuiAszn7IhPMBtXsbSCafej7PqUOvY6YywlQUExU= github.com/shirou/gopsutil/v3 v3.23.2 h1:PAWSuiAszn7IhPMBtXsbSCafej7PqUOvY6YywlQUExU=
@ -270,17 +234,15 @@ github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSS
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo= github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI= github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA= github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
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/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg= github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU= github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4= github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
github.com/stretchr/testify v1.8.3/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
github.com/stretchr/testify v1.8.4 h1:CcVxjf3Q8PM0mHUKJCdn+eZZtm5yQwehR5yeSVQQcUk= github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
github.com/stretchr/testify v1.8.4/go.mod h1:sz/lmYIOXD/1dqDmKjjqLyZ2RngseejIcXlSw2iwfAo= github.com/tidwall/gjson v1.17.0 h1:/Jocvlh98kcTfpN2+JzGQWQcqrPQwDrVEMApx/M5ZwM=
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= github.com/tidwall/gjson v1.17.0/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
@ -290,8 +252,6 @@ github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+Kd
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI= github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms= github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4= github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M= github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY= github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU= github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
@ -302,7 +262,6 @@ github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14= github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw= github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc= github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo= github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQD0Loo=
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ= github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo= github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
@ -319,16 +278,12 @@ go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y= go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60= go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg= go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
golang.org/x/crypto v0.14.0 h1:wBqGXzWJW6m1XrIKlAH0Hs1JJ7+9KBwnIO8v66Q9cHc= golang.org/x/crypto v0.23.0 h1:dIJU/v2J8Mdglj/8rJ6UUOM3Zc9zLZxVZwwxMooUSAI=
golang.org/x/crypto v0.14.0/go.mod h1:MVFd36DqK4CsrnJYDkBA3VC4m2GkXAM0PvzMCn4JQf4= golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1 h1:MGwJjxBy0HJshjDNfLsYO8xppfqWlA5ZT9OhtUUhTNw=
golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc= golang.org/x/exp v0.0.0-20230713183714-613f0c0eb8a1/go.mod h1:FXUEEKJgO7OQYeo8N01OfiKP8RXMtf6e8aTskBGqWdc=
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0= golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
@ -351,8 +306,8 @@ golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qx
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c= golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk= golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs= golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
golang.org/x/net v0.17.0 h1:pVaXccu2ozPjCXewfr1S7xza/zcXTity9cCdXQYSjIM= golang.org/x/net v0.25.0 h1:d/OCCoBEUq33pjydKrGQhw7IlUPI2Oylr+8qLx49kac=
golang.org/x/net v0.17.0/go.mod h1:NxSsAGuq816PNPmqtQdLE42eU2Fs7NoRIZrHJAlaCOE= golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U= golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g= golang.org/x/oauth2 v0.7.0 h1:qe6s0zUXlPX80/dITx3440hWZ7GwMwgDDyrSGTPJG/g=
golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4= golang.org/x/oauth2 v0.7.0/go.mod h1:hPLQkd9LyjfXTiRohC/41GhcFqxisoUQ99sCUOHO9x4=
@ -373,12 +328,7 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
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-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
@ -387,12 +337,13 @@ golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.14.0 h1:Vz7Qs629MkJkGyHxUlRHizWJRG2j8fbQKjELVSNhy7Q= golang.org/x/sys v0.20.0 h1:Od9JTbYCk261bKm4M/mw7AklTlFYIa0bIp9BgSm1S8Y=
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA= golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
golang.org/x/term v0.13.0 h1:bb+I9cTfFazGW51MZqBVmZy7+JEJMouUHTUSKVQLBek= golang.org/x/term v0.20.0 h1:VnkxpohqXaOBYJtBmEppKUG6mXpi+4O6purfc2+sMhw=
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ= golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk= golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
@ -400,10 +351,10 @@ golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8= golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
golang.org/x/text v0.13.0 h1:ablQoSUd0tRdKxZewP80B+BaqeKJuVhuRxj/dkrun3k= golang.org/x/text v0.15.0 h1:h1V/4gjBv8v9cjcR6+AR5+/cIYK5N/WAgiv4xlsEtAk=
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE= golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4= golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ= golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
@ -418,14 +369,12 @@ google.golang.org/appengine v1.6.7 h1:FZR1q0exgwxzPzp/aF+VccGrSfxfPpkBqjIIEq3ru6
google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc= google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng= google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I= google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0= gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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-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/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc= gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc= gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI= gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
@ -435,7 +384,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-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA= gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM= gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
@ -451,4 +399,5 @@ modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU= modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
modernc.org/sqlite v1.21.2 h1:ixuUG0QS413Vfzyx6FWx6PYTmHaOegTY+hjzhn7L+a0= modernc.org/sqlite v1.21.2 h1:ixuUG0QS413Vfzyx6FWx6PYTmHaOegTY+hjzhn7L+a0=
modernc.org/sqlite v1.21.2/go.mod h1:cxbLkB5WS32DnQqeH4h4o1B0eMr8W/y8/RGuxQ3JsC0= modernc.org/sqlite v1.21.2/go.mod h1:cxbLkB5WS32DnQqeH4h4o1B0eMr8W/y8/RGuxQ3JsC0=
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4= mvdan.cc/sh/v3 v3.7.0 h1:lSTjdP/1xsddtaKfGg7Myu7DnlHItd3/M2tomOcNNBg=
mvdan.cc/sh/v3 v3.7.0/go.mod h1:K2gwkaesF/D7av7Kxl0HbF5kGOd2ArupNTX3X44+8l8=

View File

@ -13,6 +13,7 @@ import (
"time" "time"
"github.com/IceWhaleTech/CasaOS-Common/model" "github.com/IceWhaleTech/CasaOS-Common/model"
"github.com/IceWhaleTech/CasaOS-Common/utils/command"
"github.com/IceWhaleTech/CasaOS-Common/utils/constants" "github.com/IceWhaleTech/CasaOS-Common/utils/constants"
"github.com/IceWhaleTech/CasaOS-Common/utils/logger" "github.com/IceWhaleTech/CasaOS-Common/utils/logger"
@ -22,7 +23,6 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/cache" "github.com/IceWhaleTech/CasaOS/pkg/cache"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/sqlite" "github.com/IceWhaleTech/CasaOS/pkg/sqlite"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/route" "github.com/IceWhaleTech/CasaOS/route"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
@ -154,7 +154,6 @@ func main() {
Path: apiPath, Path: apiPath,
Target: "http://" + listener.Addr().String(), Target: "http://" + listener.Addr().String(),
}) })
if err != nil { if err != nil {
fmt.Println("err", err) fmt.Println("err", err)
panic(err) panic(err)

View File

@ -1,159 +0,0 @@
package command
import (
"bufio"
"fmt"
"io/ioutil"
"os"
"os/exec"
"path/filepath"
"strings"
)
func OnlyExec(cmdStr string) {
cmd := exec.Command("/bin/bash", "-c", cmdStr)
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println(err)
return
}
defer stdout.Close()
if err := cmd.Start(); err != nil {
fmt.Println(err)
return
}
if err := cmd.Wait(); err != nil {
fmt.Println(err)
}
}
func ExecResultStrArray(cmdStr string) []string {
cmd := exec.Command("/bin/bash", "-c", cmdStr)
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println(err)
return nil
}
defer stdout.Close()
if err = cmd.Start(); err != nil {
fmt.Println(err)
return nil
}
// str, err := ioutil.ReadAll(stdout)
networklist := []string{}
outputBuf := bufio.NewReader(stdout)
for {
output, _, err := outputBuf.ReadLine()
if err != nil {
if err.Error() != "EOF" {
fmt.Printf("Error :%s\n", err)
}
break
}
networklist = append(networklist, string(output))
}
if err := cmd.Wait(); err != nil {
fmt.Println(err)
}
return networklist
}
func ExecResultStr(cmdStr string) string {
cmd := exec.Command("/bin/bash", "-c", cmdStr)
println(cmd.String())
stdout, err := cmd.StdoutPipe()
if err != nil {
fmt.Println(err)
return ""
}
defer stdout.Close()
if err := cmd.Start(); err != nil {
fmt.Println(err)
return ""
}
str, err := ioutil.ReadAll(stdout)
if err != nil {
fmt.Println(err)
return ""
}
if err := cmd.Wait(); err != nil {
fmt.Println(err)
}
return string(str)
}
// 执行 lsblk 命令
func ExecLSBLK() []byte {
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
if err != nil {
fmt.Println("lsblk", err)
return nil
}
return output
}
// 执行 lsblk 命令
func ExecLSBLKByPath(path string) []byte {
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
if err != nil {
fmt.Println("lsblk", err)
return nil
}
return output
}
func ExecuteScripts(scriptDirectory string) {
if _, err := os.Stat(scriptDirectory); os.IsNotExist(err) {
fmt.Printf("No post-start scripts at %s\n", scriptDirectory)
return
}
files, err := os.ReadDir(scriptDirectory)
if err != nil {
fmt.Printf("Failed to read from script directory %s: %s\n", scriptDirectory, err.Error())
return
}
for _, file := range files {
if file.IsDir() {
continue
}
scriptFilepath := filepath.Join(scriptDirectory, file.Name())
f, err := os.Open(scriptFilepath)
if err != nil {
fmt.Printf("Failed to open script file %s: %s\n", scriptFilepath, err.Error())
continue
}
f.Close()
scanner := bufio.NewScanner(f)
scanner.Scan()
shebang := scanner.Text()
interpreter := "/bin/sh"
if strings.HasPrefix(shebang, "#!") {
interpreter = shebang[2:]
}
cmd := exec.Command(interpreter, scriptFilepath)
fmt.Printf("Executing post-start script %s using %s\n", scriptFilepath, interpreter)
cmd.Stdout = os.Stdout
cmd.Stderr = os.Stderr
err = cmd.Run()
if err != nil {
fmt.Printf("Failed to execute post-start script %s: %s\n", scriptFilepath, err.Error())
}
}
fmt.Println("Finished executing post-start scripts.")
}

View File

@ -1,33 +0,0 @@
package command_test
import (
"os"
"testing"
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"go.uber.org/goleak"
"gotest.tools/assert"
)
func TestExecuteScripts(t *testing.T) {
goleak.VerifyNone(t)
// make a temp directory
tmpDir, err := os.MkdirTemp("", "casaos-test-*")
assert.NilError(t, err)
defer os.RemoveAll(tmpDir)
command.ExecuteScripts(tmpDir)
// create a sample script under tmpDir
script := tmpDir + "/test.sh"
f, err := os.Create(script)
assert.NilError(t, err)
defer f.Close()
// write a sample script
_, err = f.WriteString("#!/bin/bash\necho 123")
assert.NilError(t, err)
command.ExecuteScripts(tmpDir)
}

View File

@ -0,0 +1,11 @@
package utils
import "github.com/labstack/echo/v4"
func DefaultPostForm(ctx echo.Context, key, defaultValue string) string {
value := ctx.Request().Form.Get(key)
if value == "" {
return defaultValue
}
return value
}

View File

@ -0,0 +1,11 @@
package utils
import "github.com/labstack/echo/v4"
func DefaultQuery(ctx echo.Context, key string, defaultValue string) string {
if value := ctx.QueryParam(key); value != "" {
return value
}
return defaultValue
}

View File

@ -179,7 +179,7 @@ func CreateFileAndWriteContent(path string, content string) error {
return nil return nil
} }
// IsNotExistMkDir create a directory if it does not exist // IsNotExistCreateFile create a file if it does not exist
func IsNotExistCreateFile(src string) error { func IsNotExistCreateFile(src string) error {
if notExist := CheckNotExist(src); notExist { if notExist := CheckNotExist(src); notExist {
if err := CreateFile(src); err != nil { if err := CreateFile(src); err != nil {

View File

@ -2,50 +2,68 @@ package route
import ( import (
"crypto/ecdsa" "crypto/ecdsa"
"os" "net/http"
"strconv"
"github.com/IceWhaleTech/CasaOS-Common/external" "github.com/IceWhaleTech/CasaOS-Common/external"
"github.com/IceWhaleTech/CasaOS-Common/middleware"
"github.com/IceWhaleTech/CasaOS-Common/utils/jwt" "github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
"github.com/IceWhaleTech/CasaOS/common" "github.com/IceWhaleTech/CasaOS/common"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
v1 "github.com/IceWhaleTech/CasaOS/route/v1" v1 "github.com/IceWhaleTech/CasaOS/route/v1"
"github.com/labstack/echo/v4"
"github.com/gin-contrib/gzip" echo_middleware "github.com/labstack/echo/v4/middleware"
"github.com/gin-gonic/gin"
) )
func InitV1Router() *gin.Engine { func InitV1Router() http.Handler {
ginMode := gin.ReleaseMode e := echo.New()
if config.ServerInfo.RunMode != "" {
ginMode = config.ServerInfo.RunMode
}
if os.Getenv(gin.EnvGinMode) != "" {
ginMode = os.Getenv(gin.EnvGinMode)
}
gin.SetMode(ginMode)
r := gin.New() e.Use((echo_middleware.CORSWithConfig(echo_middleware.CORSConfig{
r.Use(gin.Recovery()) AllowOrigins: []string{"*"},
r.Use(middleware.Cors()) AllowMethods: []string{echo.POST, echo.GET, echo.OPTIONS, echo.PUT, echo.DELETE},
r.Use(gzip.Gzip(gzip.DefaultCompression)) AllowHeaders: []string{echo.HeaderAuthorization, echo.HeaderContentLength, echo.HeaderXCSRFToken, echo.HeaderContentType, echo.HeaderAccessControlAllowOrigin, echo.HeaderAccessControlAllowHeaders, echo.HeaderAccessControlAllowMethods, echo.HeaderConnection, echo.HeaderOrigin, echo.HeaderXRequestedWith},
if ginMode != gin.ReleaseMode { ExposeHeaders: []string{echo.HeaderContentLength, echo.HeaderAccessControlAllowOrigin, echo.HeaderAccessControlAllowHeaders},
r.Use(middleware.WriteLog()) MaxAge: 172800,
} AllowCredentials: true,
})))
e.Use(echo_middleware.Gzip())
e.Use(echo_middleware.Recover())
e.Use(echo_middleware.Logger())
r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug e.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug
r.GET("/v1/sys/version/check", v1.GetSystemCheckVersion) e.GET("/v1/sys/version/check", v1.GetSystemCheckVersion)
r.GET("/v1/sys/version/current", func(ctx *gin.Context) { e.GET("/v1/sys/version/current", func(ctx echo.Context) error {
ctx.String(200, common.VERSION) return ctx.String(200, common.VERSION)
}) })
r.GET("/ping", func(ctx *gin.Context) { e.GET("/ping", func(ctx echo.Context) error {
ctx.String(200, "pong") return ctx.String(200, "pong")
}) })
r.GET("/v1/recover/:type", v1.GetRecoverStorage) e.GET("/v1/recover/:type", v1.GetRecoverStorage)
v1Group := r.Group("/v1") v1Group := e.Group("/v1")
// r.Any("/v1/test", v1.CheckNetwork) // e.Any("/v1/test", v1.CheckNetwork)
v1Group.Use(jwt.ExceptLocalhost(func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) })) v1Group.Use(echo_middleware.JWTWithConfig(echo_middleware.JWTConfig{
Skipper: func(c echo.Context) bool {
return c.RealIP() == "::1" || c.RealIP() == "127.0.0.1"
},
ParseTokenFunc: func(token string, c echo.Context) (interface{}, error) {
valid, claims, err := jwt.Validate(token, func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) })
if err != nil || !valid {
return nil, echo.ErrUnauthorized
}
c.Request().Header.Set("user_id", strconv.Itoa(claims.ID))
return claims, nil
},
TokenLookupFuncs: []echo_middleware.ValuesExtractor{
func(ctx echo.Context) ([]string, error) {
if len(ctx.Request().Header.Get(echo.HeaderAuthorization)) > 0 {
return []string{ctx.Request().Header.Get(echo.HeaderAuthorization)}, nil
}
return []string{ctx.QueryParam("token")}, nil
},
},
}))
{ {
v1SysGroup := v1Group.Group("/sys") v1SysGroup := v1Group.Group("/sys")
@ -98,7 +116,7 @@ func InitV1Router() *gin.Engine {
v1FileGroup.GET("/content", v1.GetFilerContent) // file/read v1FileGroup.GET("/content", v1.GetFilerContent) // file/read
// File uploads need to be handled separately, and will not be modified here // File uploads need to be handled separately, and will not be modified here
//v1FileGroup.POST("/upload", v1.PostFileUpload) // v1FileGroup.POST("/upload", v1.PostFileUpload)
v1FileGroup.POST("/upload", v1.PostFileUpload) v1FileGroup.POST("/upload", v1.PostFileUpload)
v1FileGroup.GET("/upload", v1.GetFileUpload) v1FileGroup.GET("/upload", v1.GetFileUpload)
// v1FileGroup.GET("/download", v1.UserFileDownloadCommonService) // v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
@ -171,7 +189,6 @@ func InitV1Router() *gin.Engine {
v1OtherGroup.Use() v1OtherGroup.Use()
{ {
v1OtherGroup.GET("/search", v1.GetSearchResult) v1OtherGroup.GET("/search", v1.GetSearchResult)
} }
v1ZerotierGroup := v1Group.Group("/zt") v1ZerotierGroup := v1Group.Group("/zt")
v1ZerotierGroup.Use() v1ZerotierGroup.Use()
@ -180,5 +197,5 @@ func InitV1Router() *gin.Engine {
} }
} }
return r return e
} }

View File

@ -11,33 +11,14 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper" "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/labstack/echo/v4"
"go.uber.org/zap" "go.uber.org/zap"
) )
func ListStorages(c *gin.Context) { func ListStorages(ctx echo.Context) error {
// var req model.PageReq
// if err := c.ShouldBind(&req); err != nil {
// c.JSON(common_err.SUCCESS, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()})
// return
// }
// req.Validate()
//logger.Info("ListStorages", zap.Any("req", req))
//storages, total, err := service.MyService.Storage().GetStorages(req.Page, req.PerPage)
// if err != nil {
// c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
// return
// }
// c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: model.PageResp{
// Content: storages,
// Total: total,
// }})
r, err := service.MyService.Storage().GetStorages() r, err := service.MyService.Storage().GetStorages()
if err != nil { if err != nil {
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
for i := 0; i < len(r.MountPoints); i++ { for i := 0; i < len(r.MountPoints); i++ {
@ -53,7 +34,6 @@ func ListStorages(c *gin.Context) {
r.MountPoints[i].Icon = dropbox.ICONURL r.MountPoints[i].Icon = dropbox.ICONURL
} }
if dataMap["type"] == "onedrive" { if dataMap["type"] == "onedrive" {
r.MountPoints[i].Icon = onedrive.ICONURL r.MountPoints[i].Icon = onedrive.ICONURL
} }
r.MountPoints[i].Name = dataMap["username"] r.MountPoints[i].Name = dataMap["username"]
@ -61,46 +41,39 @@ func ListStorages(c *gin.Context) {
list := []httper.MountPoint{} list := []httper.MountPoint{}
for _, v := range r.MountPoints { for _, v := range r.MountPoints {
list = append(list, httper.MountPoint{ list = append(list, httper.MountPoint(v))
Fs: v.Fs,
Icon: v.Icon,
MountPoint: v.MountPoint,
Name: v.Name,
})
} }
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
} }
func UmountStorage(c *gin.Context) { func UmountStorage(ctx echo.Context) error {
json := make(map[string]string) json := make(map[string]string)
c.ShouldBind(&json) ctx.Bind(&json)
mountPoint := json["mount_point"] mountPoint := json["mount_point"]
if mountPoint == "" { if mountPoint == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "mount_point is empty"}) return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "mount_point is empty"})
return
} }
err := service.MyService.Storage().UnmountStorage(mountPoint) err := service.MyService.Storage().UnmountStorage(mountPoint)
if err != nil { 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 ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
service.MyService.Storage().DeleteConfigByName(strings.ReplaceAll(mountPoint, "/mnt/", "")) service.MyService.Storage().DeleteConfigByName(strings.ReplaceAll(mountPoint, "/mnt/", ""))
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "success"}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "success"})
} }
func GetStorage(c *gin.Context) { func GetStorage(ctx echo.Context) error {
// idStr := ctx.QueryParam("id")
// idStr := c.Query("id")
// id, err := strconv.Atoi(idStr) // id, err := strconv.Atoi(idStr)
// if err != nil { // if err != nil {
// c.JSON(common_err.SUCCESS, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()}) // return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()})
// return // return
// } // }
// storage, err := service.MyService.Storage().GetStorageById(uint(id)) // storage, err := service.MyService.Storage().GetStorageById(uint(id))
// if err != nil { // if err != nil {
// c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()}) // return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
// return // return
// } // }
// c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: storage}) // return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: storage})
return nil
} }

View File

@ -6,10 +6,10 @@ import (
"github.com/IceWhaleTech/CasaOS/drivers/google_drive" "github.com/IceWhaleTech/CasaOS/drivers/google_drive"
"github.com/IceWhaleTech/CasaOS/drivers/onedrive" "github.com/IceWhaleTech/CasaOS/drivers/onedrive"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/gin-gonic/gin" "github.com/labstack/echo/v4"
) )
func ListDriverInfo(c *gin.Context) { func ListDriverInfo(ctx echo.Context) error {
list := []model.Drive{} list := []model.Drive{}
google := google_drive.GetConfig() google := google_drive.GetConfig()
@ -30,5 +30,5 @@ func ListDriverInfo(c *gin.Context) {
Icon: od.Icon, Icon: od.Icon,
AuthUrl: od.AuthUrl, AuthUrl: od.AuthUrl,
}) })
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
} }

View File

@ -20,15 +20,16 @@ import (
"github.com/IceWhaleTech/CasaOS-Common/utils/logger" "github.com/IceWhaleTech/CasaOS-Common/utils/logger"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/labstack/echo/v4"
"github.com/robfig/cron/v3" "github.com/robfig/cron/v3"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"github.com/IceWhaleTech/CasaOS/pkg/utils"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
"github.com/gin-gonic/gin"
"github.com/google/uuid" "github.com/google/uuid"
"go.uber.org/zap" "go.uber.org/zap"
@ -38,8 +39,9 @@ import (
type ListReq struct { type ListReq struct {
model.PageReq model.PageReq
Path string `json:"path" form:"path"` Path string `json:"path" form:"path"`
//Refresh bool `json:"refresh"` // Refresh bool `json:"refresh"`
} }
type ObjResp struct { type ObjResp struct {
Name string `json:"name"` Name string `json:"name"`
Size int64 `json:"size"` Size int64 `json:"size"`
@ -82,58 +84,53 @@ var (
// @Param path query string true "路径" // @Param path query string true "路径"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/read [get] // @Router /file/read [get]
func GetFilerContent(c *gin.Context) { func GetFilerContent(ctx echo.Context) error {
filePath := c.Query("path") filePath := ctx.QueryParam("path")
if len(filePath) == 0 { if len(filePath) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{ return ctx.JSON(common_err.CLIENT_ERROR, model.Result{
Success: common_err.INVALID_PARAMS, Success: common_err.INVALID_PARAMS,
Message: common_err.GetMsg(common_err.INVALID_PARAMS), Message: common_err.GetMsg(common_err.INVALID_PARAMS),
}) })
return
} }
if !file.Exists(filePath) { if !file.Exists(filePath) {
c.JSON(common_err.SERVICE_ERROR, model.Result{ return ctx.JSON(common_err.SERVICE_ERROR, model.Result{
Success: common_err.FILE_DOES_NOT_EXIST, Success: common_err.FILE_DOES_NOT_EXIST,
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST), Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
}) })
return
} }
// 文件读取任务是将文件内容读取到内存中。 // 文件读取任务是将文件内容读取到内存中。
info, err := ioutil.ReadFile(filePath) info, err := ioutil.ReadFile(filePath)
if err != nil { if err != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{ return ctx.JSON(common_err.SERVICE_ERROR, model.Result{
Success: common_err.FILE_READ_ERROR, Success: common_err.FILE_READ_ERROR,
Message: common_err.GetMsg(common_err.FILE_READ_ERROR), Message: common_err.GetMsg(common_err.FILE_READ_ERROR),
Data: err.Error(), Data: err.Error(),
}) })
return
} }
result := string(info) result := string(info)
c.JSON(common_err.SUCCESS, model.Result{ return ctx.JSON(common_err.SUCCESS, model.Result{
Success: common_err.SUCCESS, Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS), Message: common_err.GetMsg(common_err.SUCCESS),
Data: result, Data: result,
}) })
} }
func GetLocalFile(c *gin.Context) { func GetLocalFile(ctx echo.Context) error {
path := c.Query("path") path := ctx.QueryParam("path")
if len(path) == 0 { if len(path) == 0 {
c.JSON(http.StatusOK, model.Result{ return ctx.JSON(http.StatusOK, model.Result{
Success: common_err.INVALID_PARAMS, Success: common_err.INVALID_PARAMS,
Message: common_err.GetMsg(common_err.INVALID_PARAMS), Message: common_err.GetMsg(common_err.INVALID_PARAMS),
}) })
return
} }
if !file.Exists(path) { if !file.Exists(path) {
c.JSON(http.StatusOK, model.Result{ return ctx.JSON(http.StatusOK, model.Result{
Success: common_err.FILE_DOES_NOT_EXIST, Success: common_err.FILE_DOES_NOT_EXIST,
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST), Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
}) })
return
} }
c.File(path) return ctx.File(path)
} }
// @Summary download // @Summary download
@ -145,42 +142,39 @@ func GetLocalFile(c *gin.Context) {
// @Param files query string true "file list eg: filename1,filename2,filename3 " // @Param files query string true "file list eg: filename1,filename2,filename3 "
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/download [get] // @Router /file/download [get]
func GetDownloadFile(c *gin.Context) { func GetDownloadFile(ctx echo.Context) error {
t := c.Query("format") t := ctx.QueryParam("format")
files := c.Query("files") files := ctx.QueryParam("files")
if len(files) == 0 { if len(files) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{ return ctx.JSON(common_err.CLIENT_ERROR, model.Result{
Success: common_err.INVALID_PARAMS, Success: common_err.INVALID_PARAMS,
Message: common_err.GetMsg(common_err.INVALID_PARAMS), Message: common_err.GetMsg(common_err.INVALID_PARAMS),
}) })
return
} }
list := strings.Split(files, ",") list := strings.Split(files, ",")
for _, v := range list { for _, v := range list {
if !file.Exists(v) { if !file.Exists(v) {
c.JSON(common_err.SERVICE_ERROR, model.Result{ return ctx.JSON(common_err.SERVICE_ERROR, model.Result{
Success: common_err.FILE_DOES_NOT_EXIST, Success: common_err.FILE_DOES_NOT_EXIST,
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST), Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
}) })
return
} }
} }
c.Header("Content-Type", "application/octet-stream") ctx.Request().Header.Add("Content-Type", "application/octet-stream")
c.Header("Content-Transfer-Encoding", "binary") ctx.Request().Header.Add("Content-Transfer-Encoding", "binary")
c.Header("Cache-Control", "no-cache") ctx.Request().Header.Add("Cache-Control", "no-cache")
// handles only single files not folders and multiple files // handles only single files not folders and multiple files
if len(list) == 1 { if len(list) == 1 {
filePath := list[0] filePath := list[0]
info, err := os.Stat(filePath) info, err := os.Stat(filePath)
if err != nil { if err != nil {
c.JSON(http.StatusOK, model.Result{ return ctx.JSON(http.StatusOK, model.Result{
Success: common_err.FILE_DOES_NOT_EXIST, Success: common_err.FILE_DOES_NOT_EXIST,
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST), Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
}) })
return
} }
if !info.IsDir() { if !info.IsDir() {
@ -190,29 +184,26 @@ func GetDownloadFile(c *gin.Context) {
// 获取文件的名称 // 获取文件的名称
fileName := path.Base(filePath) fileName := path.Base(filePath)
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName)) ctx.Response().Header().Add("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
c.File(filePath) ctx.File(filePath)
return
} }
} }
extension, ar, err := file.GetCompressionAlgorithm(t) extension, ar, err := file.GetCompressionAlgorithm(t)
if err != nil { if err != nil {
c.JSON(common_err.CLIENT_ERROR, model.Result{ return ctx.JSON(common_err.CLIENT_ERROR, model.Result{
Success: common_err.INVALID_PARAMS, Success: common_err.INVALID_PARAMS,
Message: common_err.GetMsg(common_err.INVALID_PARAMS), Message: common_err.GetMsg(common_err.INVALID_PARAMS),
}) })
return
} }
err = ar.Create(c.Writer) err = ar.Create(ctx.Response().Writer)
if err != nil { if err != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{ return ctx.JSON(common_err.SERVICE_ERROR, model.Result{
Success: common_err.SERVICE_ERROR, Success: common_err.SERVICE_ERROR,
Message: common_err.GetMsg(common_err.SERVICE_ERROR), Message: common_err.GetMsg(common_err.SERVICE_ERROR),
Data: err.Error(), Data: err.Error(),
}) })
return
} }
defer ar.Close() defer ar.Close()
commonDir := file.CommonPrefix(filepath.Separator, list...) commonDir := file.CommonPrefix(filepath.Separator, list...)
@ -221,27 +212,27 @@ func GetDownloadFile(c *gin.Context) {
name := "_" + currentPath name := "_" + currentPath
name += extension name += extension
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name)) ctx.Request().Header.Add("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(name))
for _, fname := range list { for _, fname := range list {
err = file.AddFile(ar, fname, commonDir) err = file.AddFile(ar, fname, commonDir)
if err != nil { if err != nil {
log.Printf("Failed to archive %s: %v", fname, err) log.Printf("Failed to archive %s: %v", fname, err)
} }
} }
return nil
} }
func GetDownloadSingleFile(c *gin.Context) { func GetDownloadSingleFile(ctx echo.Context) error {
filePath := c.Query("path") filePath := ctx.QueryParam("path")
if len(filePath) == 0 { if len(filePath) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{ return ctx.JSON(common_err.CLIENT_ERROR, model.Result{
Success: common_err.INVALID_PARAMS, Success: common_err.INVALID_PARAMS,
Message: common_err.GetMsg(common_err.INVALID_PARAMS), Message: common_err.GetMsg(common_err.INVALID_PARAMS),
}) })
return
} }
fileName := path.Base(filePath) fileName := path.Base(filePath)
// c.Header("Content-Disposition", "inline") // c.Header("Content-Disposition", "inline")
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName)) ctx.Request().Header.Add("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
fi, err := os.Open(filePath) fi, err := os.Open(filePath)
if err != nil { if err != nil {
@ -255,31 +246,28 @@ func GetDownloadSingleFile(c *gin.Context) {
kind, _ := filetype.Match(buffer) kind, _ := filetype.Match(buffer)
if kind != filetype.Unknown { if kind != filetype.Unknown {
c.Header("Content-Type", kind.MIME.Value) ctx.Request().Header.Add("Content-Type", kind.MIME.Value)
} }
node, err := os.Stat(filePath) node, err := os.Stat(filePath)
// Set the Last-Modified header to the timestamp // Set the Last-Modified header to the timestamp
c.Header("Last-Modified", node.ModTime().UTC().Format(http.TimeFormat)) ctx.Request().Header.Add("Last-Modified", node.ModTime().UTC().Format(http.TimeFormat))
knownSize := node.Size() >= 0 knownSize := node.Size() >= 0
if knownSize { if knownSize {
c.Header("Content-Length", strconv.FormatInt(node.Size(), 10)) ctx.Request().Header.Add("Content-Length", strconv.FormatInt(node.Size(), 10))
} }
http.ServeContent(c.Writer, c.Request, fileName, node.ModTime(), fi) http.ServeContent(ctx.Response().Writer, ctx.Request(), fileName, node.ModTime(), fi)
//http.ServeFile(c.Writer, c.Request, filePath)
defer fi.Close() defer fi.Close()
return
fileTmp, err := os.Open(filePath) fileTmp, err := os.Open(filePath)
if err != nil { if err != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{ return ctx.JSON(common_err.SERVICE_ERROR, model.Result{
Success: common_err.FILE_DOES_NOT_EXIST, Success: common_err.FILE_DOES_NOT_EXIST,
Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST), Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
}) })
return
} }
defer fileTmp.Close() defer fileTmp.Close()
c.File(filePath) return nil
} }
// @Summary 获取目录列表 // @Summary 获取目录列表
@ -290,17 +278,14 @@ func GetDownloadSingleFile(c *gin.Context) {
// @Param path query string false "路径" // @Param path query string false "路径"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/dirpath [get] // @Router /file/dirpath [get]
func DirPath(c *gin.Context) { func DirPath(ctx echo.Context) error {
var req ListReq var req ListReq
if err := c.ShouldBind(&req); err != nil { path := ctx.QueryParam("path")
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()}) req.Path = path
return
}
req.Validate() req.Validate()
info, err := service.MyService.System().GetDirPath(req.Path) info, err := service.MyService.System().GetDirPath(req.Path)
if err != nil { 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 ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
shares := service.MyService.Shares().GetSharesList() shares := service.MyService.Shares().GetSharesList()
sharesMap := make(map[string]string) sharesMap := make(map[string]string)
@ -308,7 +293,7 @@ func DirPath(c *gin.Context) {
sharesMap[v.Path] = fmt.Sprint(v.ID) sharesMap[v.Path] = fmt.Sprint(v.ID)
} }
// if len(info) <= (req.Page-1)*req.Size { // if len(info) <= (req.Page-1)*req.Size {
// c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "page out of range"}) // return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "page out of range"})
// return // return
// } // }
forEnd := req.Index * req.Size forEnd := req.Index * req.Size
@ -380,7 +365,7 @@ func DirPath(c *gin.Context) {
Index: req.Index, Index: req.Index,
Size: req.Size, Size: req.Size,
} }
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: flist}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: flist})
} }
// @Summary rename file or dir // @Summary rename file or dir
@ -392,23 +377,21 @@ func DirPath(c *gin.Context) {
// @Param newpath body 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(ctx echo.Context) error {
json := make(map[string]string) json := make(map[string]string)
c.ShouldBind(&json) ctx.Bind(&json)
op := json["old_path"] op := json["old_path"]
np := json["new_path"] np := json["new_path"]
if len(op) == 0 || len(np) == 0 { if len(op) == 0 || len(np) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
} }
mounted := service.IsMounted(op) mounted := service.IsMounted(op)
if mounted { if mounted {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.MOUNTED_DIRECTIORIES, Message: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES), Data: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES)}) return ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.MOUNTED_DIRECTIORIES, Message: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES), Data: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES)})
return
} }
success, err := service.MyService.System().RenameFile(op, np) success, err := service.MyService.System().RenameFile(op, np)
c.JSON(common_err.SUCCESS, model.Result{Success: success, Message: common_err.GetMsg(success), Data: err}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: success, Message: common_err.GetMsg(success), Data: err})
} }
// @Summary create folder // @Summary create folder
@ -419,22 +402,21 @@ func RenamePath(c *gin.Context) {
// @Param path body 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(ctx echo.Context) error {
json := make(map[string]string) json := make(map[string]string)
c.ShouldBind(&json) ctx.Bind(&json)
path := json["path"] path := json["path"]
var code int var code int
if len(path) == 0 { 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 ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
} }
// decodedPath, err := url.QueryUnescape(path) // decodedPath, err := url.QueryUnescape(path)
// if err != nil { // if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) // return ctx.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return // return
// } // }
code, _ = service.MyService.System().MkdirAll(path) code, _ = service.MyService.System().MkdirAll(path)
c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
} }
// @Summary create file // @Summary create file
@ -445,22 +427,21 @@ func MkdirAll(c *gin.Context) {
// @Param path body string true "path of folder (path need to url encode)" // @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(ctx echo.Context) error {
json := make(map[string]string) json := make(map[string]string)
c.ShouldBind(&json) ctx.Bind(&json)
path := json["path"] path := json["path"]
var code int var code int
if len(path) == 0 { 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 ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
} }
// decodedPath, err := url.QueryUnescape(path) // decodedPath, err := url.QueryUnescape(path)
// if err != nil { // if err != nil {
// c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) // return ctx.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return // return
// } // }
code, _ = service.MyService.System().CreateFile(path) code, _ = service.MyService.System().CreateFile(path)
c.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: code, Message: common_err.GetMsg(code)})
} }
// @Summary upload file // @Summary upload file
@ -472,17 +453,16 @@ func PostCreateFile(c *gin.Context) {
// @Param file formData file true "file" // @Param file formData file true "file"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/upload [get] // @Router /file/upload [get]
func GetFileUpload(c *gin.Context) { func GetFileUpload(ctx echo.Context) error {
relative := c.Query("relativePath") relative := ctx.QueryParam("relativePath")
fileName := c.Query("filename") fileName := ctx.QueryParam("filename")
chunkNumber := c.Query("chunkNumber") chunkNumber := ctx.QueryParam("chunkNumber")
totalChunks, _ := strconv.Atoi(c.DefaultQuery("totalChunks", "0")) totalChunks, _ := strconv.Atoi(utils.DefaultQuery(ctx, "totalChunks", "0"))
path := c.Query("path") path := ctx.QueryParam("path")
dirPath := "" dirPath := ""
hash := file.GetHashByContent([]byte(fileName)) hash := file.GetHashByContent([]byte(fileName))
if file.Exists(path + "/" + relative) { if file.Exists(path + "/" + relative) {
c.JSON(http.StatusConflict, model.Result{Success: http.StatusConflict, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)}) return ctx.JSON(http.StatusConflict, model.Result{Success: http.StatusConflict, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
return
} }
tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/" tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
if fileName != relative { if fileName != relative {
@ -492,11 +472,10 @@ 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: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)}) return ctx.JSON(200, model.Result{Success: 200, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
return
} }
c.JSON(204, model.Result{Success: 204, Message: common_err.GetMsg(common_err.SUCCESS)}) return ctx.JSON(204, model.Result{Success: 204, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary upload file // @Summary upload file
@ -508,21 +487,20 @@ func GetFileUpload(c *gin.Context) {
// @Param file formData file true "file" // @Param file formData file true "file"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/upload [post] // @Router /file/upload [post]
func PostFileUpload(c *gin.Context) { func PostFileUpload(ctx echo.Context) error {
f, _, _ := c.Request.FormFile("file") f, _, _ := ctx.Request().FormFile("file")
relative := c.PostForm("relativePath") relative := ctx.FormValue("relativePath")
fileName := c.PostForm("filename") fileName := ctx.FormValue("filename")
totalChunks, _ := strconv.Atoi(c.DefaultPostForm("totalChunks", "0")) totalChunks, _ := strconv.Atoi(utils.DefaultPostForm(ctx, "totalChunks", "0"))
chunkNumber := c.PostForm("chunkNumber") chunkNumber := ctx.FormValue("chunkNumber")
dirPath := "" dirPath := ""
path := c.PostForm("path") path := ctx.FormValue("path")
hash := file.GetHashByContent([]byte(fileName)) hash := file.GetHashByContent([]byte(fileName))
if len(path) == 0 { if len(path) == 0 {
logger.Error("path should not be empty") logger.Error("path should not be empty")
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) return ctx.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
} }
tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/" tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
@ -531,8 +509,7 @@ func PostFileUpload(c *gin.Context) {
tempDir += dirPath tempDir += dirPath
if err := file.MkDir(path + "/" + dirPath); err != nil { if err := file.MkDir(path + "/" + dirPath); err != nil {
logger.Error("error when trying to create `"+path+"/"+dirPath+"`", zap.Error(err)) logger.Error("error when trying to create `"+path+"/"+dirPath+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return ctx.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
} }
} }
@ -541,48 +518,41 @@ func PostFileUpload(c *gin.Context) {
if !file.CheckNotExist(tempDir + chunkNumber) { if !file.CheckNotExist(tempDir + chunkNumber) {
if err := file.RMDir(tempDir + chunkNumber); err != nil { if err := file.RMDir(tempDir + chunkNumber); err != nil {
logger.Error("error when trying to remove existing `"+tempDir+chunkNumber+"`", zap.Error(err)) logger.Error("error when trying to remove existing `"+tempDir+chunkNumber+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return ctx.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
} }
} }
if totalChunks > 1 { if totalChunks > 1 {
if err := file.IsNotExistMkDir(tempDir); err != nil { if err := file.IsNotExistMkDir(tempDir); err != nil {
logger.Error("error when trying to create `"+tempDir+"`", zap.Error(err)) logger.Error("error when trying to create `"+tempDir+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return ctx.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
} }
out, err := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0o644) out, err := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0o644)
if err != nil { if err != nil {
logger.Error("error when trying to open `"+tempDir+chunkNumber+"` for creation", zap.Error(err)) logger.Error("error when trying to open `"+tempDir+chunkNumber+"` for creation", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return ctx.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
} }
defer out.Close() defer out.Close()
if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
logger.Error("error when trying to write to `"+tempDir+chunkNumber+"`", zap.Error(err)) logger.Error("error when trying to write to `"+tempDir+chunkNumber+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return ctx.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
} }
fileNum, err := ioutil.ReadDir(tempDir) fileNum, err := ioutil.ReadDir(tempDir)
if err != nil { if err != nil {
logger.Error("error when trying to read number of files under `"+tempDir+"`", zap.Error(err)) logger.Error("error when trying to read number of files under `"+tempDir+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return ctx.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
} }
if totalChunks == len(fileNum) { if totalChunks == len(fileNum) {
if err := file.SpliceFiles(tempDir, path, totalChunks, 1); err != nil { if err := file.SpliceFiles(tempDir, path, totalChunks, 1); err != nil {
logger.Error("error when trying to splice files under `"+tempDir+"`", zap.Error(err)) logger.Error("error when trying to splice files under `"+tempDir+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return ctx.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
} }
go func() { go func() {
time.Sleep(11 * time.Second) time.Sleep(11 * time.Second)
if err := file.RMDir(tempDir); err != nil { if err := file.RMDir(tempDir); err != nil {
logger.Error("error when trying to remove `"+tempDir+"`", zap.Error(err)) logger.Error("error when trying to remove `"+tempDir+"`", zap.Error(err))
@ -593,57 +563,49 @@ func PostFileUpload(c *gin.Context) {
out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o644) out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o644)
if err != nil { if err != nil {
logger.Error("error when trying to open `"+path+"` for creation", zap.Error(err)) logger.Error("error when trying to open `"+path+"` for creation", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()}) return ctx.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
return
} }
defer out.Close() defer out.Close()
if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
logger.Error("error when trying to write to `"+path+"`", zap.Error(err)) logger.Error("error when trying to write to `"+path+"`", zap.Error(err))
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()}) return ctx.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
} }
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) return ctx.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
func PostFileOctet(c *gin.Context) { func PostFileOctet(ctx echo.Context) error {
content_length := ctx.Request().ContentLength
content_length := c.Request.ContentLength
if content_length <= 0 || content_length > 1024*1024*1024*2*1024 { if content_length <= 0 || content_length > 1024*1024*1024*2*1024 {
log.Printf("content_length error\n") log.Printf("content_length error\n")
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "content_length error"}) return ctx.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "content_length error"})
return
} }
content_type_, has_key := c.Request.Header["Content-Type"] content_type_, has_key := ctx.Request().Header["Content-Type"]
if !has_key { if !has_key {
log.Printf("Content-Type error\n") log.Printf("Content-Type error\n")
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Content-Type error"}) return ctx.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Content-Type error"})
return
} }
if len(content_type_) != 1 { if len(content_type_) != 1 {
log.Printf("Content-Type count error\n") log.Printf("Content-Type count error\n")
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Content-Type count error"}) return ctx.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Content-Type count error"})
return
} }
content_type := content_type_[0] content_type := content_type_[0]
const BOUNDARY string = "; boundary=" const BOUNDARY string = "; boundary="
loc := strings.Index(content_type, BOUNDARY) loc := strings.Index(content_type, BOUNDARY)
if loc == -1 { if loc == -1 {
log.Printf("Content-Type error, no boundary\n") log.Printf("Content-Type error, no boundary\n")
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Content-Type error, no boundary"}) return ctx.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Content-Type error, no boundary"})
return
} }
boundary := []byte(content_type[(loc + len(BOUNDARY)):]) boundary := []byte(content_type[(loc + len(BOUNDARY)):])
log.Printf("[%s]\n\n", boundary) log.Printf("[%s]\n\n", boundary)
read_data := make([]byte, 1024*24) read_data := make([]byte, 1024*24)
var read_total int = 0 var read_total int = 0
for { for {
file_header, file_data, err := file.ParseFromHead(read_data, read_total, append(boundary, []byte("\r\n")...), c.Request.Body) file_header, file_data, err := file.ParseFromHead(read_data, read_total, append(boundary, []byte("\r\n")...), ctx.Request().Body)
if err != nil { if err != nil {
log.Printf("%v", err) log.Printf("%v", err)
return
} }
log.Printf("file :%s\n", file_header) log.Printf("file :%s\n", file_header)
// //
@ -651,16 +613,14 @@ func PostFileOctet(c *gin.Context) {
f, err := os.OpenFile(file_header["path"]+"/"+file_header["filename"], os.O_WRONLY|os.O_CREATE, 0o644) f, err := os.OpenFile(file_header["path"]+"/"+file_header["filename"], os.O_WRONLY|os.O_CREATE, 0o644)
if err != nil { if err != nil {
log.Printf("create file fail:%v\n", err) log.Printf("create file fail:%v\n", err)
return
} }
f.Write(file_data) f.Write(file_data)
file_data = nil file_data = nil
temp_data, reach_end, err := file.ReadToBoundary(boundary, c.Request.Body, f) temp_data, reach_end, err := file.ReadToBoundary(boundary, ctx.Request().Body, f)
f.Close() f.Close()
if err != nil { if err != nil {
log.Printf("%v\n", err) log.Printf("%v\n", err)
return
} }
if reach_end { if reach_end {
break break
@ -670,7 +630,7 @@ func PostFileOctet(c *gin.Context) {
continue continue
} }
} }
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) return ctx.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary copy or move file // @Summary copy or move file
@ -681,17 +641,15 @@ func PostFileOctet(c *gin.Context) {
// @Param body body model.FileOperate true "type:move,copy" // @Param body body model.FileOperate true "type: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(ctx echo.Context) error {
list := model.FileOperate{} list := model.FileOperate{}
c.ShouldBind(&list) ctx.Bind(&list)
if len(list.Item) == 0 { 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 ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
} }
if list.To == list.Item[0].From[:strings.LastIndex(list.Item[0].From, "/")] { if list.To == list.Item[0].From[:strings.LastIndex(list.Item[0].From, "/")] {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SOURCE_DES_SAME, Message: common_err.GetMsg(common_err.SOURCE_DES_SAME)}) return ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SOURCE_DES_SAME, Message: common_err.GetMsg(common_err.SOURCE_DES_SAME)})
return
} }
var total int64 = 0 var total int64 = 0
@ -706,8 +664,7 @@ func PostOperateFileOrDir(c *gin.Context) {
if list.Type == "move" { if list.Type == "move" {
mounted := service.IsMounted(list.Item[i].From) mounted := service.IsMounted(list.Item[i].From)
if mounted { if mounted {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.MOUNTED_DIRECTIORIES, Message: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES), Data: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES)}) return ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.MOUNTED_DIRECTIORIES, Message: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES), Data: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES)})
return
} }
} }
} }
@ -726,7 +683,7 @@ func PostOperateFileOrDir(c *gin.Context) {
} }
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary delete file // @Summary delete file
@ -737,33 +694,30 @@ func PostOperateFileOrDir(c *gin.Context) {
// @Param body body string true "paths eg ["/a/b/c","/d/e/f"]" // @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(ctx echo.Context) error {
paths := []string{} paths := []string{}
c.ShouldBind(&paths) ctx.Bind(&paths)
if len(paths) == 0 { if len(paths) == 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
return
} }
// path := c.Query("path") // path := ctx.QueryParam("path")
// paths := strings.Split(path, ",") // paths := strings.Split(path, ",")
for _, v := range paths { for _, v := range paths {
mounted := service.IsMounted(v) mounted := service.IsMounted(v)
if mounted { if mounted {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.MOUNTED_DIRECTIORIES, Message: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES), Data: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES)}) return ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.MOUNTED_DIRECTIORIES, Message: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES), Data: common_err.GetMsg(common_err.MOUNTED_DIRECTIORIES)})
return
} }
} }
for _, v := range paths { for _, v := range paths {
err := os.RemoveAll(v) err := os.RemoveAll(v)
if err != nil { 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 ctx.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)}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary update file // @Summary update file
@ -775,34 +729,30 @@ func DeleteFile(c *gin.Context) {
// @Param content body 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(ctx echo.Context) error {
fi := model.FileUpdate{} fi := model.FileUpdate{}
c.ShouldBind(&fi) ctx.Bind(&fi)
// path := c.PostForm("path") // path := ctx.FormValue("path")
// content := c.PostForm("content") // content := ctx.FormValue("content")
if !file.Exists(fi.FilePath) { 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 ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
return
} }
// err := os.Remove(path) // err := os.Remove(path)
f, err := os.Stat(fi.FilePath) f, err := os.Stat(fi.FilePath)
if err != nil { if err != nil {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)}) return ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
return
} }
fm := f.Mode() fm := f.Mode()
if err != nil { 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 ctx.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
} }
os.OpenFile(fi.FilePath, os.O_CREATE, fm) os.OpenFile(fi.FilePath, os.O_CREATE, fm)
err = file.WriteToFullPath([]byte(fi.FileContent), fi.FilePath, fm) err = file.WriteToFullPath([]byte(fi.FileContent), fi.FilePath, fm)
if err != nil { 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 ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) return ctx.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
@ -814,38 +764,34 @@ func PutFileContent(c *gin.Context) {
// @Param type query string false "original,thumbnail" Enums(original,thumbnail) // @Param type query string false "original,thumbnail" Enums(original,thumbnail)
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /file/image [get] // @Router /file/image [get]
func GetFileImage(c *gin.Context) { func GetFileImage(ctx echo.Context) error {
t := c.Query("type") t := ctx.QueryParam("type")
path := c.Query("path") path := ctx.QueryParam("path")
if !file.Exists(path) { if !file.Exists(path) {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)}) return ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
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(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()}) return ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
c.Writer.WriteString(string(f)) ctx.Response().Writer.Write(f)
return
} }
f, err := os.Open(path) f, err := os.Open(path)
if err != nil { 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 ctx.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 f.Close() defer f.Close()
data, err := ioutil.ReadAll(f) data, err := ioutil.ReadAll(f)
if err != nil { 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 ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
c.Writer.WriteString(string(data)) ctx.Response().Writer.Write(data)
return nil
} }
func DeleteOperateFileOrDir(c *gin.Context) { func DeleteOperateFileOrDir(ctx echo.Context) error {
id := c.Param("id") id := ctx.Param("id")
if id == "0" { if id == "0" {
service.FileQueue = sync.Map{} service.FileQueue = sync.Map{}
service.OpStrArr = []string{} service.OpStrArr = []string{}
@ -863,30 +809,29 @@ func DeleteOperateFileOrDir(c *gin.Context) {
} }
go service.MyService.Notify().SendFileOperateNotify(true) go service.MyService.Notify().SendFileOperateNotify(true)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
func GetSize(c *gin.Context) {
func GetSize(ctx echo.Context) error {
json := make(map[string]string) json := make(map[string]string)
c.ShouldBind(&json) ctx.Bind(&json)
path := json["path"] path := json["path"]
size, err := file.GetFileOrDirSize(path) size, err := file.GetFileOrDirSize(path)
if err != nil { 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 ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: size}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: size})
} }
func GetFileCount(c *gin.Context) { func GetFileCount(ctx echo.Context) error {
json := make(map[string]string) json := make(map[string]string)
c.ShouldBind(&json) ctx.Bind(&json)
path := json["path"] path := json["path"]
list, err := ioutil.ReadDir(path) list, err := ioutil.ReadDir(path)
if err != nil { 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 ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: len(list)}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: len(list)})
} }
type CenterHandler struct { type CenterHandler struct {
@ -919,17 +864,16 @@ type PeerModel struct {
RtcSupported bool `json:"rtcSupported"` RtcSupported bool `json:"rtcSupported"`
} }
func ConnectWebSocket(c *gin.Context) { func ConnectWebSocket(ctx echo.Context) error {
peerId := c.Query("peer") peerId := ctx.QueryParam("peer")
writer := c.Writer writer := ctx.Response().Writer
request := c.Request request := ctx.Request()
key := uuid.NewString() key := uuid.NewString()
//peerModel := service.MyService.Peer().GetPeerByUserAgent(c.Request.UserAgent()) // peerModel := service.MyService.Peer().GetPeerByUserAgent(ctx.Request().UserAgent())
peerModel := model2.PeerDriveDBModel{} peerModel := model2.PeerDriveDBModel{}
name := service.GetName(request) name := service.GetName(request)
if conn, err = upgraderFile.Upgrade(writer, request, writer.Header()); err != nil { if conn, err = upgraderFile.Upgrade(writer, request, writer.Header()); err != nil {
log.Println(err) log.Println(err)
return
} }
client := &Client{handler: &handler, conn: conn, send: make(chan []byte, 256), ID: service.GetPeerId(request, key), IP: service.GetIP(request), Name: name, RtcSupported: true, TimerId: 0, LastBeat: time.Now()} client := &Client{handler: &handler, conn: conn, send: make(chan []byte, 256), ID: service.GetPeerId(request, key), IP: service.GetIP(request), Name: name, RtcSupported: true, TimerId: 0, LastBeat: time.Now()}
if peerId != "" || len(peerModel.ID) > 0 { if peerId != "" || len(peerModel.ID) > 0 {
@ -942,7 +886,7 @@ func ConnectWebSocket(c *gin.Context) {
client.Name = service.GetNameByDB(peerModel) client.Name = service.GetNameByDB(peerModel)
} }
} }
var list = service.MyService.Peer().GetPeers() list := service.MyService.Peer().GetPeers()
if len(peerModel.ID) == 0 { if len(peerModel.ID) == 0 {
peerModel.ID = key peerModel.ID = key
peerModel.DisplayName = name.DisplayName peerModel.DisplayName = name.DisplayName
@ -950,7 +894,7 @@ func ConnectWebSocket(c *gin.Context) {
peerModel.Model = name.Model peerModel.Model = name.Model
peerModel.OS = name.OS peerModel.OS = name.OS
peerModel.Browser = name.Browser peerModel.Browser = name.Browser
peerModel.UserAgent = c.Request.UserAgent() peerModel.UserAgent = ctx.Request().UserAgent()
peerModel.IP = client.IP peerModel.IP = client.IP
service.MyService.Peer().CreatePeer(&peerModel) service.MyService.Peer().CreatePeer(&peerModel)
list = append(list, peerModel) list = append(list, peerModel)
@ -994,7 +938,7 @@ func ConnectWebSocket(c *gin.Context) {
for _, v := range handler.clients { for _, v := range handler.clients {
v.send <- pby v.send <- pby
} }
//client.handler.broadcast <- pby // client.handler.broadcast <- pby
clients := []PeerModel{} clients := []PeerModel{}
for _, v := range client.handler.clients { for _, v := range client.handler.clients {
if _, ok := handler.clients[v.ID]; ok { if _, ok := handler.clients[v.ID]; ok {
@ -1027,31 +971,34 @@ func ConnectWebSocket(c *gin.Context) {
// 每个 client 都挂起 2 个新的协程,监控读、写状态 // 每个 client 都挂起 2 个新的协程,监控读、写状态
go client.writePump() go client.writePump()
go client.readPump() go client.readPump()
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
var handler = CenterHandler{broadcast: make(chan []byte), var handler = CenterHandler{
broadcast: make(chan []byte),
register: make(chan *Client), register: make(chan *Client),
unregister: make(chan *Client), unregister: make(chan *Client),
clients: make(map[string]*Client)} clients: make(map[string]*Client),
}
func init() { func init() {
// 起个协程跑起来,监听注册、注销、消息 3 个 channel // 起个协程跑起来,监听注册、注销、消息 3 个 channel
go handler.monitoring() go handler.monitoring()
crontab := cron.New(cron.WithSeconds()) //精确到秒 crontab := cron.New(cron.WithSeconds()) // 精确到秒
//定义定时器调用的任务函数 // 定义定时器调用的任务函数
task := func() { task := func() {
handler.broadcast <- []byte(`{"type":"ping"}`) handler.broadcast <- []byte(`{"type":"ping"}`)
} }
//定时任务 // 定时任务
spec := "*/30 * * * * ?" //cron表达式每五秒一次 spec := "*/30 * * * * ?" // cron表达式每五秒一次
// 添加定时任务, // 添加定时任务,
crontab.AddFunc(spec, task) crontab.AddFunc(spec, task)
// 启动定时器 // 启动定时器
crontab.Start() crontab.Start()
} }
func (c *Client) writePump() { func (c *Client) writePump() {
defer func() { defer func() {
c.handler.unregister <- c c.handler.unregister <- c
@ -1106,7 +1053,7 @@ func (c *Client) readPump() {
// otherBy, err := json.Marshal(other) // otherBy, err := json.Marshal(other)
// fmt.Println(err) // fmt.Println(err)
c.handler.broadcast <- []byte(`{"type":"peer-left","peerId":"` + c.ID + `"}`) c.handler.broadcast <- []byte(`{"type":"peer-left","peerId":"` + c.ID + `"}`)
//c.handler.broadcast <- otherBy // c.handler.broadcast <- otherBy
break break
} else if t.String() == "pong" { } else if t.String() == "pong" {
c.LastBeat = time.Now() c.LastBeat = time.Now()
@ -1131,6 +1078,7 @@ func (c *Client) readPump() {
c.handler.broadcast <- message c.handler.broadcast <- message
} }
} }
func (ch *CenterHandler) monitoring() { func (ch *CenterHandler) monitoring() {
for { for {
select { select {
@ -1150,12 +1098,13 @@ func (ch *CenterHandler) monitoring() {
} }
} }
} }
func GetPeers(c *gin.Context) {
func GetPeers(ctx echo.Context) error {
peers := service.MyService.Peer().GetPeers() peers := service.MyService.Peer().GetPeers()
for i := 0; i < len(peers); i++ { for i := 0; i < len(peers); i++ {
if _, ok := handler.clients[peers[i].ID]; ok { if _, ok := handler.clients[peers[i].ID]; ok {
peers[i].Online = true peers[i].Online = true
} }
} }
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: peers}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: peers})
} }

View File

@ -6,28 +6,26 @@ import (
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/labstack/echo/v4"
) )
func PostNotifyMessage(c *gin.Context) { func PostNotifyMessage(ctx echo.Context) error {
name := c.Param("name") name := ctx.Param("name")
message := make(map[string]interface{}) message := make(map[string]interface{})
if err := c.ShouldBind(&message); err != nil { if err := ctx.Bind(&message); err != nil {
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()}) return ctx.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()})
return
} }
service.MyService.Notify().SendNotify(name, message) service.MyService.Notify().SendNotify(name, message)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
func PostSystemStatusNotify(c *gin.Context) { func PostSystemStatusNotify(ctx echo.Context) error {
message := make(map[string]interface{}) message := make(map[string]interface{})
if err := c.ShouldBind(&message); err != nil { if err := ctx.Bind(&message); err != nil {
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()}) return ctx.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: err.Error()})
return
} }
service.MyService.Notify().SettingSystemTempData(message) service.MyService.Notify().SettingSystemTempData(message)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }

View File

@ -6,8 +6,8 @@ import (
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
"github.com/IceWhaleTech/CasaOS/types" "github.com/IceWhaleTech/CasaOS/types"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"github.com/labstack/echo/v4"
) )
var upGrader = websocket.Upgrader{ var upGrader = websocket.Upgrader{
@ -24,11 +24,11 @@ var upGrader = websocket.Upgrader{
// @Param token path string true "token" // @Param token path string true "token"
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /notify/ws [get] // @Router /notify/ws [get]
func NotifyWS(c *gin.Context) { func NotifyWS(ctx echo.Context) error {
//升级get请求为webSocket协议 // 升级get请求为webSocket协议
ws, err := upGrader.Upgrade(c.Writer, c.Request, nil) ws, err := upGrader.Upgrade(ctx.Response().Writer, ctx.Request(), nil)
if err != nil { if err != nil {
return return nil
} }
defer ws.Close() defer ws.Close()
service.WebSocketConns = append(service.WebSocketConns, ws) service.WebSocketConns = append(service.WebSocketConns, ws)
@ -41,7 +41,6 @@ func NotifyWS(c *gin.Context) {
mt, message, err := ws.ReadMessage() mt, message, err := ws.ReadMessage()
fmt.Println(mt, message, err) fmt.Println(mt, message, err)
} }
} }
// @Summary 标记notify已读 // @Summary 标记notify已读
@ -51,12 +50,13 @@ func NotifyWS(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /notify/read/{id} [put] // @Router /notify/read/{id} [put]
func PutNotifyRead(c *gin.Context) { func PutNotifyRead(ctx echo.Context) error {
id := c.Param("id") id := ctx.Param("id")
// if len(id) == 0 { // if len(id) == 0 {
// c.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)}) // return ctx.JSON(http.StatusOK, model.Result{Success: oasis_err.INVALID_PARAMS, Message: oasis_err.GetMsg(oasis_err.INVALID_PARAMS)})
// return // return
// } // }
fmt.Println(id) fmt.Println(id)
service.MyService.Notify().MarkRead(id, types.NOTIFY_READ) service.MyService.Notify().MarkRead(id, types.NOTIFY_READ)
return nil
} }

View File

@ -6,25 +6,23 @@ import (
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/labstack/echo/v4"
) )
func GetSearchResult(c *gin.Context) { func GetSearchResult(ctx echo.Context) error {
json := make(map[string]string) json := make(map[string]string)
c.ShouldBind(&json) ctx.Bind(&json)
url := json["url"] url := json["url"]
if url == "" { if url == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "key is empty"}) return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "key is empty"})
return
} }
//data, err := service.MyService.Other().Search(key) // data, err := service.MyService.Other().Search(key)
data, err := service.MyService.Other().AgentSearch(url) data, err := service.MyService.Other().AgentSearch(url)
if err != nil { if err != nil {
fmt.Println(err) 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()}) return ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
} }

View File

@ -1,6 +1,8 @@
package v1 package v1
import ( import (
"context"
"net/http"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -10,57 +12,52 @@ import (
"github.com/IceWhaleTech/CasaOS/drivers/google_drive" "github.com/IceWhaleTech/CasaOS/drivers/google_drive"
"github.com/IceWhaleTech/CasaOS/drivers/onedrive" "github.com/IceWhaleTech/CasaOS/drivers/onedrive"
"github.com/IceWhaleTech/CasaOS/service" "github.com/IceWhaleTech/CasaOS/service"
"github.com/gin-gonic/gin" "github.com/labstack/echo/v4"
"go.uber.org/zap" "go.uber.org/zap"
) )
func GetRecoverStorage(c *gin.Context) { func GetRecoverStorage(ctx echo.Context) error {
c.Header("Content-Type", "text/html; charset=utf-8") t := strings.TrimSuffix(ctx.Param("type"), "/")
t := c.Param("type")
currentTime := time.Now().UTC() currentTime := time.Now().UTC()
currentDate := time.Now().UTC().Format("2006-01-02") currentDate := time.Now().UTC().Format("2006-01-02")
notify := make(map[string]interface{}) notify := make(map[string]interface{})
event := "casaos:file:recover"
if t == "GoogleDrive" { if t == "GoogleDrive" {
google_drive := google_drive.GetConfig() google_drive := google_drive.GetConfig()
google_drive.Code = c.Query("code") google_drive.Code = ctx.QueryParam("code")
if len(google_drive.Code) == 0 { if len(google_drive.Code) == 0 {
c.String(200, `<p>Code cannot be empty</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Code cannot be empty" notify["message"] = "Code cannot be empty"
logger.Error("Then code is empty: ", zap.String("code", google_drive.Code), zap.Any("name", "google_drive")) logger.Error("Then code is empty: ", zap.String("code", google_drive.Code), zap.Any("name", "google_drive"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify("casaos:file:recover", notify)
return return ctx.HTML(http.StatusOK, `<p>Code cannot be empty</p><script>window.close()</script>`)
} }
err := google_drive.Init(context.Background())
err := google_drive.Init(c)
if err != nil { if err != nil {
c.String(200, `<p>Initialization failure:`+err.Error()+`</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Initialization failure" notify["message"] = "Initialization failure"
logger.Error("Then init error: ", zap.Error(err), zap.Any("name", "google_drive")) logger.Error("Then init error: ", zap.Error(err), zap.Any("name", "google_drive"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>Initialization failure:`+err.Error()+`</p><script>window.close()</script>`)
} }
username, err := google_drive.GetUserInfo(c) username, err := google_drive.GetUserInfo(context.Background())
if err != nil { if err != nil {
c.String(200, `<p>Failed to get user information:`+err.Error()+`</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Failed to get user information" notify["message"] = "Failed to get user information"
logger.Error("Then get user info error: ", zap.Error(err), zap.Any("name", "google_drive")) logger.Error("Then get user info error: ", zap.Error(err), zap.Any("name", "google_drive"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>Failed to get user information:`+err.Error()+`</p><script>window.close()</script>`)
} }
dmap := make(map[string]string) dmap := make(map[string]string)
dmap["username"] = username dmap["username"] = username
configs, err := service.MyService.Storage().GetConfig() configs, err := service.MyService.Storage().GetConfig()
if err != nil { if err != nil {
c.String(200, `<p>Failed to get rclone config:`+err.Error()+`</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Failed to get rclone config" notify["message"] = "Failed to get rclone config"
logger.Error("Then get config error: ", zap.Error(err), zap.Any("name", "google_drive")) logger.Error("Then get config error: ", zap.Error(err), zap.Any("name", "google_drive"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>Failed to get rclone config:`+err.Error()+`</p><script>window.close()</script>`)
} }
for _, v := range configs.Remotes { for _, v := range configs.Remotes {
cf, err := service.MyService.Storage().GetConfigByName(v) cf, err := service.MyService.Storage().GetConfigByName(v)
@ -69,15 +66,14 @@ func GetRecoverStorage(c *gin.Context) {
continue continue
} }
if cf["type"] == "drive" && cf["username"] == dmap["username"] { if cf["type"] == "drive" && cf["username"] == dmap["username"] {
c.String(200, `<p>The same configuration has been added</p><script>window.close()</script>`)
err := service.MyService.Storage().CheckAndMountByName(v) err := service.MyService.Storage().CheckAndMountByName(v)
if err != nil { if err != nil {
logger.Error("check and mount by name error: ", zap.Error(err), zap.Any("name", cf["username"])) logger.Error("check and mount by name error: ", zap.Error(err), zap.Any("name", cf["username"]))
} }
notify["status"] = "warn" notify["status"] = "warn"
notify["message"] = "The same configuration has been added" notify["message"] = "The same configuration has been added"
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>The same configuration has been added</p><script>window.close()</script>`)
} }
} }
if len(username) > 0 { if len(username) > 0 {
@ -85,7 +81,6 @@ func GetRecoverStorage(c *gin.Context) {
username = a[0] username = a[0]
} }
//username = fileutil.NameAccumulation(username, "/mnt")
username += "_google_drive_" + strconv.FormatInt(time.Now().Unix(), 10) username += "_google_drive_" + strconv.FormatInt(time.Now().Unix(), 10)
dmap["client_id"] = google_drive.ClientID dmap["client_id"] = google_drive.ClientID
@ -99,48 +94,45 @@ func GetRecoverStorage(c *gin.Context) {
notify["status"] = "success" notify["status"] = "success"
notify["message"] = "Success" notify["message"] = "Success"
notify["driver"] = "GoogleDrive" notify["driver"] = "GoogleDrive"
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
} else if t == "Dropbox" { } else if t == "Dropbox" {
dropbox := dropbox.GetConfig() dropbox := dropbox.GetConfig()
dropbox.Code = c.Query("code")
dropbox.Code = ctx.QueryParam("code")
if len(dropbox.Code) == 0 { if len(dropbox.Code) == 0 {
c.String(200, `<p>Code cannot be empty</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Code cannot be empty" notify["message"] = "Code cannot be empty"
logger.Error("Then code is empty error: ", zap.String("code", dropbox.Code), zap.Any("name", "dropbox")) logger.Error("Then code is empty error: ", zap.String("code", dropbox.Code), zap.Any("name", "dropbox"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>Code cannot be empty</p><script>window.close()</script>`)
} }
err := dropbox.Init(context.Background())
err := dropbox.Init(c)
if err != nil { if err != nil {
c.String(200, `<p>Initialization failure:`+err.Error()+`</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Initialization failure" notify["message"] = "Initialization failure"
logger.Error("Then init error: ", zap.Error(err), zap.Any("name", "dropbox")) logger.Error("Then init error: ", zap.Error(err), zap.Any("name", "dropbox"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>Initialization failure:`+err.Error()+`</p><script>window.close()</script>`)
} }
username, err := dropbox.GetUserInfo(c) username, err := dropbox.GetUserInfo(context.Background())
if err != nil { if err != nil {
c.String(200, `<p>Failed to get user information:`+err.Error()+`</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Failed to get user information" notify["message"] = "Failed to get user information"
logger.Error("Then get user information: ", zap.Error(err), zap.Any("name", "dropbox")) logger.Error("Then get user information: ", zap.Error(err), zap.Any("name", "dropbox"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>Failed to get user information:`+err.Error()+`</p><script>window.close()</script>`)
} }
dmap := make(map[string]string) dmap := make(map[string]string)
dmap["username"] = username dmap["username"] = username
configs, err := service.MyService.Storage().GetConfig() configs, err := service.MyService.Storage().GetConfig()
if err != nil { if err != nil {
c.String(200, `<p>Failed to get rclone config:`+err.Error()+`</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Failed to get rclone config" notify["message"] = "Failed to get rclone config"
logger.Error("Then get config error: ", zap.Error(err), zap.Any("name", "dropbox")) logger.Error("Then get config error: ", zap.Error(err), zap.Any("name", "dropbox"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>Failed to get rclone config:`+err.Error()+`</p><script>window.close()</script>`)
} }
for _, v := range configs.Remotes { for _, v := range configs.Remotes {
cf, err := service.MyService.Storage().GetConfigByName(v) cf, err := service.MyService.Storage().GetConfigByName(v)
@ -149,16 +141,14 @@ func GetRecoverStorage(c *gin.Context) {
continue continue
} }
if cf["type"] == "dropbox" && cf["username"] == dmap["username"] { if cf["type"] == "dropbox" && cf["username"] == dmap["username"] {
c.String(200, `<p>The same configuration has been added</p><script>window.close()</script>`) if err := service.MyService.Storage().CheckAndMountByName(v); err != nil {
err := service.MyService.Storage().CheckAndMountByName(v)
if err != nil {
logger.Error("check and mount by name error: ", zap.Error(err), zap.Any("name", cf["username"])) logger.Error("check and mount by name error: ", zap.Error(err), zap.Any("name", cf["username"]))
} }
notify["status"] = "warn" notify["status"] = "warn"
notify["message"] = "The same configuration has been added" notify["message"] = "The same configuration has been added"
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>The same configuration has been added</p><script>window.close()</script>`)
} }
} }
if len(username) > 0 { if len(username) > 0 {
@ -171,66 +161,49 @@ func GetRecoverStorage(c *gin.Context) {
dmap["client_secret"] = dropbox.AppSecret dmap["client_secret"] = dropbox.AppSecret
dmap["token"] = `{"access_token":"` + dropbox.AccessToken + `","token_type":"bearer","refresh_token":"` + dropbox.Addition.RefreshToken + `","expiry":"` + currentDate + `T` + currentTime.Add(time.Hour*3).Add(time.Minute*50).Format("15:04:05") + `.780385354Z"}` dmap["token"] = `{"access_token":"` + dropbox.AccessToken + `","token_type":"bearer","refresh_token":"` + dropbox.Addition.RefreshToken + `","expiry":"` + currentDate + `T` + currentTime.Add(time.Hour*3).Add(time.Minute*50).Format("15:04:05") + `.780385354Z"}`
dmap["mount_point"] = "/mnt/" + username dmap["mount_point"] = "/mnt/" + username
// data.SetValue(username, "type", "dropbox")
// data.SetValue(username, "client_id", add.AppKey)
// data.SetValue(username, "client_secret", add.AppSecret)
// data.SetValue(username, "mount_point", "/mnt/"+username)
// data.SetValue(username, "token", `{"access_token":"`+dropbox.AccessToken+`","token_type":"bearer","refresh_token":"`+dropbox.Addition.RefreshToken+`","expiry":"`+currentDate+`T`+currentTime.Add(time.Hour*3).Format("15:04:05")+`.780385354Z"}`)
// e = data.Save()
// if e != nil {
// c.String(200, `<p>保存配置失败:`+e.Error()+`</p>`)
// return
// }
service.MyService.Storage().CreateConfig(dmap, username, "dropbox") service.MyService.Storage().CreateConfig(dmap, username, "dropbox")
service.MyService.Storage().MountStorage("/mnt/"+username, username+":") service.MyService.Storage().MountStorage("/mnt/"+username, username+":")
notify["status"] = "success" notify["status"] = "success"
notify["message"] = "Success" notify["message"] = "Success"
notify["driver"] = "Dropbox" notify["driver"] = "Dropbox"
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
} else if t == "Onedrive" { } else if t == "Onedrive" {
onedrive := onedrive.GetConfig() onedrive := onedrive.GetConfig()
onedrive.Code = c.Query("code") onedrive.Code = ctx.QueryParam("code")
if len(onedrive.Code) == 0 { if len(onedrive.Code) == 0 {
c.String(200, `<p>Code cannot be empty</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Code cannot be empty" notify["message"] = "Code cannot be empty"
logger.Error("Then code is empty error: ", zap.String("code", onedrive.Code), zap.Any("name", "onedrive")) logger.Error("Then code is empty error: ", zap.String("code", onedrive.Code), zap.Any("name", "onedrive"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>Code cannot be empty</p><script>window.close()</script>`)
} }
err := onedrive.Init(context.Background())
err := onedrive.Init(c)
if err != nil { if err != nil {
c.String(200, `<p>Initialization failure:`+err.Error()+`</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Initialization failure" notify["message"] = "Initialization failure"
logger.Error("Then init error: ", zap.Error(err), zap.Any("name", "onedrive")) logger.Error("Then init error: ", zap.Error(err), zap.Any("name", "onedrive"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>Initialization failure:`+err.Error()+`</p><script>window.close()</script>`)
} }
username, driveId, driveType, err := onedrive.GetInfo(c) username, driveId, driveType, err := onedrive.GetInfo(context.Background())
if err != nil { if err != nil {
c.String(200, `<p>Failed to get user information:`+err.Error()+`</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Failed to get user information" notify["message"] = "Failed to get user information"
logger.Error("Then get user information: ", zap.Error(err), zap.Any("name", "onedrive")) logger.Error("Then get user information: ", zap.Error(err), zap.Any("name", "onedrive"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>Failed to get user information:`+err.Error()+`</p><script>window.close()</script>`)
} }
dmap := make(map[string]string) dmap := make(map[string]string)
dmap["username"] = username dmap["username"] = username
configs, err := service.MyService.Storage().GetConfig() configs, err := service.MyService.Storage().GetConfig()
if err != nil { if err != nil {
c.String(200, `<p>Failed to get rclone config:`+err.Error()+`</p><script>window.close()</script>`)
notify["status"] = "fail" notify["status"] = "fail"
notify["message"] = "Failed to get rclone config" notify["message"] = "Failed to get rclone config"
logger.Error("Then get config error: ", zap.Error(err), zap.Any("name", "onedrive")) logger.Error("Then get config error: ", zap.Error(err), zap.Any("name", "onedrive"))
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>Failed to get rclone config:`+err.Error()+`</p><script>window.close()</script>`)
} }
for _, v := range configs.Remotes { for _, v := range configs.Remotes {
cf, err := service.MyService.Storage().GetConfigByName(v) cf, err := service.MyService.Storage().GetConfigByName(v)
@ -239,16 +212,14 @@ func GetRecoverStorage(c *gin.Context) {
continue continue
} }
if cf["type"] == "onedrive" && cf["username"] == dmap["username"] { if cf["type"] == "onedrive" && cf["username"] == dmap["username"] {
c.String(200, `<p>The same configuration has been added</p><script>window.close()</script>`) if err := service.MyService.Storage().CheckAndMountByName(v); err != nil {
err := service.MyService.Storage().CheckAndMountByName(v)
if err != nil {
logger.Error("check and mount by name error: ", zap.Error(err), zap.Any("name", cf["username"])) logger.Error("check and mount by name error: ", zap.Error(err), zap.Any("name", cf["username"]))
} }
notify["status"] = "warn" notify["status"] = "warn"
notify["message"] = "The same configuration has been added" notify["message"] = "The same configuration has been added"
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
return return ctx.HTML(http.StatusOK, `<p>The same configuration has been added</p><script>window.close()</script>`)
} }
} }
if len(username) > 0 { if len(username) > 0 {
@ -263,26 +234,14 @@ func GetRecoverStorage(c *gin.Context) {
dmap["mount_point"] = "/mnt/" + username dmap["mount_point"] = "/mnt/" + username
dmap["drive_id"] = driveId dmap["drive_id"] = driveId
dmap["drive_type"] = driveType dmap["drive_type"] = driveType
// data.SetValue(username, "type", "dropbox")
// data.SetValue(username, "client_id", add.AppKey)
// data.SetValue(username, "client_secret", add.AppSecret)
// data.SetValue(username, "mount_point", "/mnt/"+username)
// data.SetValue(username, "token", `{"access_token":"`+dropbox.AccessToken+`","token_type":"bearer","refresh_token":"`+dropbox.Addition.RefreshToken+`","expiry":"`+currentDate+`T`+currentTime.Add(time.Hour*3).Format("15:04:05")+`.780385354Z"}`)
// e = data.Save()
// if e != nil {
// c.String(200, `<p>保存配置失败:`+e.Error()+`</p>`)
// return
// }
service.MyService.Storage().CreateConfig(dmap, username, "onedrive") service.MyService.Storage().CreateConfig(dmap, username, "onedrive")
service.MyService.Storage().MountStorage("/mnt/"+username, username+":") service.MyService.Storage().MountStorage("/mnt/"+username, username+":")
notify["status"] = "success" notify["status"] = "success"
notify["message"] = "Success" notify["message"] = "Success"
notify["driver"] = "Onedrive" notify["driver"] = "Onedrive"
service.MyService.Notify().SendNotify("casaos:file:recover", notify) service.MyService.Notify().SendNotify(event, notify)
} }
c.String(200, `<p>Just close the page</p><script>window.close()</script>`) return ctx.HTML(200, `<p>Just close the page</p><script>window.close()</script>`)
} }

View File

@ -20,6 +20,7 @@ import (
"github.com/IceWhaleTech/CasaOS-Common/utils/logger" "github.com/IceWhaleTech/CasaOS-Common/utils/logger"
"github.com/IceWhaleTech/CasaOS-Common/utils/systemctl" "github.com/IceWhaleTech/CasaOS-Common/utils/systemctl"
"github.com/labstack/echo/v4"
"go.uber.org/zap" "go.uber.org/zap"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
@ -28,18 +29,16 @@ import (
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"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"
) )
// service // service
func GetSambaStatus(c *gin.Context) { func GetSambaStatus(ctx echo.Context) error {
if status, err := systemctl.IsServiceRunning("smbd"); err != nil || !status { if status, err := systemctl.IsServiceRunning("smbd"); err != nil || !status {
c.JSON(http.StatusInternalServerError, model.Result{ return ctx.JSON(http.StatusInternalServerError, model.Result{
Success: common_err.SERVICE_NOT_RUNNING, Success: common_err.SERVICE_NOT_RUNNING,
Message: common_err.GetMsg(common_err.SERVICE_NOT_RUNNING), Message: common_err.GetMsg(common_err.SERVICE_NOT_RUNNING),
}) })
return
} }
needInit := true needInit := true
@ -51,10 +50,10 @@ func GetSambaStatus(c *gin.Context) {
} }
data := make(map[string]string, 1) data := make(map[string]string, 1)
data["need_init"] = fmt.Sprintf("%v", needInit) data["need_init"] = fmt.Sprintf("%v", needInit)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
} }
func GetSambaSharesList(c *gin.Context) { func GetSambaSharesList(ctx echo.Context) error {
shares := service.MyService.Shares().GetSharesList() shares := service.MyService.Shares().GetSharesList()
shareList := []model.Shares{} shareList := []model.Shares{}
for _, v := range shares { for _, v := range shares {
@ -64,28 +63,24 @@ func GetSambaSharesList(c *gin.Context) {
ID: v.ID, ID: v.ID,
}) })
} }
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: shareList}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: shareList})
} }
func PostSambaSharesCreate(c *gin.Context) { func PostSambaSharesCreate(ctx echo.Context) error {
shares := []model.Shares{} shares := []model.Shares{}
c.ShouldBindJSON(&shares) ctx.Bind(&shares)
for _, v := range shares { for _, v := range shares {
if v.Path == "" { if v.Path == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)}) return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
return
} }
if !file.Exists(v.Path) { if !file.Exists(v.Path) {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)}) return ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
return
} }
if len(service.MyService.Shares().GetSharesByPath(v.Path)) > 0 { if len(service.MyService.Shares().GetSharesByPath(v.Path)) > 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.SHARE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.SHARE_ALREADY_EXISTS)}) return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.SHARE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.SHARE_ALREADY_EXISTS)})
return
} }
if len(service.MyService.Shares().GetSharesByPath(filepath.Base(v.Path))) > 0 { if len(service.MyService.Shares().GetSharesByPath(filepath.Base(v.Path))) > 0 {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.SHARE_NAME_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.SHARE_NAME_ALREADY_EXISTS)}) return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.SHARE_NAME_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.SHARE_NAME_ALREADY_EXISTS)})
return
} }
} }
for _, v := range shares { for _, v := range shares {
@ -97,21 +92,20 @@ func PostSambaSharesCreate(c *gin.Context) {
service.MyService.Shares().CreateShare(shareDBModel) service.MyService.Shares().CreateShare(shareDBModel)
} }
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: shares}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: shares})
} }
func DeleteSambaShares(c *gin.Context) { func DeleteSambaShares(ctx echo.Context) error {
id := c.Param("id") id := ctx.Param("id")
if id == "" { if id == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)}) return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
return
} }
service.MyService.Shares().DeleteShare(id) service.MyService.Shares().DeleteShare(id)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
} }
// client // client
func GetSambaConnectionsList(c *gin.Context) { func GetSambaConnectionsList(ctx echo.Context) error {
connections := service.MyService.Connections().GetConnectionsList() connections := service.MyService.Connections().GetConnectionsList()
connectionList := []model.Connections{} connectionList := []model.Connections{}
for _, v := range connections { for _, v := range connections {
@ -123,34 +117,33 @@ func GetSambaConnectionsList(c *gin.Context) {
MountPoint: v.MountPoint, MountPoint: v.MountPoint,
}) })
} }
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connectionList}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connectionList})
} }
func PostSambaConnectionsCreate(c *gin.Context) { func PostSambaConnectionsCreate(ctx echo.Context) error {
connection := model.Connections{} connection := model.Connections{}
c.ShouldBindJSON(&connection) ctx.Bind(&connection)
if connection.Port == "" { if connection.Port == "" {
connection.Port = "445" connection.Port = "445"
} }
if connection.Username == "" || connection.Host == "" { if connection.Username == "" || connection.Host == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CHARACTER_LIMIT, Message: common_err.GetMsg(common_err.CHARACTER_LIMIT)}) return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CHARACTER_LIMIT, Message: common_err.GetMsg(common_err.CHARACTER_LIMIT)})
return
} }
// if ok, _ := regexp.MatchString(`^[\w@#*.]{4,30}$`, connection.Password); !ok { // if ok, _ := regexp.MatchString(`^[\w@#*.]{4,30}$`, connection.Password); !ok {
// c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CHARACTER_LIMIT, Message: common_err.GetMsg(common_err.CHARACTER_LIMIT)}) // return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CHARACTER_LIMIT, Message: common_err.GetMsg(common_err.CHARACTER_LIMIT)})
// return // return
// } // }
// if ok, _ := regexp.MatchString(`^[\w@#*.]{4,30}$`, connection.Username); !ok { // if ok, _ := regexp.MatchString(`^[\w@#*.]{4,30}$`, connection.Username); !ok {
// c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) // return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return // return
// } // }
// if !ip_helper.IsIPv4(connection.Host) && !ip_helper.IsIPv6(connection.Host) { // if !ip_helper.IsIPv4(connection.Host) && !ip_helper.IsIPv6(connection.Host) {
// c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) // return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return // return
// } // }
// if ok, _ := regexp.MatchString("^[0-9]{1,6}$", connection.Port); !ok { // if ok, _ := regexp.MatchString("^[0-9]{1,6}$", connection.Port); !ok {
// c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)}) // return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
// return // return
// } // }
@ -158,14 +151,12 @@ func PostSambaConnectionsCreate(c *gin.Context) {
// check is exists // check is exists
connections := service.MyService.Connections().GetConnectionByHost(connection.Host) connections := service.MyService.Connections().GetConnectionByHost(connection.Host)
if len(connections) > 0 { if len(connections) > 0 {
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.Record_ALREADY_EXIST, Message: common_err.GetMsg(common_err.Record_ALREADY_EXIST), Data: common_err.GetMsg(common_err.Record_ALREADY_EXIST)}) return ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.Record_ALREADY_EXIST, Message: common_err.GetMsg(common_err.Record_ALREADY_EXIST), Data: common_err.GetMsg(common_err.Record_ALREADY_EXIST)})
return
} }
// check connect is ok // check connect is ok
directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password) directories, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
if err != nil { 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 ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
connectionDBModel := model2.ConnectionsDBModel{} connectionDBModel := model2.ConnectionsDBModel{}
@ -187,21 +178,19 @@ func PostSambaConnectionsCreate(c *gin.Context) {
service.MyService.Connections().CreateConnection(&connectionDBModel) service.MyService.Connections().CreateConnection(&connectionDBModel)
connection.ID = connectionDBModel.ID connection.ID = connectionDBModel.ID
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connection}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: connection})
} }
func DeleteSambaConnections(c *gin.Context) { func DeleteSambaConnections(ctx echo.Context) error {
id := c.Param("id") id := ctx.Param("id")
connection := service.MyService.Connections().GetConnectionByID(id) connection := service.MyService.Connections().GetConnectionByID(id)
if connection.Username == "" { if connection.Username == "" {
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.Record_NOT_EXIST, Message: common_err.GetMsg(common_err.Record_NOT_EXIST)}) return ctx.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.Record_NOT_EXIST, Message: common_err.GetMsg(common_err.Record_NOT_EXIST)})
return
} }
mountPointList, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password) mountPointList, err := samba.GetSambaSharesList(connection.Host, connection.Port, connection.Username, connection.Password)
//mountPointList, err := service.MyService.System().GetDirPath(connection.MountPoint) // mountPointList, err := service.MyService.System().GetDirPath(connection.MountPoint)
if err != nil { 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 ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
baseHostPath := "/mnt/" + connection.Host baseHostPath := "/mnt/" + connection.Host
for _, v := range mountPointList { for _, v := range mountPointList {
@ -209,16 +198,14 @@ func DeleteSambaConnections(c *gin.Context) {
err := service.MyService.Connections().UnmountSmaba(baseHostPath + "/" + v) err := service.MyService.Connections().UnmountSmaba(baseHostPath + "/" + v)
if err != nil { if err != nil {
logger.Error("unmount smaba error", zap.Error(err), zap.Any("path", baseHostPath+"/"+v)) logger.Error("unmount smaba error", zap.Error(err), zap.Any("path", baseHostPath+"/"+v))
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 ctx.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
return
} }
} }
} }
dir, _ := ioutil.ReadDir(connection.MountPoint) dir, _ := ioutil.ReadDir(connection.MountPoint)
if len(dir) == 0 { if len(dir) == 0 {
os.RemoveAll(connection.MountPoint) os.RemoveAll(connection.MountPoint)
} }
service.MyService.Connections().DeleteConnection(id) service.MyService.Connections().DeleteConnection(id)
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
} }

View File

@ -16,8 +16,8 @@ import (
"testing" "testing"
v1 "github.com/IceWhaleTech/CasaOS/route/v1" v1 "github.com/IceWhaleTech/CasaOS/route/v1"
"github.com/gin-gonic/gin"
"github.com/golang/mock/gomock" "github.com/golang/mock/gomock"
"github.com/labstack/echo/v4"
"gotest.tools/assert" "gotest.tools/assert"
) )
@ -54,17 +54,22 @@ func performRequest(r http.Handler, method, path string) *httptest.ResponseRecor
func TestGetSambaSharesList(t *testing.T) { func TestGetSambaSharesList(t *testing.T) {
t.Skip("This test is always failing. Skipped to unblock releasing - MUST FIX!") t.Skip("This test is always failing. Skipped to unblock releasing - MUST FIX!")
gin.SetMode(gin.TestMode)
ctrl := gomock.NewController(t) ctrl := gomock.NewController(t)
defer ctrl.Finish() defer ctrl.Finish()
executeWithContext := func() *httptest.ResponseRecorder { executeWithContext := func() *httptest.ResponseRecorder {
response := httptest.NewRecorder() response := httptest.NewRecorder()
con, ginEngine := gin.CreateTestContext(response) // con, ginEngine := gin.CreateTestContext(response)
e := echo.New()
requestUrl := "/v1/samba/shares" requestUrl := "/v1/samba/shares"
httpRequest, _ := http.NewRequest("GET", requestUrl, nil) httpRequest, _ := http.NewRequest("GET", requestUrl, nil)
con := e.NewContext(httpRequest, response)
v1.GetSambaSharesList(con) v1.GetSambaSharesList(con)
ginEngine.ServeHTTP(response, httpRequest) e.ServeHTTP(response, httpRequest)
return response return response
} }

View File

@ -10,8 +10,9 @@ import (
"github.com/IceWhaleTech/CasaOS-Common/utils/common_err" "github.com/IceWhaleTech/CasaOS-Common/utils/common_err"
"github.com/IceWhaleTech/CasaOS-Common/utils/logger" "github.com/IceWhaleTech/CasaOS-Common/utils/logger"
sshHelper "github.com/IceWhaleTech/CasaOS-Common/utils/ssh" sshHelper "github.com/IceWhaleTech/CasaOS-Common/utils/ssh"
"github.com/IceWhaleTech/CasaOS/pkg/utils"
"github.com/labstack/echo/v4"
"github.com/gin-gonic/gin"
"github.com/gorilla/websocket" "github.com/gorilla/websocket"
"go.uber.org/zap" "go.uber.org/zap"
"golang.org/x/crypto/ssh" "golang.org/x/crypto/ssh"
@ -26,44 +27,41 @@ var upgrader = websocket.Upgrader{
HandshakeTimeout: time.Duration(time.Second * 5), HandshakeTimeout: time.Duration(time.Second * 5),
} }
func PostSshLogin(c *gin.Context) { func PostSshLogin(ctx echo.Context) error {
j := make(map[string]string) j := make(map[string]string)
c.ShouldBind(&j) ctx.Bind(&j)
userName := j["username"] userName := j["username"]
password := j["password"] password := j["password"]
port := j["port"] port := j["port"]
if userName == "" || password == "" || port == "" { if userName == "" || password == "" || port == "" {
c.JSON(common_err.CLIENT_ERROR, modelCommon.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "Username or password or port is empty"}) return ctx.JSON(common_err.CLIENT_ERROR, modelCommon.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "Username or password or port is empty"})
return
} }
_, err := sshHelper.NewSshClient(userName, password, port) _, err := sshHelper.NewSshClient(userName, password, port)
if err != nil { if err != nil {
c.JSON(common_err.CLIENT_ERROR, modelCommon.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Please check if the username and port are correct, and make sure that ssh server is installed."})
logger.Error("connect ssh error", zap.Any("error", err)) logger.Error("connect ssh error", zap.Any("error", err))
return return ctx.JSON(common_err.CLIENT_ERROR, modelCommon.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Please check if the username and port are correct, and make sure that ssh server is installed."})
} }
c.JSON(common_err.SUCCESS, modelCommon.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) return ctx.JSON(common_err.SUCCESS, modelCommon.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
func WsSsh(c *gin.Context) { func WsSsh(ctx echo.Context) error {
_, e := exec.LookPath("ssh") _, e := exec.LookPath("ssh")
if e != nil { if e != nil {
c.JSON(common_err.SERVICE_ERROR, modelCommon.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "ssh server not found"}) return ctx.JSON(common_err.SERVICE_ERROR, modelCommon.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "ssh server not found"})
return
} }
userName := c.Query("username") userName := ctx.QueryParam("username")
password := c.Query("password") password := ctx.QueryParam("password")
port := c.Query("port") port := ctx.QueryParam("port")
wsConn, _ := upgrader.Upgrade(c.Writer, c.Request, nil) wsConn, _ := upgrader.Upgrade(ctx.Response().Writer, ctx.Request(), nil)
logBuff := new(bytes.Buffer) logBuff := new(bytes.Buffer)
quitChan := make(chan bool, 3) quitChan := make(chan bool, 3)
// user := "" // user := ""
// password := "" // password := ""
var login int = 1 var login int = 1
cols, _ := strconv.Atoi(c.DefaultQuery("cols", "200")) cols, _ := strconv.Atoi(utils.DefaultQuery(ctx, "cols", "200"))
rows, _ := strconv.Atoi(c.DefaultQuery("rows", "32")) rows, _ := strconv.Atoi(utils.DefaultQuery(ctx, "rows", "32"))
var client *ssh.Client var client *ssh.Client
for login != 0 { for login != 0 {
@ -93,4 +91,5 @@ func WsSsh(c *gin.Context) {
go ssConn.SessionWait(quitChan) go ssConn.SessionWait(quitChan)
<-quitChan <-quitChan
return nil
} }

View File

@ -19,12 +19,13 @@ import (
"github.com/IceWhaleTech/CasaOS/common" "github.com/IceWhaleTech/CasaOS/common"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
"github.com/IceWhaleTech/CasaOS/pkg/utils"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"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/labstack/echo/v4"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
) )
@ -35,7 +36,7 @@ import (
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/version/check [get] // @Router /sys/version/check [get]
func GetSystemCheckVersion(c *gin.Context) { func GetSystemCheckVersion(ctx echo.Context) error {
need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion()) need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion())
if need { if need {
installLog := model2.AppNotify{} installLog := model2.AppNotify{}
@ -51,7 +52,7 @@ func GetSystemCheckVersion(c *gin.Context) {
data["need_update"] = need data["need_update"] = need
data["version"] = version data["version"] = version
data["current_version"] = common.VERSION data["current_version"] = common.VERSION
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
} }
// @Summary 系统信息 // @Summary 系统信息
@ -61,12 +62,12 @@ func GetSystemCheckVersion(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @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(ctx echo.Context) error {
need, version := version.IsNeedUpdate(service.MyService.Casa().GetCasaosVersion()) 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(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
} }
// @Summary get logs // @Summary get logs
@ -76,13 +77,13 @@ func SystemUpdate(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/error/logs [get] // @Router /sys/error/logs [get]
func GetCasaOSErrorLogs(c *gin.Context) { func GetCasaOSErrorLogs(ctx echo.Context) error {
line, _ := strconv.Atoi(c.DefaultQuery("line", "100")) line, _ := strconv.Atoi(utils.DefaultQuery(ctx, "line", "100"))
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
} }
// 系统配置 // 系统配置
func GetSystemConfigDebug(c *gin.Context) { func GetSystemConfigDebug(ctx echo.Context) error {
array := service.MyService.System().GetSystemConfigDebug() array := service.MyService.System().GetSystemConfigDebug()
disk := service.MyService.System().GetDiskInfo() disk := service.MyService.System().GetDiskInfo()
sys := service.MyService.System().GetSysInfo() sys := service.MyService.System().GetSysInfo()
@ -100,7 +101,7 @@ func GetSystemConfigDebug(c *gin.Context) {
// 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(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: bugContent}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: bugContent})
} }
// @Summary get casaos server port // @Summary get casaos server port
@ -110,8 +111,8 @@ func GetSystemConfigDebug(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @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(ctx echo.Context) error {
c.JSON(common_err.SUCCESS, return ctx.JSON(common_err.SUCCESS,
model.Result{ model.Result{
Success: common_err.SUCCESS, Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS), Message: common_err.GetMsg(common_err.SUCCESS),
@ -127,31 +128,29 @@ func GetCasaOSPort(c *gin.Context) {
// @Param port json 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(ctx echo.Context) error {
json := make(map[string]string) json := make(map[string]string)
c.ShouldBind(&json) ctx.Bind(&json)
portStr := json["port"] portStr := json["port"]
portNumber, err := strconv.Atoi(portStr) portNumber, err := strconv.Atoi(portStr)
if err != nil { if err != nil {
c.JSON(common_err.SERVICE_ERROR, return ctx.JSON(common_err.SERVICE_ERROR,
model.Result{ model.Result{
Success: common_err.SERVICE_ERROR, Success: common_err.SERVICE_ERROR,
Message: err.Error(), Message: err.Error(),
}) })
return
} }
isAvailable := port.IsPortAvailable(portNumber, "tcp") isAvailable := port.IsPortAvailable(portNumber, "tcp")
if !isAvailable { if !isAvailable {
c.JSON(common_err.SERVICE_ERROR, return ctx.JSON(common_err.SERVICE_ERROR,
model.Result{ model.Result{
Success: common_err.PORT_IS_OCCUPIED, Success: common_err.PORT_IS_OCCUPIED,
Message: common_err.GetMsg(common_err.PORT_IS_OCCUPIED), Message: common_err.GetMsg(common_err.PORT_IS_OCCUPIED),
}) })
return
} }
service.MyService.System().UpSystemPort(strconv.Itoa(portNumber)) service.MyService.System().UpSystemPort(strconv.Itoa(portNumber))
c.JSON(common_err.SUCCESS, return ctx.JSON(common_err.SUCCESS,
model.Result{ model.Result{
Success: common_err.SUCCESS, Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS), Message: common_err.GetMsg(common_err.SUCCESS),
@ -165,8 +164,9 @@ func PutCasaOSPort(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/restart [post] // @Router /sys/restart [post]
func PostKillCasaOS(c *gin.Context) { func PostKillCasaOS(ctx echo.Context) error {
os.Exit(0) os.Exit(0)
return nil
} }
// @Summary get system hardware info // @Summary get system hardware info
@ -176,20 +176,20 @@ func PostKillCasaOS(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/hardware/info [get] // @Router /sys/hardware/info [get]
func GetSystemHardwareInfo(c *gin.Context) { func GetSystemHardwareInfo(ctx echo.Context) error {
data := make(map[string]string, 1) data := make(map[string]string, 1)
data["drive_model"] = service.MyService.System().GetDeviceTree() data["drive_model"] = service.MyService.System().GetDeviceTree()
data["arch"] = runtime.GOARCH data["arch"] = runtime.GOARCH
if cpu := service.MyService.System().GetCpuInfo(); len(cpu) > 0 { if cpu := service.MyService.System().GetCpuInfo(); len(cpu) > 0 {
return ctx.JSON(common_err.SUCCESS,
c.JSON(common_err.SUCCESS,
model.Result{ model.Result{
Success: common_err.SUCCESS, Success: common_err.SUCCESS,
Message: common_err.GetMsg(common_err.SUCCESS), Message: common_err.GetMsg(common_err.SUCCESS),
Data: data, Data: data,
}) })
} }
return nil
} }
// @Summary system utilization // @Summary system utilization
@ -199,7 +199,7 @@ func GetSystemHardwareInfo(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/utilization [get] // @Router /sys/utilization [get]
func GetSystemUtilization(c *gin.Context) { func GetSystemUtilization(ctx echo.Context) error {
data := make(map[string]interface{}) data := make(map[string]interface{})
cpu := service.MyService.System().GetCpuPercent() cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum() num := service.MyService.System().GetCpuCoreNum()
@ -243,7 +243,7 @@ func GetSystemUtilization(c *gin.Context) {
data[key.(string)] = value data[key.(string)] = value
return true return true
}) })
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) return ctx.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
} }
// @Summary get cpu info // @Summary get cpu info
@ -253,13 +253,13 @@ func GetSystemUtilization(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/cpu [get] // @Router /sys/cpu [get]
func GetSystemCupInfo(c *gin.Context) { func GetSystemCupInfo(ctx echo.Context) error {
cpu := service.MyService.System().GetCpuPercent() cpu := service.MyService.System().GetCpuPercent()
num := service.MyService.System().GetCpuCoreNum() num := service.MyService.System().GetCpuCoreNum()
data := make(map[string]interface{}) data := make(map[string]interface{})
data["percent"] = cpu data["percent"] = cpu
data["num"] = num data["num"] = num
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data}) return ctx.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
} }
// @Summary get mem info // @Summary get mem info
@ -269,9 +269,9 @@ func GetSystemCupInfo(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/mem [get] // @Router /sys/mem [get]
func GetSystemMemInfo(c *gin.Context) { func GetSystemMemInfo(ctx echo.Context) error {
mem := service.MyService.System().GetMemInfo() mem := service.MyService.System().GetMemInfo()
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mem}) return ctx.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mem})
} }
// @Summary get disk info // @Summary get disk info
@ -281,9 +281,9 @@ func GetSystemMemInfo(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/disk [get] // @Router /sys/disk [get]
func GetSystemDiskInfo(c *gin.Context) { func GetSystemDiskInfo(ctx echo.Context) error {
disk := service.MyService.System().GetDiskInfo() disk := service.MyService.System().GetDiskInfo()
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: disk}) return ctx.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: disk})
} }
// @Summary get Net info // @Summary get Net info
@ -293,7 +293,7 @@ func GetSystemDiskInfo(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /sys/net [get] // @Router /sys/net [get]
func GetSystemNetInfo(c *gin.Context) { func GetSystemNetInfo(ctx echo.Context) error {
netList := service.MyService.System().GetNetInfo() netList := service.MyService.System().GetNetInfo()
newNet := []model.IOCountersStat{} newNet := []model.IOCountersStat{}
for _, n := range netList { for _, n := range netList {
@ -308,35 +308,36 @@ func GetSystemNetInfo(c *gin.Context) {
} }
} }
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: newNet}) return ctx.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: newNet})
} }
func GetSystemProxy(c *gin.Context) { func GetSystemProxy(ctx echo.Context) error {
url := c.Query("url") url := ctx.QueryParam("url")
resp, err := http2.Get(url, 30*time.Second) resp, err := http2.Get(url, 30*time.Second)
if err != nil { if err != nil {
return return ctx.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
} }
defer resp.Body.Close() defer resp.Body.Close()
for k, v := range c.Request.Header { for k, v := range ctx.Request().Header {
c.Header(k, v[0]) ctx.Request().Header.Add(k, v[0])
} }
rda, _ := ioutil.ReadAll(resp.Body) rda, _ := ioutil.ReadAll(resp.Body)
// json.NewEncoder(c.Writer).Encode(json.RawMessage(string(rda))) // json.NewEncoder(c.Writer).Encode(json.RawMessage(string(rda)))
// 响应状态码 // 响应状态码
c.Writer.WriteHeader(resp.StatusCode) ctx.Response().Writer.WriteHeader(resp.StatusCode)
// 复制转发的响应Body到响应Body // 复制转发的响应Body到响应Body
io.Copy(c.Writer, ioutil.NopCloser(bytes.NewBuffer(rda))) io.Copy(ctx.Response().Writer, ioutil.NopCloser(bytes.NewBuffer(rda)))
return nil
} }
func PutSystemState(c *gin.Context) { func PutSystemState(ctx echo.Context) error {
state := c.Param("state") state := ctx.Param("state")
if strings.ToLower(state) == "off" { if strings.ToLower(state) == "off" {
service.MyService.System().SystemShutdown() service.MyService.System().SystemShutdown()
} else if strings.ToLower(state) == "restart" { } else if strings.ToLower(state) == "restart" {
service.MyService.System().SystemReboot() service.MyService.System().SystemReboot()
} }
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "The operation will be completed shortly."}) return ctx.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "The operation will be completed shortly."})
} }
// @Summary 获取一个可用端口 // @Summary 获取一个可用端口
@ -347,8 +348,8 @@ func PutSystemState(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /app/getport [get] // @Router /app/getport [get]
func GetPort(c *gin.Context) { func GetPort(ctx echo.Context) error {
t := c.DefaultQuery("type", "tcp") t := utils.DefaultQuery(ctx, "type", "tcp")
var p int var p int
ok := true ok := true
for ok { for ok {
@ -356,7 +357,7 @@ func GetPort(c *gin.Context) {
ok = !port.IsPortAvailable(p, t) ok = !port.IsPortAvailable(p, t)
} }
// @tiger 这里最好封装成 {'port': ...} 的形式,来体现出参的上下文 // @tiger 这里最好封装成 {'port': ...} 的形式,来体现出参的上下文
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: p}) return ctx.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: p})
} }
// @Summary 检查端口是否可用 // @Summary 检查端口是否可用
@ -368,18 +369,17 @@ func GetPort(c *gin.Context) {
// @Security ApiKeyAuth // @Security ApiKeyAuth
// @Success 200 {string} string "ok" // @Success 200 {string} string "ok"
// @Router /app/check/{port} [get] // @Router /app/check/{port} [get]
func PortCheck(c *gin.Context) { func PortCheck(ctx echo.Context) error {
p, _ := strconv.Atoi(c.Param("port")) p, _ := strconv.Atoi(ctx.Param("port"))
t := c.DefaultQuery("type", "tcp") t := utils.DefaultQuery(ctx, "type", "tcp")
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port.IsPortAvailable(p, t)}) return ctx.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: port.IsPortAvailable(p, t)})
} }
func GetSystemEntry(c *gin.Context) { func GetSystemEntry(ctx echo.Context) error {
entry := service.MyService.System().GetSystemEntry() entry := service.MyService.System().GetSystemEntry()
str := json.RawMessage(entry) str := json.RawMessage(entry)
if !gjson.ValidBytes(str) { if !gjson.ValidBytes(str) {
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: entry, Data: json.RawMessage("[]")}) return ctx.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: entry, Data: json.RawMessage("[]")})
return
} }
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: str}) return ctx.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: str})
} }

View File

@ -12,19 +12,18 @@ import (
"github.com/IceWhaleTech/CasaOS-Common/utils/logger" "github.com/IceWhaleTech/CasaOS-Common/utils/logger"
"github.com/IceWhaleTech/CasaOS/common" "github.com/IceWhaleTech/CasaOS/common"
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper" "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
"github.com/gin-gonic/gin" "github.com/labstack/echo/v4"
"github.com/tidwall/gjson" "github.com/tidwall/gjson"
"go.uber.org/zap" "go.uber.org/zap"
) )
func ZerotierProxy(c *gin.Context) { func ZerotierProxy(ctx echo.Context) error {
// Read the port number from the file // Read the port number from the file
w := c.Writer w := ctx.Response().Writer
r := c.Request r := ctx.Request()
port, err := ioutil.ReadFile("/var/lib/zerotier-one/zerotier-one.port") port, err := ioutil.ReadFile("/var/lib/zerotier-one/zerotier-one.port")
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return
} }
// Get the request path and remove "/zt" // Get the request path and remove "/zt"
@ -38,14 +37,12 @@ func ZerotierProxy(c *gin.Context) {
req, err := http.NewRequest(r.Method, targetURL, r.Body) req, err := http.NewRequest(r.Method, targetURL, r.Body)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return
} }
// Add the X-ZT1-AUTH header // Add the X-ZT1-AUTH header
authToken, err := ioutil.ReadFile("/var/lib/zerotier-one/authtoken.secret") authToken, err := ioutil.ReadFile("/var/lib/zerotier-one/authtoken.secret")
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return
} }
req.Header.Set("X-ZT1-AUTH", strings.TrimSpace(string(authToken))) req.Header.Set("X-ZT1-AUTH", strings.TrimSpace(string(authToken)))
@ -55,7 +52,6 @@ func ZerotierProxy(c *gin.Context) {
resp, err := client.Do(req) resp, err := client.Do(req)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return
} }
defer resp.Body.Close() defer resp.Body.Close()
@ -64,12 +60,13 @@ func ZerotierProxy(c *gin.Context) {
respBody, err := ioutil.ReadAll(resp.Body) respBody, err := ioutil.ReadAll(resp.Body)
if err != nil { if err != nil {
http.Error(w, err.Error(), http.StatusInternalServerError) http.Error(w, err.Error(), http.StatusInternalServerError)
return
} }
// Return the response to the client // Return the response to the client
w.WriteHeader(resp.StatusCode) w.WriteHeader(resp.StatusCode)
w.Write(respBody) w.Write(respBody)
// TODO
return nil
} }
func copyHeaders(destination, source http.Header) { func copyHeaders(destination, source http.Header) {
@ -130,6 +127,7 @@ func CheckNetwork() {
JoinAndUpdateNet(address, networkId, ip) JoinAndUpdateNet(address, networkId, ip)
} }
} }
func GetAddress() string { func GetAddress() string {
nodeRes, err := httper.ZTGet("/status") nodeRes, err := httper.ZTGet("/status")
if err != nil { if err != nil {
@ -138,6 +136,7 @@ func GetAddress() string {
} }
return gjson.GetBytes(nodeRes, "address").String() return gjson.GetBytes(nodeRes, "address").String()
} }
func JoinAndUpdateNet(address, networkId, ip string) { func JoinAndUpdateNet(address, networkId, ip string) {
logger.Info("start join network", zap.Any("ip", ip)) logger.Info("start join network", zap.Any("ip", ip))
_, err := httper.ZTPost("/network/"+networkId, "") _, err := httper.ZTPost("/network/"+networkId, "")
@ -162,6 +161,7 @@ func JoinAndUpdateNet(address, networkId, ip string) {
return return
} }
} }
func CreateNet(address, s, e, c string) string { func CreateNet(address, s, e, c string) string {
body := `{ body := `{
"name": "` + common.RANW_NAME + `", "name": "` + common.RANW_NAME + `",

View File

@ -71,8 +71,7 @@ func InitV2Router() http.Handler {
e.Use(echo_middleware.JWTWithConfig(echo_middleware.JWTConfig{ e.Use(echo_middleware.JWTWithConfig(echo_middleware.JWTConfig{
Skipper: func(c echo.Context) bool { Skipper: func(c echo.Context) bool {
return c.RealIP() == "::1" || c.RealIP() == "127.0.0.1" return c.RealIP() == "::1" || c.RealIP() == "127.0.0.1"
//return true // return true
}, },
ParseTokenFunc: func(token string, c echo.Context) (interface{}, error) { ParseTokenFunc: func(token string, c echo.Context) (interface{}, error) {
valid, claims, err := jwt.Validate(token, func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) }) valid, claims, err := jwt.Validate(token, func() (*ecdsa.PublicKey, error) { return external.GetPublicKey(config.CommonInfo.RuntimePath) })
@ -84,11 +83,11 @@ func InitV2Router() http.Handler {
return claims, nil return claims, nil
}, },
TokenLookupFuncs: []echo_middleware.ValuesExtractor{ TokenLookupFuncs: []echo_middleware.ValuesExtractor{
func(c echo.Context) ([]string, error) { func(ctx echo.Context) ([]string, error) {
if len(c.Request().Header.Get(echo.HeaderAuthorization)) > 0 { if len(ctx.Request().Header.Get(echo.HeaderAuthorization)) > 0 {
return []string{c.Request().Header.Get(echo.HeaderAuthorization)}, nil return []string{ctx.Request().Header.Get(echo.HeaderAuthorization)}, nil
} }
return []string{c.QueryParam("token")}, nil return []string{ctx.QueryParam("token")}, nil
}, },
}, },
})) }))
@ -168,7 +167,7 @@ func InitFile() http.Handler {
fileName := path.Base(filePath) fileName := path.Base(filePath)
w.Header().Add("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(fileName)) w.Header().Add("Content-Disposition", "attachment; filename*=utf-8''"+url.PathEscape(fileName))
http.ServeFile(w, r, filePath) http.ServeFile(w, r, filePath)
//http.ServeFile(w, r, filePath) // http.ServeFile(w, r, filePath)
}) })
} }
@ -202,7 +201,7 @@ func InitDir() http.Handler {
list := strings.Split(files, ",") list := strings.Split(files, ",")
for _, v := range list { for _, v := range list {
if !file.Exists(v) { if !file.Exists(v) {
// c.JSON(common_err.SERVICE_ERROR, model.Result{ // return ctx.JSON(common_err.SERVICE_ERROR, model.Result{
// Success: common_err.FILE_DOES_NOT_EXIST, // Success: common_err.FILE_DOES_NOT_EXIST,
// Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST), // Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST),
// }) // })
@ -238,7 +237,7 @@ func InitDir() http.Handler {
err = ar.Create(w) err = ar.Create(w)
if err != nil { if err != nil {
// c.JSON(common_err.SERVICE_ERROR, model.Result{ // return ctx.JSON(common_err.SERVICE_ERROR, model.Result{
// Success: common_err.SERVICE_ERROR, // Success: common_err.SERVICE_ERROR,
// Message: common_err.GetMsg(common_err.SERVICE_ERROR), // Message: common_err.GetMsg(common_err.SERVICE_ERROR),
// Data: err.Error(), // Data: err.Error(),

View File

@ -39,20 +39,25 @@ func (s *connectionsStruct) GetConnectionByHost(host string) (connections []mode
s.db.Select("username,host,status,id").Where("host = ?", host).Find(&connections) s.db.Select("username,host,status,id").Where("host = ?", host).Find(&connections)
return return
} }
func (s *connectionsStruct) GetConnectionByID(id string) (connections model2.ConnectionsDBModel) { func (s *connectionsStruct) GetConnectionByID(id string) (connections model2.ConnectionsDBModel) {
s.db.Select("username,password,host,status,id,directories,mount_point,port").Where("id = ?", id).First(&connections) s.db.Select("username,password,host,status,id,directories,mount_point,port").Where("id = ?", id).First(&connections)
return return
} }
func (s *connectionsStruct) GetConnectionsList() (connections []model2.ConnectionsDBModel) { func (s *connectionsStruct) GetConnectionsList() (connections []model2.ConnectionsDBModel) {
s.db.Select("username,host,port,status,id,mount_point").Find(&connections) s.db.Select("username,host,port,status,id,mount_point").Find(&connections)
return return
} }
func (s *connectionsStruct) CreateConnection(connection *model2.ConnectionsDBModel) { func (s *connectionsStruct) CreateConnection(connection *model2.ConnectionsDBModel) {
s.db.Create(connection) s.db.Create(connection)
} }
func (s *connectionsStruct) UpdateConnection(connection *model2.ConnectionsDBModel) { func (s *connectionsStruct) UpdateConnection(connection *model2.ConnectionsDBModel) {
s.db.Save(connection) s.db.Save(connection)
} }
func (s *connectionsStruct) DeleteConnection(id string) { func (s *connectionsStruct) DeleteConnection(id string) {
s.db.Where("id= ?", id).Delete(&model.ConnectionsDBModel{}) s.db.Where("id= ?", id).Delete(&model.ConnectionsDBModel{})
} }
@ -66,9 +71,10 @@ func (s *connectionsStruct) MountSmaba(username, host, directory, port, mountPoi
fmt.Sprintf("username=%s,password=%s", username, password), fmt.Sprintf("username=%s,password=%s", username, password),
) )
return err return err
//str := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;MountCIFS " + username + " " + host + " " + directory + " " + port + " " + mountPoint + " " + password) // str := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;MountCIFS " + username + " " + host + " " + directory + " " + port + " " + mountPoint + " " + password)
//return str // return str
} }
func (s *connectionsStruct) UnmountSmaba(mountPoint string) error { func (s *connectionsStruct) UnmountSmaba(mountPoint string) error {
return mount.Unmount(mountPoint) return mount.Unmount(mountPoint)
} }

View File

@ -14,8 +14,8 @@ import (
"path/filepath" "path/filepath"
"strings" "strings"
"github.com/IceWhaleTech/CasaOS-Common/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/file" "github.com/IceWhaleTech/CasaOS/pkg/utils/file"
"github.com/IceWhaleTech/CasaOS/service/model" "github.com/IceWhaleTech/CasaOS/service/model"
model2 "github.com/IceWhaleTech/CasaOS/service/model" model2 "github.com/IceWhaleTech/CasaOS/service/model"
@ -47,19 +47,23 @@ func (s *sharesStruct) GetSharesByName(name string) (shares []model2.SharesDBMod
return return
} }
func (s *sharesStruct) GetSharesByPath(path string) (shares []model2.SharesDBModel) { func (s *sharesStruct) GetSharesByPath(path string) (shares []model2.SharesDBModel) {
s.db.Select("anonymous,path,id").Where("path = ?", path).Find(&shares) s.db.Select("anonymous,path,id").Where("path = ?", path).Find(&shares)
return return
} }
func (s *sharesStruct) GetSharesList() (shares []model2.SharesDBModel) { func (s *sharesStruct) GetSharesList() (shares []model2.SharesDBModel) {
s.db.Select("anonymous,path,id").Find(&shares) s.db.Select("anonymous,path,id").Find(&shares)
return return
} }
func (s *sharesStruct) CreateShare(share model2.SharesDBModel) { func (s *sharesStruct) CreateShare(share model2.SharesDBModel) {
s.db.Create(&share) s.db.Create(&share)
s.InitSambaConfig() s.InitSambaConfig()
s.UpdateConfigFile() s.UpdateConfigFile()
} }
func (s *sharesStruct) DeleteShare(id string) { func (s *sharesStruct) DeleteShare(id string) {
s.db.Where("id= ?", id).Delete(&model.SharesDBModel{}) s.db.Where("id= ?", id).Delete(&model.SharesDBModel{})
s.UpdateConfigFile() s.UpdateConfigFile()
@ -68,8 +72,8 @@ func (s *sharesStruct) DeleteShare(id string) {
func (s *sharesStruct) UpdateConfigFile() { func (s *sharesStruct) UpdateConfigFile() {
shares := []model2.SharesDBModel{} shares := []model2.SharesDBModel{}
s.db.Select("anonymous,path").Find(&shares) s.db.Select("anonymous,path").Find(&shares)
//generated config file // generated config file
var configStr = "" configStr := ""
for _, share := range shares { for _, share := range shares {
dirName := filepath.Base(share.Path) dirName := filepath.Base(share.Path)
configStr += ` configStr += `
@ -86,12 +90,12 @@ force user = root
` `
} }
//write config file // write config file
file.WriteToPath([]byte(configStr), "/etc/samba", "smb.casa.conf") file.WriteToPath([]byte(configStr), "/etc/samba", "smb.casa.conf")
//restart samba // restart samba
command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;RestartSMBD") command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;RestartSMBD")
} }
func (s *sharesStruct) InitSambaConfig() { func (s *sharesStruct) InitSambaConfig() {
if file.Exists("/etc/samba/smb.conf") { if file.Exists("/etc/samba/smb.conf") {
str := file.ReadLine(1, "/etc/samba/smb.conf") str := file.ReadLine(1, "/etc/samba/smb.conf")
@ -99,7 +103,7 @@ func (s *sharesStruct) InitSambaConfig() {
return return
} }
file.MoveFile("/etc/samba/smb.conf", "/etc/samba/smb.conf.bak") file.MoveFile("/etc/samba/smb.conf", "/etc/samba/smb.conf.bak")
var smbConf = "" smbConf := ""
smbConf += `# Copyright (c) 2021-2022 CasaOS Inc. All rights reserved. smbConf += `# Copyright (c) 2021-2022 CasaOS Inc. All rights reserved.
# #
# #
@ -150,7 +154,6 @@ func (s *sharesStruct) InitSambaConfig() {
include=/etc/samba/smb.casa.conf` include=/etc/samba/smb.casa.conf`
file.WriteToPath([]byte(smbConf), "/etc/samba", "smb.conf") file.WriteToPath([]byte(smbConf), "/etc/samba", "smb.conf")
} }
} }
func NewSharesService(db *gorm.DB) SharesService { func NewSharesService(db *gorm.DB) SharesService {

View File

@ -4,22 +4,23 @@ import (
"encoding/json" "encoding/json"
"errors" "errors"
"fmt" "fmt"
"io/ioutil" "io"
net2 "net" net2 "net"
"os" "os"
"os/exec"
"path/filepath" "path/filepath"
"runtime" "runtime"
"strconv" "strconv"
"strings" "strings"
"time" "time"
"github.com/IceWhaleTech/CasaOS-Common/utils/command"
exec2 "github.com/IceWhaleTech/CasaOS-Common/utils/exec"
"github.com/IceWhaleTech/CasaOS-Common/utils/file" "github.com/IceWhaleTech/CasaOS-Common/utils/file"
"github.com/IceWhaleTech/CasaOS-Common/utils/logger" "github.com/IceWhaleTech/CasaOS-Common/utils/logger"
"github.com/IceWhaleTech/CasaOS/common" "github.com/IceWhaleTech/CasaOS/common"
"github.com/IceWhaleTech/CasaOS/model" "github.com/IceWhaleTech/CasaOS/model"
"github.com/IceWhaleTech/CasaOS/pkg/config" "github.com/IceWhaleTech/CasaOS/pkg/config"
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err" "github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
"github.com/IceWhaleTech/CasaOS/pkg/utils/httper" "github.com/IceWhaleTech/CasaOS/pkg/utils/httper"
"github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper" "github.com/IceWhaleTech/CasaOS/pkg/utils/ip_helper"
@ -119,6 +120,7 @@ func (c *systemService) GetDeviceInfo() model.DeviceInfo {
return m return m
} }
func (c *systemService) GenreateSystemEntry() { func (c *systemService) GenreateSystemEntry() {
modelsPath := "/var/lib/casaos/www/modules" modelsPath := "/var/lib/casaos/www/modules"
entryFileName := "entry.json" entryFileName := "entry.json"
@ -141,15 +143,14 @@ func (c *systemService) GenreateSystemEntry() {
} }
json = strings.TrimRight(json, ",") json = strings.TrimRight(json, ",")
json += "]" json += "]"
err = os.WriteFile(entryFilePath, []byte(json), 0666) err = os.WriteFile(entryFilePath, []byte(json), 0o666)
if err != nil { if err != nil {
logger.Error("write entry file error", zap.Error(err)) logger.Error("write entry file error", zap.Error(err))
return return
} }
} }
func (c *systemService) GetSystemEntry() string {
func (c *systemService) GetSystemEntry() string {
modelsPath := "/var/lib/casaos/www/modules" modelsPath := "/var/lib/casaos/www/modules"
entryFileName := "entry.json" entryFileName := "entry.json"
dir, err := os.ReadDir(modelsPath) dir, err := os.ReadDir(modelsPath)
@ -174,6 +175,7 @@ func (c *systemService) GetSystemEntry() string {
} }
return json return json
} }
func (c *systemService) GetMacAddress() (string, error) { func (c *systemService) GetMacAddress() (string, error) {
interfaces, err := net.Interfaces() interfaces, err := net.Interfaces()
if err != nil { if err != nil {
@ -235,7 +237,11 @@ func (c *systemService) CreateFile(path string) (int, error) {
} }
func (c *systemService) GetDeviceTree() string { func (c *systemService) GetDeviceTree() string {
return command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDeviceTree") if output, err := command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDeviceTree"); err != nil {
return ""
} else {
return output
}
} }
func (c *systemService) GetSysInfo() host.InfoStat { func (c *systemService) GetSysInfo() host.InfoStat {
@ -255,7 +261,11 @@ func (c *systemService) GetDiskInfo() *disk.UsageStat {
} }
func (c *systemService) GetNetState(name string) string { func (c *systemService) GetNetState(name string) string {
return command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;CatNetCardState " + name) if output, err := command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;CatNetCardState " + name); err != nil {
return ""
} else {
return output
}
} }
func (c *systemService) GetDirPathOne(path string) (m model.Path) { func (c *systemService) GetDirPathOne(path string) (m model.Path) {
@ -352,7 +362,12 @@ func (c *systemService) GetNet(physics bool) []string {
if physics { if physics {
t = "2" t = "2"
} }
return command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetNetCard " + t)
if output, err := command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;GetNetCard " + t); err != nil {
return []string{}
} else {
return strings.Split(output, "\n")
}
} }
func (s *systemService) UpdateSystemVersion(version string) { func (s *systemService) UpdateSystemVersion(version string) {
@ -364,10 +379,10 @@ func (s *systemService) UpdateSystemVersion(version string) {
file.CreateFile(config.AppInfo.LogPath + "/upgrade.log") file.CreateFile(config.AppInfo.LogPath + "/upgrade.log")
// go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/LinkLeong/casaos-alpha/main/update.sh | bash") // go command2.OnlyExec("curl -fsSL https://raw.githubusercontent.com/LinkLeong/casaos-alpha/main/update.sh | bash")
if len(config.ServerInfo.UpdateUrl) > 0 { if len(config.ServerInfo.UpdateUrl) > 0 {
go command2.OnlyExec("curl -fsSL " + config.ServerInfo.UpdateUrl + " | bash") go command.OnlyExec("curl -fsSL " + config.ServerInfo.UpdateUrl + " | bash")
} else { } else {
osRelease, _ := file.ReadOSRelease() osRelease, _ := file.ReadOSRelease()
go command2.OnlyExec("curl -fsSL https://get.casaos.io/update?t=" + osRelease["MANUFACTURER"] + " | bash") go command.OnlyExec("curl -fsSL https://get.casaos.io/update?t=" + osRelease["MANUFACTURER"] + " | bash")
} }
// s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version) // s.log.Error(config.AppInfo.ProjectPath + "/shell/tool.sh -r " + version)
@ -375,15 +390,23 @@ func (s *systemService) UpdateSystemVersion(version string) {
} }
func (s *systemService) UpdateAssist() { func (s *systemService) UpdateAssist() {
command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/assist.sh") command.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/assist.sh")
} }
func (s *systemService) GetTimeZone() string { func (s *systemService) GetTimeZone() string {
return command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetTimeZone") if output, err := command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;GetTimeZone"); err != nil {
return ""
} else {
return output
}
} }
func (s *systemService) GetSystemConfigDebug() []string { func (s *systemService) GetSystemConfigDebug() []string {
return command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetSysInfo") if output, err := command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;GetSysInfo"); err != nil {
return []string{}
} else {
return strings.Split(output, "\n")
}
} }
func (s *systemService) UpAppOrderFile(str, id string) { func (s *systemService) UpAppOrderFile(str, id string) {
@ -411,7 +434,7 @@ func (s *systemService) GetCasaOSLogs(lineNumber int) string {
return err.Error() return err.Error()
} }
defer file.Close() defer file.Close()
content, err := ioutil.ReadAll(file) content, err := io.ReadAll(file)
if err != nil { if err != nil {
return err.Error() return err.Error()
} }
@ -510,9 +533,8 @@ func (s *systemService) GetCPUPower() map[string]string {
} }
func (s *systemService) SystemReboot() error { func (s *systemService) SystemReboot() error {
// cmd := exec.Command("/bin/bash", "-c", "reboot")
arg := []string{"6"} arg := []string{"6"}
cmd := exec.Command("init", arg...) cmd := exec2.Command("init", arg...)
_, err := cmd.CombinedOutput() _, err := cmd.CombinedOutput()
if err != nil { if err != nil {
return err return err
@ -522,7 +544,7 @@ func (s *systemService) SystemReboot() error {
func (s *systemService) SystemShutdown() error { func (s *systemService) SystemShutdown() error {
arg := []string{"0"} arg := []string{"0"}
cmd := exec.Command("init", arg...) cmd := exec2.Command("init", arg...)
_, err := cmd.CombinedOutput() _, err := cmd.CombinedOutput()
if err != nil { if err != nil {
return err return err