Compare commits
31 Commits
v0.3.5
...
v0.3.7-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
0f3d3e82f5 | ||
|
|
dd66f73157 | ||
|
|
cbbb907d6a | ||
|
|
ff6cdb6fda | ||
|
|
2eac040875 | ||
|
|
b41d855f73 | ||
|
|
182bc25343 | ||
|
|
12d5e5db03 | ||
|
|
455d226dcd | ||
|
|
f0448cd1b9 | ||
|
|
aff18fa091 | ||
|
|
80c347ac01 | ||
|
|
8113f51cf7 | ||
|
|
4f491fa22f | ||
|
|
3935489d8b | ||
|
|
d14381e6a2 | ||
|
|
466350dd21 | ||
|
|
fb39529e8f | ||
|
|
4434ba522b | ||
|
|
aac8fe85ba | ||
|
|
314dbdab57 | ||
|
|
727aca564b | ||
|
|
70ba4d5e3d | ||
|
|
8d088afcc5 | ||
|
|
34f35bbf20 | ||
|
|
b6f413b9e9 | ||
|
|
091be6d12e | ||
|
|
aefa68d8f8 | ||
|
|
9aed323d8d | ||
|
|
eba607fc53 | ||
|
|
d064f20a04 |
4
.github/workflows/push_events_to_discord.yml
vendored
@@ -36,13 +36,13 @@ jobs:
|
|||||||
webhook: ${{ secrets.Discord_CasaOS_App_Request_Webhook }}
|
webhook: ${{ secrets.Discord_CasaOS_App_Request_Webhook }}
|
||||||
|
|
||||||
- name: Bug Issues & Comments
|
- name: Bug Issues & Comments
|
||||||
if: ${{ ( github.event_name == 'issues' || github.event_name == 'issue_comment' ) && contains(github.event.issue.labels.*.name, 'bug') && !contains(!github.event.issue.labels.*.name, 'alpha') }}
|
if: ${{ ( github.event_name == 'issues' || github.event_name == 'issue_comment' ) && contains(github.event.issue.labels.*.name, 'bug') && !contains(github.event.issue.labels.*.name, 'alpha') }}
|
||||||
uses: joseph-montanez/forward-event-action@v3.0.0
|
uses: joseph-montanez/forward-event-action@v3.0.0
|
||||||
with:
|
with:
|
||||||
webhook: ${{ secrets.Discord_CasaOS_Bug_Webhook }}
|
webhook: ${{ secrets.Discord_CasaOS_Bug_Webhook }}
|
||||||
|
|
||||||
- name: Alpha Issues & Comments
|
- name: Alpha Issues & Comments
|
||||||
if: ${{ ( github.event_name == 'issues' || github.event_name == 'issue_comment' ) && contains(!github.event.issue.labels.*.name, 'alpha') }}
|
if: ${{ ( github.event_name == 'issues' || github.event_name == 'issue_comment' ) && contains(github.event.issue.labels.*.name, 'alpha') }}
|
||||||
uses: joseph-montanez/forward-event-action@v3.0.0
|
uses: joseph-montanez/forward-event-action@v3.0.0
|
||||||
with:
|
with:
|
||||||
webhook: ${{ secrets.Discord_CasaOS_Alpha_Webhook }}
|
webhook: ${{ secrets.Discord_CasaOS_Alpha_Webhook }}
|
||||||
|
|||||||
47
.github/workflows/release.yml
vendored
Normal file
@@ -0,0 +1,47 @@
|
|||||||
|
name: goreleaser
|
||||||
|
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- v*.*.*
|
||||||
|
|
||||||
|
permissions:
|
||||||
|
contents: write
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
goreleaser:
|
||||||
|
runs-on: ubuntu-22.04
|
||||||
|
steps:
|
||||||
|
-
|
||||||
|
name: Install dependencies for cross-compiling
|
||||||
|
run: |
|
||||||
|
sudo apt update
|
||||||
|
sudo apt-get --no-install-recommends --yes install \
|
||||||
|
libc6-dev-amd64-cross \
|
||||||
|
gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
|
||||||
|
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross
|
||||||
|
-
|
||||||
|
name: Checkout
|
||||||
|
uses: actions/checkout@v2
|
||||||
|
with:
|
||||||
|
fetch-depth: 0
|
||||||
|
-
|
||||||
|
name: Fetch all tags
|
||||||
|
run: git fetch --force --tags
|
||||||
|
-
|
||||||
|
name: Set up Go
|
||||||
|
uses: actions/setup-go@v2
|
||||||
|
with:
|
||||||
|
go-version: 1.19
|
||||||
|
-
|
||||||
|
name: Run GoReleaser
|
||||||
|
uses: goreleaser/goreleaser-action@v2
|
||||||
|
with:
|
||||||
|
# either 'goreleaser' (default) or 'goreleaser-pro'
|
||||||
|
distribution: goreleaser
|
||||||
|
version: latest
|
||||||
|
args: release --rm-dist
|
||||||
|
env:
|
||||||
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
|
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
|
||||||
|
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
||||||
5
.gitignore
vendored
@@ -28,13 +28,12 @@ gen
|
|||||||
/sql/
|
/sql/
|
||||||
/out/
|
/out/
|
||||||
/db/
|
/db/
|
||||||
/docs/
|
|
||||||
/web/
|
|
||||||
/conf/conf.ini
|
/conf/conf.ini
|
||||||
/conf/conf.conf
|
/conf/conf.conf
|
||||||
/conf/conf.json
|
/conf/conf.json
|
||||||
__debug_bin
|
__debug_bin
|
||||||
main
|
main
|
||||||
CasaOS
|
|
||||||
github.com
|
github.com
|
||||||
.all-contributorsrc
|
.all-contributorsrc
|
||||||
|
dist
|
||||||
|
CasaOS
|
||||||
167
.goreleaser.debug.yaml
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||||
|
# Make sure to check the documentation at https://goreleaser.com
|
||||||
|
project_name: casaos
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
# You may remove this if you don't use go modules.
|
||||||
|
- go mod tidy
|
||||||
|
builds:
|
||||||
|
- id: casaos-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-migration-tool-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- id: casaos-migration-tool-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
- id: casaos-migration-tool-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
gcflags:
|
||||||
|
- all=-N -l
|
||||||
|
ldflags:
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
archives:
|
||||||
|
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}"
|
||||||
|
id: casaos
|
||||||
|
builds:
|
||||||
|
- casaos-amd64
|
||||||
|
- casaos-arm64
|
||||||
|
- casaos-arm-7
|
||||||
|
replacements:
|
||||||
|
arm: arm-7
|
||||||
|
files:
|
||||||
|
- build/**/*
|
||||||
|
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}"
|
||||||
|
id: casaos-migration-tool
|
||||||
|
builds:
|
||||||
|
- casaos-migration-tool-amd64
|
||||||
|
- casaos-migration-tool-arm64
|
||||||
|
- casaos-migration-tool-arm-7
|
||||||
|
replacements:
|
||||||
|
arm: arm-7
|
||||||
|
files:
|
||||||
|
- build/sysroot/etc/**/*
|
||||||
|
checksum:
|
||||||
|
name_template: "checksums.txt"
|
||||||
|
snapshot:
|
||||||
|
name_template: "{{ incpatch .Version }}"
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- "^docs:"
|
||||||
|
- "^test:"
|
||||||
|
# release:
|
||||||
|
# github:
|
||||||
|
# owner: IceWhaleTech
|
||||||
|
# name: CasaOS
|
||||||
|
# draft: true
|
||||||
|
# prerelease: auto
|
||||||
|
# mode: replace
|
||||||
|
# name_template: "v{{ .Version }}"
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: IceWhaleTech
|
||||||
|
name: CasaOS
|
||||||
|
draft: true
|
||||||
|
prerelease: auto
|
||||||
|
mode: replace
|
||||||
|
name_template: "v{{ .Version }}"
|
||||||
167
.goreleaser.yaml
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
# This is an example .goreleaser.yml file with some sensible defaults.
|
||||||
|
# Make sure to check the documentation at https://goreleaser.com
|
||||||
|
project_name: casaos
|
||||||
|
before:
|
||||||
|
hooks:
|
||||||
|
# You may remove this if you don't use go modules.
|
||||||
|
- go mod tidy
|
||||||
|
builds:
|
||||||
|
- id: casaos-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
hooks:
|
||||||
|
post:
|
||||||
|
- find build/sysroot -type f | xargs -L 1 realpath --relative-to=build/sysroot > build/sysroot.manifest
|
||||||
|
- id: casaos-migration-tool-amd64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=x86_64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- amd64
|
||||||
|
- id: casaos-migration-tool-arm64
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=aarch64-linux-gnu-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm64
|
||||||
|
- id: casaos-migration-tool-arm-7
|
||||||
|
binary: build/sysroot/usr/bin/casaos-migration-tool
|
||||||
|
main: ./cmd/migration-tool
|
||||||
|
env:
|
||||||
|
- CGO_ENABLED=1
|
||||||
|
- CC=arm-linux-gnueabihf-gcc
|
||||||
|
ldflags:
|
||||||
|
- -s
|
||||||
|
- -w
|
||||||
|
- -extldflags "-static"
|
||||||
|
tags:
|
||||||
|
- musl
|
||||||
|
- netgo
|
||||||
|
goos:
|
||||||
|
- linux
|
||||||
|
goarch:
|
||||||
|
- arm
|
||||||
|
goarm:
|
||||||
|
- "7"
|
||||||
|
archives:
|
||||||
|
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-v{{ .Version }}"
|
||||||
|
id: casaos
|
||||||
|
builds:
|
||||||
|
- casaos-amd64
|
||||||
|
- casaos-arm64
|
||||||
|
- casaos-arm-7
|
||||||
|
replacements:
|
||||||
|
arm: arm-7
|
||||||
|
files:
|
||||||
|
- build/**/*
|
||||||
|
- name_template: "{{ .Os }}-{{ .Arch }}-{{ .ProjectName }}-migration-tool-v{{ .Version }}"
|
||||||
|
id: casaos-migration-tool
|
||||||
|
builds:
|
||||||
|
- casaos-migration-tool-amd64
|
||||||
|
- casaos-migration-tool-arm64
|
||||||
|
- casaos-migration-tool-arm-7
|
||||||
|
replacements:
|
||||||
|
arm: arm-7
|
||||||
|
files:
|
||||||
|
- build/sysroot/etc/**/*
|
||||||
|
checksum:
|
||||||
|
name_template: "checksums.txt"
|
||||||
|
snapshot:
|
||||||
|
name_template: "{{ incpatch .Version }}"
|
||||||
|
changelog:
|
||||||
|
sort: asc
|
||||||
|
filters:
|
||||||
|
exclude:
|
||||||
|
- "^docs:"
|
||||||
|
- "^test:"
|
||||||
|
# release:
|
||||||
|
# github:
|
||||||
|
# owner: IceWhaleTech
|
||||||
|
# name: CasaOS
|
||||||
|
# draft: true
|
||||||
|
# prerelease: auto
|
||||||
|
# mode: replace
|
||||||
|
# name_template: "v{{ .Version }}"
|
||||||
|
release:
|
||||||
|
github:
|
||||||
|
owner: IceWhaleTech
|
||||||
|
name: CasaOS
|
||||||
|
draft: true
|
||||||
|
prerelease: auto
|
||||||
|
mode: replace
|
||||||
|
name_template: "v{{ .Version }}"
|
||||||
15
CHANGELOG.md
@@ -18,7 +18,20 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
## [0.3.5-alpha] - 2022-08-08
|
|
||||||
|
## [0.3.6-alpha.1] - 2022-09-06
|
||||||
|
|
||||||
|
### Added
|
||||||
|
- [System] Added power and temperature info to performance widget (Intel)
|
||||||
|
- [Apps] Custom links can be added to Apps section
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
- [Apps] Fixed the problem of not being able to modify some App settings ([#510](https://github.com/IceWhaleTech/CasaOS/issues/510))
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
- [System] Architecture optimization. Improved performance.
|
||||||
|
|
||||||
|
## [0.3.5] - 2022-08-23
|
||||||
|
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
|
|||||||
1
UI
177
build/scripts/migration/script.d/03-migrate-casaos.sh
Normal file
@@ -0,0 +1,177 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
# functions
|
||||||
|
__info() {
|
||||||
|
echo -e "🟩 ${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__info_done() {
|
||||||
|
echo -e "✅ ${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__warning() {
|
||||||
|
echo -e "🟨 ${1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
__error() {
|
||||||
|
echo "🟥 ${1}"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
__is_version_gt() {
|
||||||
|
test "$(echo "$@" | tr " " "\n" | sort -V | head -n 1)" != "$1"
|
||||||
|
}
|
||||||
|
__normalize_version() {
|
||||||
|
local version
|
||||||
|
if [ "${1::1}" = "v" ]; then
|
||||||
|
version="${1:1}"
|
||||||
|
else
|
||||||
|
version="${1}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
echo "$version"
|
||||||
|
}
|
||||||
|
|
||||||
|
__is_migration_needed() {
|
||||||
|
local version1
|
||||||
|
local version2
|
||||||
|
|
||||||
|
version1=$(__normalize_version "${1}")
|
||||||
|
version2=$(__normalize_version "${2}")
|
||||||
|
|
||||||
|
if [ "${version1}" = "${version2}" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "CURRENT_VERSION_NOT_FOUND" = "${version1}" ]; then
|
||||||
|
return 1
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "LEGACY_WITHOUT_VERSION" = "${version1}" ]; then
|
||||||
|
return 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
__is_version_gt "${version2}" "${version1}"
|
||||||
|
}
|
||||||
|
|
||||||
|
BUILD_PATH=$(dirname "${BASH_SOURCE[0]}")/../../..
|
||||||
|
SOURCE_ROOT=${BUILD_PATH}/sysroot
|
||||||
|
|
||||||
|
APP_NAME="casaos"
|
||||||
|
|
||||||
|
# check if migration is needed
|
||||||
|
SOURCE_BIN_PATH=${SOURCE_ROOT}/usr/bin
|
||||||
|
SOURCE_BIN_FILE=${SOURCE_BIN_PATH}/${APP_NAME}
|
||||||
|
|
||||||
|
CURRENT_BIN_PATH=/usr/bin
|
||||||
|
CURRENT_BIN_PATH_LEGACY=/usr/local/bin
|
||||||
|
CURRENT_BIN_FILE=${CURRENT_BIN_PATH}/${APP_NAME}
|
||||||
|
CURRENT_BIN_FILE_LEGACY=$(realpath -e ${CURRENT_BIN_PATH_LEGACY}/${APP_NAME} || which ${APP_NAME} || echo CURRENT_BIN_FILE_LEGACY_NOT_FOUND)
|
||||||
|
|
||||||
|
SOURCE_VERSION="$(${SOURCE_BIN_FILE} -v)"
|
||||||
|
CURRENT_VERSION="$(${CURRENT_BIN_FILE} -v || ${CURRENT_BIN_FILE_LEGACY} -v || (stat "${CURRENT_BIN_FILE_LEGACY}" > /dev/null && echo LEGACY_WITHOUT_VERSION) || echo CURRENT_VERSION_NOT_FOUND)"
|
||||||
|
|
||||||
|
__info_done "CURRENT_VERSION: ${CURRENT_VERSION}"
|
||||||
|
__info_done "SOURCE_VERSION: ${SOURCE_VERSION}"
|
||||||
|
|
||||||
|
NEED_MIGRATION=$(__is_migration_needed "${CURRENT_VERSION}" "${SOURCE_VERSION}" && echo "true" || echo "false")
|
||||||
|
|
||||||
|
if [ "${NEED_MIGRATION}" = "false" ]; then
|
||||||
|
__info_done "Migration is not needed."
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
ARCH="unknown"
|
||||||
|
|
||||||
|
case $(uname -m) in
|
||||||
|
x86_64)
|
||||||
|
ARCH="amd64"
|
||||||
|
;;
|
||||||
|
aarch64)
|
||||||
|
ARCH="arm64"
|
||||||
|
;;
|
||||||
|
armv7l)
|
||||||
|
ARCH="arm-7"
|
||||||
|
;;
|
||||||
|
*)
|
||||||
|
__error "Unsupported architecture"
|
||||||
|
;;
|
||||||
|
esac
|
||||||
|
|
||||||
|
__info "ARCH: ${ARCH}"
|
||||||
|
|
||||||
|
MIGRATION_SERVICE_DIR=${1}
|
||||||
|
|
||||||
|
if [ -z "${MIGRATION_SERVICE_DIR}" ]; then
|
||||||
|
MIGRATION_SERVICE_DIR=${BUILD_PATH}/scripts/migration/service.d/${APP_NAME}
|
||||||
|
fi
|
||||||
|
MIGRATION_LIST_FILE=${MIGRATION_SERVICE_DIR}/migration.list
|
||||||
|
MIGRATION_PATH=()
|
||||||
|
|
||||||
|
CURRENT_VERSION_FOUND="false"
|
||||||
|
|
||||||
|
# a VERSION_PAIR looks like "v0.3.5 <url>"
|
||||||
|
#
|
||||||
|
# - "v0.3.5" is the current version installed on this host
|
||||||
|
# - "<url>" is the url of the migration tool
|
||||||
|
while read -r VERSION_PAIR; do
|
||||||
|
if [ -z "${VERSION_PAIR}" ]; then
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
# obtain "v0.3.5" from "v0.3.5 v0.3.6-alpha2"
|
||||||
|
VER1=$(echo "${VERSION_PAIR}" | cut -d' ' -f1)
|
||||||
|
|
||||||
|
# obtain "<url>" from "v0.3.5 <url>"
|
||||||
|
URL=$(eval echo "${VERSION_PAIR}" | cut -d' ' -f2)
|
||||||
|
|
||||||
|
if [ "${CURRENT_VERSION}" = "${VER1// /}" ] || [ "${CURRENT_VERSION}" = "LEGACY_WITHOUT_VERSION" ]; then
|
||||||
|
CURRENT_VERSION_FOUND="true"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if [ "${CURRENT_VERSION_FOUND}" = "true" ]; then
|
||||||
|
MIGRATION_PATH+=("${URL// /}")
|
||||||
|
fi
|
||||||
|
done < "${MIGRATION_LIST_FILE}"
|
||||||
|
|
||||||
|
if [ ${#MIGRATION_PATH[@]} -eq 0 ]; then
|
||||||
|
__warning "No migration path found from ${CURRENT_VERSION} to ${SOURCE_VERSION}"
|
||||||
|
exit 0
|
||||||
|
fi
|
||||||
|
|
||||||
|
pushd "${MIGRATION_SERVICE_DIR}"
|
||||||
|
|
||||||
|
{ for URL in "${MIGRATION_PATH[@]}"; do
|
||||||
|
MIGRATION_TOOL_FILE=$(basename "${URL}")
|
||||||
|
|
||||||
|
if [ -f "${MIGRATION_TOOL_FILE}" ]; then
|
||||||
|
__info "Migration tool ${MIGRATION_TOOL_FILE} exists. Skip downloading."
|
||||||
|
continue
|
||||||
|
fi
|
||||||
|
|
||||||
|
__info "Dowloading ${URL}..."
|
||||||
|
curl -fsSL -o "${MIGRATION_TOOL_FILE}" -O "${URL}"
|
||||||
|
done
|
||||||
|
} || {
|
||||||
|
popd
|
||||||
|
__error "Failed to download migration tools"
|
||||||
|
}
|
||||||
|
|
||||||
|
{
|
||||||
|
for URL in "${MIGRATION_PATH[@]}"; do
|
||||||
|
MIGRATION_TOOL_FILE=$(basename "${URL}")
|
||||||
|
__info "Extracting ${MIGRATION_TOOL_FILE}..."
|
||||||
|
tar zxvf "${MIGRATION_TOOL_FILE}" || __error "Failed to extract ${MIGRATION_TOOL_FILE}"
|
||||||
|
|
||||||
|
MIGRATION_TOOL_PATH=build/sysroot/usr/bin/${APP_NAME}-migration-tool
|
||||||
|
__info "Running ${MIGRATION_TOOL_PATH}..."
|
||||||
|
${MIGRATION_TOOL_PATH}
|
||||||
|
done
|
||||||
|
} || {
|
||||||
|
popd
|
||||||
|
__error "Failed to extract and run migration tools"
|
||||||
|
}
|
||||||
|
|
||||||
|
popd
|
||||||
3
build/scripts/migration/service.d/casaos/migration.list
Normal file
@@ -0,0 +1,3 @@
|
|||||||
|
LEGACY_WITHOUT_VERSION https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
|
v0.3.5 https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
|
v0.3.5.1 https://github.com/IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
54
build/scripts/setup/script.d/03-setup-casaos.sh
Executable file
@@ -0,0 +1,54 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
BUILD_PATH=$(dirname "${BASH_SOURCE[0]}")/../../..
|
||||||
|
|
||||||
|
APP_NAME_SHORT=casaos
|
||||||
|
|
||||||
|
__get_setup_script_directory_by_os_release() {
|
||||||
|
pushd "$(dirname "${BASH_SOURCE[0]}")/../service.d/${APP_NAME_SHORT}" >/dev/null
|
||||||
|
|
||||||
|
{
|
||||||
|
# shellcheck source=/dev/null
|
||||||
|
{
|
||||||
|
source /etc/os-release
|
||||||
|
{
|
||||||
|
pushd "${ID}"/"${VERSION_CODENAME}" >/dev/null
|
||||||
|
} || {
|
||||||
|
pushd "${ID}" >/dev/null
|
||||||
|
} || {
|
||||||
|
pushd "${ID_LIKE}" >/dev/null
|
||||||
|
} || {
|
||||||
|
echo "Unsupported OS: ${ID} ${VERSION_CODENAME} (${ID_LIKE})"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
pwd
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
|
|
||||||
|
} || {
|
||||||
|
echo "Unsupported OS: unknown"
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
popd >/dev/null
|
||||||
|
}
|
||||||
|
|
||||||
|
SETUP_SCRIPT_DIRECTORY=$(__get_setup_script_directory_by_os_release)
|
||||||
|
SETUP_SCRIPT_FILENAME="setup-${APP_NAME_SHORT}.sh"
|
||||||
|
|
||||||
|
SETUP_SCRIPT_FILEPATH="${SETUP_SCRIPT_DIRECTORY}/${SETUP_SCRIPT_FILENAME}"
|
||||||
|
|
||||||
|
{
|
||||||
|
echo "🟩 Running ${SETUP_SCRIPT_FILENAME}..."
|
||||||
|
$SHELL "${SETUP_SCRIPT_FILEPATH}" "${BUILD_PATH}"
|
||||||
|
} || {
|
||||||
|
echo "🟥 ${SETUP_SCRIPT_FILENAME} failed."
|
||||||
|
exit 1
|
||||||
|
}
|
||||||
|
|
||||||
|
echo "✅ ${SETUP_SCRIPT_FILENAME} finished."
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../setup-casaos.sh
|
||||||
45
build/scripts/setup/service.d/casaos/debian/setup-casaos.sh
Normal file
@@ -0,0 +1,45 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: LinkLeong link@icewhale.org
|
||||||
|
# @Date: 2022-08-25 11:41:22
|
||||||
|
# @LastEditors: LinkLeong
|
||||||
|
# @LastEditTime: 2022-08-31 17:54:17
|
||||||
|
# @FilePath: /CasaOS/build/scripts/setup/service.d/casaos/debian/setup-casaos.sh
|
||||||
|
# @Description:
|
||||||
|
|
||||||
|
# @Website: https://www.casaos.io
|
||||||
|
# Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
###
|
||||||
|
|
||||||
|
set -e
|
||||||
|
|
||||||
|
APP_NAME="casaos"
|
||||||
|
|
||||||
|
# copy config files
|
||||||
|
CONF_PATH=/etc/casaos
|
||||||
|
OLD_CONF_PATH=/etc/casaos.conf
|
||||||
|
CONF_FILE=${CONF_PATH}/${APP_NAME}.conf
|
||||||
|
CONF_FILE_SAMPLE=${CONF_PATH}/${APP_NAME}.conf.sample
|
||||||
|
|
||||||
|
|
||||||
|
if [ -f "${OLD_CONF_PATH}" ]; then
|
||||||
|
echo "copy old conf"
|
||||||
|
cp "${OLD_CONF_PATH}" "${CONF_FILE}"
|
||||||
|
fi
|
||||||
|
if [ ! -f "${CONF_FILE}" ]; then
|
||||||
|
echo "Initializing config file..."
|
||||||
|
cp -v "${CONF_FILE_SAMPLE}" "${CONF_FILE}"
|
||||||
|
fi
|
||||||
|
|
||||||
|
if systemctl is-active "${APP_NAME}.service" &>/dev/null ;then
|
||||||
|
echo "server started"
|
||||||
|
else
|
||||||
|
# enable and start service
|
||||||
|
systemctl daemon-reload
|
||||||
|
|
||||||
|
echo "Enabling service..."
|
||||||
|
systemctl enable --force --no-ask-password "${APP_NAME}.service"
|
||||||
|
|
||||||
|
#echo "Starting service..."
|
||||||
|
#systemctl start --force --no-ask-password "${APP_NAME}.service"
|
||||||
|
fi
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
../setup-casaos.sh
|
||||||
1
build/scripts/setup/service.d/casaos/ubuntu/setup-casaos.sh
Symbolic link
@@ -0,0 +1 @@
|
|||||||
|
../debian/setup-casaos.sh
|
||||||
22
build/sysroot/etc/casaos/casaos.conf.sample
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
[app]
|
||||||
|
PAGE_SIZE = 10
|
||||||
|
RuntimeRootPath = runtime/
|
||||||
|
LogPath = /var/log/casaos/
|
||||||
|
LogSaveName = log
|
||||||
|
LogFileExt = log
|
||||||
|
DateStrFormat = 20060102
|
||||||
|
DateTimeFormat = 2006-01-02 15:04:05
|
||||||
|
TimeFormat = 15:04:05
|
||||||
|
DateFormat = 2006-01-02
|
||||||
|
DBPath = /var/lib/casaos
|
||||||
|
ShellPath = /usr/share/casaos/shell
|
||||||
|
UserDataPath = /var/lib/casaos/conf
|
||||||
|
|
||||||
|
[server]
|
||||||
|
RunMode = release
|
||||||
|
ServerApi = https://api.casaos.io/casaos-api
|
||||||
|
Handshake = socket.casaos.io
|
||||||
|
Token =
|
||||||
|
USBAutoMount =
|
||||||
|
|
||||||
|
[system]
|
||||||
13
build/sysroot/usr/lib/systemd/system/casaos.service
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
[Unit]
|
||||||
|
After=casaos-gateway.service
|
||||||
|
ConditionFileNotEmpty=/etc/casaos/casaos.conf
|
||||||
|
Description=CasaOS Main Service
|
||||||
|
|
||||||
|
[Service]
|
||||||
|
ExecStart=/usr/bin/casaos -c /etc/casaos/casaos.conf
|
||||||
|
PIDFile=/var/run/casaos/casaos.pid
|
||||||
|
Restart=always
|
||||||
|
Type=notify
|
||||||
|
|
||||||
|
[Install]
|
||||||
|
WantedBy=multi-user.target
|
||||||
@@ -385,5 +385,4 @@ CheckServiceStatus(){
|
|||||||
}
|
}
|
||||||
UDEVILUmount(){
|
UDEVILUmount(){
|
||||||
$sudo_cmd udevil umount -f $1
|
$sudo_cmd udevil umount -f $1
|
||||||
}
|
}
|
||||||
|
|
||||||
12
build/sysroot/usr/share/casaos/shell/update.sh
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
#!/bin/bash
|
||||||
|
###
|
||||||
|
# @Author: LinkLeong link@icewhale.com
|
||||||
|
# @Date: 2022-06-30 10:08:33
|
||||||
|
# @LastEditors: LinkLeong
|
||||||
|
# @LastEditTime: 2022-09-01 22:33:06
|
||||||
|
# @FilePath: /CasaOS/build/sysroot/usr/share/casaos/shell/update.sh
|
||||||
|
# @Description:
|
||||||
|
###
|
||||||
|
|
||||||
|
|
||||||
|
curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/update.sh | bash
|
||||||
37
cmd/migration-tool/log.go
Normal file
@@ -0,0 +1,37 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"os"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Logger struct {
|
||||||
|
DebugMode bool
|
||||||
|
|
||||||
|
_debug *log.Logger
|
||||||
|
_info *log.Logger
|
||||||
|
_error *log.Logger
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewLogger() *Logger {
|
||||||
|
return &Logger{
|
||||||
|
DebugMode: false,
|
||||||
|
_debug: log.New(os.Stdout, "DEBUG: ", 0),
|
||||||
|
_info: log.New(os.Stdout, "", 0),
|
||||||
|
_error: log.New(os.Stderr, "ERROR: ", 0),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Debug(format string, v ...interface{}) {
|
||||||
|
if l.DebugMode {
|
||||||
|
l._debug.Printf(format, v...)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Info(format string, v ...interface{}) {
|
||||||
|
l._info.Printf(format, v...)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (l *Logger) Error(format string, v ...interface{}) {
|
||||||
|
l._error.Printf(format, v...)
|
||||||
|
}
|
||||||
120
cmd/migration-tool/main.go
Normal file
@@ -0,0 +1,120 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-08-23 18:09:11
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-31 14:17:51
|
||||||
|
* @FilePath: /CasaOS/cmd/migration-tool/main.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"os"
|
||||||
|
|
||||||
|
interfaces "github.com/IceWhaleTech/CasaOS-Common"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/systemctl"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Gateway/common"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
casaosServiceName = "casaos.service"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
_logger *Logger
|
||||||
|
sqliteDB *gorm.DB
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
configFlag = ""
|
||||||
|
dbFlag = ""
|
||||||
|
)
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
config.InitSetup(configFlag)
|
||||||
|
|
||||||
|
if len(dbFlag) == 0 {
|
||||||
|
dbFlag = config.AppInfo.DBPath + "/db"
|
||||||
|
}
|
||||||
|
|
||||||
|
sqliteDB = sqlite.GetDb(dbFlag)
|
||||||
|
// gredis.GetRedisConn(config.RedisInfo),
|
||||||
|
|
||||||
|
service.MyService = service.NewService(sqliteDB, "")
|
||||||
|
}
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
versionFlag := flag.Bool("v", false, "version")
|
||||||
|
debugFlag := flag.Bool("d", true, "debug")
|
||||||
|
forceFlag := flag.Bool("f", true, "force")
|
||||||
|
flag.Parse()
|
||||||
|
_logger = NewLogger()
|
||||||
|
if *versionFlag {
|
||||||
|
fmt.Println(common.Version)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
|
|
||||||
|
if os.Getuid() != 0 {
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
if *debugFlag {
|
||||||
|
_logger.DebugMode = true
|
||||||
|
}
|
||||||
|
|
||||||
|
if !*forceFlag {
|
||||||
|
serviceEnabled, err := systemctl.IsServiceEnabled(casaosServiceName)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if serviceEnabled {
|
||||||
|
_logger.Info("%s is already enabled. If migration is still needed, try with -f.", casaosServiceName)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
migrationTools := []interfaces.MigrationTool{
|
||||||
|
// nothing to migrate from last version
|
||||||
|
}
|
||||||
|
|
||||||
|
var selectedMigrationTool interfaces.MigrationTool
|
||||||
|
|
||||||
|
// look for the right migration tool matching current version
|
||||||
|
for _, tool := range migrationTools {
|
||||||
|
migrationNeeded, err := tool.IsMigrationNeeded()
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if migrationNeeded {
|
||||||
|
selectedMigrationTool = tool
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if selectedMigrationTool == nil {
|
||||||
|
_logger.Error("selectedMigrationTool is null")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := selectedMigrationTool.PreMigrate(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := selectedMigrationTool.Migrate(); err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := selectedMigrationTool.PostMigrate(); err != nil {
|
||||||
|
_logger.Error("Migration succeeded, but post-migration failed: %s", err)
|
||||||
|
}
|
||||||
|
}
|
||||||
89
common/notify.go
Normal file
@@ -0,0 +1,89 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
CasaOSURLFilename = "casaos.url"
|
||||||
|
APICasaOSNotify = "/v1/notify"
|
||||||
|
)
|
||||||
|
|
||||||
|
type NotifyService interface {
|
||||||
|
SendNotify(path string, message map[string]interface{}) error
|
||||||
|
SendSystemStatusNotify(message map[string]interface{}) error
|
||||||
|
}
|
||||||
|
type notifyService struct {
|
||||||
|
address string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *notifyService) SendNotify(path string, message map[string]interface{}) error {
|
||||||
|
|
||||||
|
url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/" + path
|
||||||
|
body, err := json.Marshal(message)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
response, err := http.Post(url, "application/json", bytes.NewBuffer(body))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
// disk: "sys_disk":{"size":56866869248,"avail":5855485952,"health":true,"used":48099700736}
|
||||||
|
// usb: "sys_usb":[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}]
|
||||||
|
func (n *notifyService) SendSystemStatusNotify(message map[string]interface{}) error {
|
||||||
|
|
||||||
|
url := strings.TrimSuffix(n.address, "/") + APICasaOSNotify + "/system_status"
|
||||||
|
fmt.Println(url)
|
||||||
|
body, err := json.Marshal(message)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
response, err := http.Post(url, "application/json", bytes.NewBuffer(body))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return errors.New("failed to send notify (status code: " + fmt.Sprint(response.StatusCode) + ")")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
func NewNotifyService(runtimePath string) (NotifyService, error) {
|
||||||
|
casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename)
|
||||||
|
|
||||||
|
buf, err := os.ReadFile(casaosAddressFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
address := string(buf)
|
||||||
|
|
||||||
|
response, err := http.Get(address + "/ping")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode != 200 {
|
||||||
|
return nil, errors.New("failed to ping casaos service")
|
||||||
|
}
|
||||||
|
|
||||||
|
return ¬ifyService{
|
||||||
|
address: address,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
29
common/notify_test.go
Normal file
@@ -0,0 +1,29 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestSendNotify(t *testing.T) {
|
||||||
|
notify, err := NewNotifyService("/var/run/casaos")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
err = notify.SendNotify("test", map[string]interface{}{
|
||||||
|
"test": "test",
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestSendSystemStatusNotify(t *testing.T) {
|
||||||
|
notify, err := NewNotifyService("/var/run/casaos")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
err = notify.SendSystemStatusNotify(map[string]interface{}{
|
||||||
|
"sys_usb": `[{"name": "sdc","size": 7747397632,"model": "DataTraveler_2.0","avail": 7714418688,"children": null}]`,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
78
common/share.go
Normal file
@@ -0,0 +1,78 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import (
|
||||||
|
"bytes"
|
||||||
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
|
"fmt"
|
||||||
|
"net/http"
|
||||||
|
"os"
|
||||||
|
"path/filepath"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
APICasaOSShare = "/v1/samba/shares"
|
||||||
|
)
|
||||||
|
|
||||||
|
type ShareService interface {
|
||||||
|
DeleteShare(id string) error
|
||||||
|
}
|
||||||
|
type shareService struct {
|
||||||
|
address string
|
||||||
|
}
|
||||||
|
|
||||||
|
func (n *shareService) DeleteShare(id string) error {
|
||||||
|
url := strings.TrimSuffix(n.address, "/") + APICasaOSShare + "/" + id
|
||||||
|
fmt.Println(url)
|
||||||
|
message := "{}"
|
||||||
|
body, err := json.Marshal(message)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
client := &http.Client{}
|
||||||
|
|
||||||
|
// Create request
|
||||||
|
req, err := http.NewRequest("DELETE", url, bytes.NewBuffer(body))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
// Fetch Request
|
||||||
|
response, err := client.Do(req)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
defer response.Body.Close()
|
||||||
|
|
||||||
|
if response.StatusCode != http.StatusOK {
|
||||||
|
return errors.New("failed to send share (status code: " + fmt.Sprint(response.StatusCode) + ")")
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewShareService(runtimePath string) (ShareService, error) {
|
||||||
|
casaosAddressFile := filepath.Join(runtimePath, CasaOSURLFilename)
|
||||||
|
|
||||||
|
buf, err := os.ReadFile(casaosAddressFile)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
address := string(buf)
|
||||||
|
|
||||||
|
response, err := http.Get(address + "/ping")
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if response.StatusCode != 200 {
|
||||||
|
return nil, errors.New("failed to ping casaos service")
|
||||||
|
}
|
||||||
|
|
||||||
|
return &shareService{
|
||||||
|
address: address,
|
||||||
|
}, nil
|
||||||
|
}
|
||||||
14
common/share_test.go
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
package common
|
||||||
|
|
||||||
|
import "testing"
|
||||||
|
|
||||||
|
func TestDeleteShare(t *testing.T) {
|
||||||
|
share, err := NewShareService("/var/run/casaos")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
err = share.DeleteShare("1")
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,14 +11,15 @@ DateFormat = 2006-01-02
|
|||||||
DBPath = /var/lib/casaos
|
DBPath = /var/lib/casaos
|
||||||
ShellPath = /usr/share/casaos/shell
|
ShellPath = /usr/share/casaos/shell
|
||||||
UserDataPath = /var/lib/casaos/conf
|
UserDataPath = /var/lib/casaos/conf
|
||||||
TempPath = /var/lib/casaos/temp
|
|
||||||
|
|
||||||
[server]
|
[server]
|
||||||
HttpPort = 80
|
|
||||||
RunMode = release
|
RunMode = release
|
||||||
ServerApi = https://api.casaos.io/casaos-api
|
ServerApi = https://api.casaos.io/casaos-api
|
||||||
Handshake = socket.casaos.io
|
Handshake = socket.casaos.io
|
||||||
Token =
|
Token =
|
||||||
USBAutoMount =
|
USBAutoMount =
|
||||||
|
|
||||||
[system]
|
[system]
|
||||||
|
|
||||||
|
[common]
|
||||||
|
RuntimePath=/var/run/casaos
|
||||||
42
go.mod
@@ -4,52 +4,38 @@ go 1.16
|
|||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
|
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
|
||||||
|
github.com/IceWhaleTech/CasaOS-Common v0.0.0-20220929035515-b1287110d6d8
|
||||||
|
github.com/IceWhaleTech/CasaOS-Gateway v0.3.6
|
||||||
github.com/Microsoft/go-winio v0.5.0 // indirect
|
github.com/Microsoft/go-winio v0.5.0 // indirect
|
||||||
github.com/Microsoft/hcsshim v0.8.22 // indirect
|
|
||||||
github.com/ambelovsky/go-structs v1.1.0 // indirect
|
github.com/ambelovsky/go-structs v1.1.0 // indirect
|
||||||
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109
|
github.com/ambelovsky/gosf v0.0.0-20201109201340-237aea4d6109
|
||||||
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect
|
github.com/ambelovsky/gosf-socketio v0.0.0-20201109193639-add9d32f8b19 // indirect
|
||||||
github.com/bits-and-blooms/bitset v1.2.1 // indirect
|
github.com/containerd/containerd v1.5.7 // indirect
|
||||||
github.com/containerd/containerd v1.5.7
|
github.com/coreos/go-systemd v0.0.0-20190321100706-95778dfbb74e
|
||||||
github.com/containerd/continuity v0.2.0 // indirect
|
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
github.com/docker/distribution v2.8.0+incompatible // indirect
|
github.com/docker/distribution v2.8.0+incompatible // indirect
|
||||||
github.com/docker/docker v20.10.7+incompatible
|
github.com/docker/docker v20.10.7+incompatible
|
||||||
github.com/docker/go-connections v0.4.0
|
github.com/docker/go-connections v0.4.0
|
||||||
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b
|
github.com/dsoprea/go-exif/v3 v3.0.0-20210625224831-a6301f85c82b
|
||||||
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
|
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
|
||||||
github.com/gin-contrib/gzip v0.0.2
|
github.com/gin-contrib/gzip v0.0.6
|
||||||
github.com/gin-gonic/gin v1.7.2
|
github.com/gin-gonic/gin v1.8.1
|
||||||
github.com/go-ini/ini v1.62.0
|
github.com/go-ini/ini v1.62.0
|
||||||
github.com/go-playground/validator/v10 v10.6.1 // indirect
|
|
||||||
github.com/gogo/googleapis v1.4.1 // indirect
|
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.1
|
|
||||||
github.com/golang/groupcache v0.0.0-20210331224755-41bb18bfe9da // indirect
|
|
||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
github.com/gomodule/redigo v1.8.5
|
github.com/gomodule/redigo v1.8.5
|
||||||
github.com/google/go-github/v36 v36.0.0
|
github.com/google/go-github/v36 v36.0.0
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
|
||||||
github.com/googollee/go-socket.io v1.6.2
|
github.com/googollee/go-socket.io v1.6.2
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/mux v1.8.0 // indirect
|
||||||
github.com/gorilla/websocket v1.4.2
|
github.com/gorilla/websocket v1.4.2
|
||||||
github.com/hirochachacha/go-smb2 v1.1.0
|
github.com/hirochachacha/go-smb2 v1.1.0
|
||||||
github.com/jinzhu/copier v0.3.2
|
github.com/jinzhu/copier v0.3.2
|
||||||
github.com/json-iterator/go v1.1.11 // indirect
|
|
||||||
github.com/klauspost/compress v1.13.6 // indirect
|
|
||||||
github.com/kr/text v0.2.0 // indirect
|
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
|
||||||
github.com/lucas-clemente/quic-go v0.25.0
|
github.com/lucas-clemente/quic-go v0.25.0
|
||||||
github.com/mattn/go-isatty v0.0.14 // indirect
|
|
||||||
github.com/mattn/go-sqlite3 v1.14.11 // indirect
|
|
||||||
github.com/mholt/archiver/v3 v3.5.1
|
github.com/mholt/archiver/v3 v3.5.1
|
||||||
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
github.com/moby/term v0.0.0-20210619224110-3f7ff695adc6 // indirect
|
||||||
github.com/morikuni/aec v1.0.0 // indirect
|
github.com/morikuni/aec v1.0.0 // indirect
|
||||||
github.com/opencontainers/image-spec v1.0.2 // indirect
|
github.com/opencontainers/image-spec v1.0.2 // indirect
|
||||||
github.com/opencontainers/selinux v1.8.5 // indirect
|
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pilebones/go-udev v0.9.0
|
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/prometheus/procfs v0.7.3 // indirect
|
|
||||||
github.com/robfig/cron v1.2.0
|
github.com/robfig/cron v1.2.0
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shirou/gopsutil/v3 v3.22.7
|
github.com/shirou/gopsutil/v3 v3.22.7
|
||||||
@@ -58,22 +44,12 @@ require (
|
|||||||
github.com/smartystreets/goconvey v1.6.4 // indirect
|
github.com/smartystreets/goconvey v1.6.4 // indirect
|
||||||
github.com/stretchr/testify v1.8.0
|
github.com/stretchr/testify v1.8.0
|
||||||
github.com/tidwall/gjson v1.10.2
|
github.com/tidwall/gjson v1.10.2
|
||||||
github.com/ugorji/go v1.2.6 // indirect
|
go.uber.org/zap v1.21.0
|
||||||
go.opencensus.io v0.23.0 // indirect
|
golang.org/x/crypto v0.0.0-20220411220226-7b82a4e95df4
|
||||||
go.uber.org/zap v1.10.0
|
|
||||||
golang.org/x/crypto v0.0.0-20210817164053-32db794688a5
|
|
||||||
golang.org/x/mod v0.5.0 // indirect
|
golang.org/x/mod v0.5.0 // indirect
|
||||||
golang.org/x/net v0.0.0-20211020060615-d418f374d309 // indirect
|
golang.org/x/oauth2 v0.0.0-20220411215720-9780585627b5
|
||||||
golang.org/x/oauth2 v0.0.0-20210819190943-2bc19b11175f
|
|
||||||
golang.org/x/term v0.0.0-20210615171337-6886f2dfbf5b // indirect
|
|
||||||
golang.org/x/text v0.3.7 // indirect
|
|
||||||
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
golang.org/x/time v0.0.0-20210723032227-1f47c861a9ac // indirect
|
||||||
golang.org/x/tools v0.1.7 // indirect
|
golang.org/x/tools v0.1.7 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
|
||||||
google.golang.org/genproto v0.0.0-20210924002016-3dee208752a0 // indirect
|
|
||||||
google.golang.org/grpc v1.41.0 // indirect
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c // indirect
|
|
||||||
gopkg.in/ini.v1 v1.62.0 // indirect
|
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
gopkg.in/natefinch/lumberjack.v2 v2.0.0
|
||||||
gorm.io/driver/sqlite v1.2.6
|
gorm.io/driver/sqlite v1.2.6
|
||||||
gorm.io/gorm v1.22.5
|
gorm.io/gorm v1.22.5
|
||||||
|
|||||||
18
interfaces/migrationTool.go
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-08-24 17:37:36
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-24 17:38:48
|
||||||
|
* @FilePath: /CasaOS/interfaces/migrationTool.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package interfaces
|
||||||
|
|
||||||
|
type MigrationTool interface {
|
||||||
|
IsMigrationNeeded() (bool, error)
|
||||||
|
PostMigrate() error
|
||||||
|
Migrate() error
|
||||||
|
PreMigrate() error
|
||||||
|
}
|
||||||
131
main.go
@@ -3,40 +3,45 @@ package main
|
|||||||
import (
|
import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Gateway/common"
|
||||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
"github.com/IceWhaleTech/CasaOS/model/notify"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
"github.com/IceWhaleTech/CasaOS/pkg/cache"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
"github.com/IceWhaleTech/CasaOS/pkg/sqlite"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/random"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/route"
|
"github.com/IceWhaleTech/CasaOS/route"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/IceWhaleTech/CasaOS/types"
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
|
"github.com/coreos/go-systemd/daemon"
|
||||||
|
"go.uber.org/zap"
|
||||||
|
|
||||||
"github.com/robfig/cron"
|
"github.com/robfig/cron"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const LOCALHOST = "127.0.0.1"
|
||||||
|
|
||||||
var sqliteDB *gorm.DB
|
var sqliteDB *gorm.DB
|
||||||
|
|
||||||
var configFlag = flag.String("c", "", "config address")
|
var (
|
||||||
var dbFlag = flag.String("db", "", "db path")
|
configFlag = flag.String("c", "", "config address")
|
||||||
var resetUser = flag.Bool("ru", false, "reset user")
|
dbFlag = flag.String("db", "", "db path")
|
||||||
var user = flag.String("user", "", "user name")
|
versionFlag = flag.Bool("v", false, "version")
|
||||||
var version = flag.Bool("v", false, "show version")
|
)
|
||||||
|
|
||||||
func init() {
|
func init() {
|
||||||
flag.Parse()
|
flag.Parse()
|
||||||
if *version {
|
if *versionFlag {
|
||||||
fmt.Println("v" + types.CURRENTVERSION)
|
fmt.Println("v" + types.CURRENTVERSION)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
config.InitSetup(*configFlag)
|
config.InitSetup(*configFlag)
|
||||||
config.UpdateSetup()
|
|
||||||
|
|
||||||
loger.LogInit()
|
loger.LogInit()
|
||||||
if len(*dbFlag) == 0 {
|
if len(*dbFlag) == 0 {
|
||||||
@@ -44,9 +49,9 @@ func init() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
sqliteDB = sqlite.GetDb(*dbFlag)
|
sqliteDB = sqlite.GetDb(*dbFlag)
|
||||||
//gredis.GetRedisConn(config.RedisInfo),
|
// gredis.GetRedisConn(config.RedisInfo),
|
||||||
|
|
||||||
service.MyService = service.NewService(sqliteDB)
|
service.MyService = service.NewService(sqliteDB, config.CommonInfo.RuntimePath)
|
||||||
|
|
||||||
service.Cache = cache.Init()
|
service.Cache = cache.Init()
|
||||||
|
|
||||||
@@ -57,7 +62,6 @@ func init() {
|
|||||||
|
|
||||||
// go service.LoopFriend()
|
// go service.LoopFriend()
|
||||||
// go service.MyService.App().CheckNewImage()
|
// go service.MyService.App().CheckNewImage()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @title casaOS API
|
// @title casaOS API
|
||||||
@@ -73,43 +77,25 @@ func init() {
|
|||||||
// @BasePath /v1
|
// @BasePath /v1
|
||||||
func main() {
|
func main() {
|
||||||
service.NotifyMsg = make(chan notify.Message, 10)
|
service.NotifyMsg = make(chan notify.Message, 10)
|
||||||
if *version {
|
if *versionFlag {
|
||||||
return
|
|
||||||
}
|
|
||||||
if *resetUser {
|
|
||||||
if user == nil || len(*user) == 0 {
|
|
||||||
fmt.Println("user is empty")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
userData := service.MyService.User().GetUserAllInfoByName(*user)
|
|
||||||
if userData.Id == 0 {
|
|
||||||
fmt.Println("user not exist")
|
|
||||||
return
|
|
||||||
}
|
|
||||||
password := random.RandomString(6, false)
|
|
||||||
userData.Password = encryption.GetMD5ByStr(password)
|
|
||||||
service.MyService.User().UpdateUserPassword(userData)
|
|
||||||
fmt.Println("User reset successful")
|
|
||||||
fmt.Println("UserName:" + userData.Username)
|
|
||||||
fmt.Println("Password:" + password)
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go route.SocketInit(service.NotifyMsg)
|
go route.SocketInit(service.NotifyMsg)
|
||||||
go route.MonitoryUSB()
|
// model.Setup()
|
||||||
//model.Setup()
|
// gredis.Setup()
|
||||||
//gredis.Setup()
|
|
||||||
r := route.InitRouter()
|
r := route.InitRouter()
|
||||||
//service.SyncTask(sqliteDB)
|
// service.SyncTask(sqliteDB)
|
||||||
cron2 := cron.New()
|
cron2 := cron.New()
|
||||||
//every day execution
|
// every day execution
|
||||||
|
|
||||||
err := cron2.AddFunc("0/5 * * * * *", func() {
|
err := cron2.AddFunc("0/5 * * * * *", func() {
|
||||||
if service.ClientCount > 0 {
|
if service.ClientCount > 0 {
|
||||||
//route.SendNetINfoBySocket()
|
// route.SendNetINfoBySocket()
|
||||||
//route.SendCPUBySocket()
|
// route.SendCPUBySocket()
|
||||||
//route.SendMemBySocket()
|
// route.SendMemBySocket()
|
||||||
// route.SendDiskBySocket()
|
// route.SendDiskBySocket()
|
||||||
//route.SendUSBBySocket()
|
// route.SendUSBBySocket()
|
||||||
route.SendAllHardwareStatusBySocket()
|
route.SendAllHardwareStatusBySocket()
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -117,18 +103,63 @@ func main() {
|
|||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
}
|
}
|
||||||
cron2.Start()
|
cron2.Start()
|
||||||
|
|
||||||
defer cron2.Stop()
|
defer cron2.Stop()
|
||||||
s := &http.Server{
|
|
||||||
Addr: fmt.Sprintf(":%v", config.ServerInfo.HttpPort),
|
listener, err := net.Listen("tcp", net.JoinHostPort(LOCALHOST, "0"))
|
||||||
Handler: r,
|
if err != nil {
|
||||||
ReadTimeout: 60 * time.Second,
|
panic(err)
|
||||||
WriteTimeout: 60 * time.Second,
|
}
|
||||||
MaxHeaderBytes: 1 << 20,
|
routers := []string{"sys", "apps", "container", "app-categories", "port", "file", "folder", "batch", "image", "samba", "notify"}
|
||||||
|
for _, v := range routers {
|
||||||
|
err = service.MyService.Gateway().CreateRoute(&common.Route{
|
||||||
|
Path: "/v1/" + v,
|
||||||
|
Target: "http://" + listener.Addr().String(),
|
||||||
|
})
|
||||||
|
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println("err", err)
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
go func() {
|
||||||
|
time.Sleep(time.Second * 2)
|
||||||
|
// v0.3.6
|
||||||
|
if config.ServerInfo.HttpPort != "" {
|
||||||
|
changePort := common.ChangePortRequest{}
|
||||||
|
changePort.Port = config.ServerInfo.HttpPort
|
||||||
|
err := service.MyService.Gateway().ChangePort(&changePort)
|
||||||
|
if err == nil {
|
||||||
|
config.Cfg.Section("server").Key("HttpPort").SetValue("")
|
||||||
|
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}()
|
||||||
|
|
||||||
|
urlFilePath := filepath.Join(config.CommonInfo.RuntimePath, "casaos.url")
|
||||||
|
err = file.CreateFileAndWriteContent(urlFilePath, "http://"+listener.Addr().String())
|
||||||
|
if err != nil {
|
||||||
|
loger.Error("Management service is listening...",
|
||||||
|
zap.Any("address", listener.Addr().String()),
|
||||||
|
zap.Any("filepath", urlFilePath),
|
||||||
|
)
|
||||||
}
|
}
|
||||||
|
|
||||||
s.ListenAndServe()
|
if supported, err := daemon.SdNotify(false, daemon.SdNotifyReady); err != nil {
|
||||||
|
loger.Error("Failed to notify systemd that casaos main service is ready", zap.Any("error", err))
|
||||||
|
} else if supported {
|
||||||
|
loger.Info("Notified systemd that casaos main service is ready")
|
||||||
|
} else {
|
||||||
|
loger.Info("This process is not running as a systemd service.")
|
||||||
|
}
|
||||||
|
|
||||||
// if err := r.Run(fmt.Sprintf(":%v", config.ServerInfo.HttpPort)); err != nil {
|
s := &http.Server{
|
||||||
// fmt.Println("failed run app: ", err)
|
Handler: r,
|
||||||
// }
|
ReadHeaderTimeout: 5 * time.Second, // fix G112: Potential slowloris attack (see https://github.com/securego/gosec)
|
||||||
|
}
|
||||||
|
|
||||||
|
err = s.Serve(listener) // not using http.serve() to fix G114: Use of net/http serve function that has no support for setting timeouts (see https://github.com/securego/gosec)
|
||||||
|
if err != nil {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,62 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2021-10-08 10:29:08
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-07-22 11:06:07
|
|
||||||
* @FilePath: /CasaOS/middleware/gin.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package middleware
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"net/http"
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
|
||||||
|
|
||||||
func Cors() gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
method := c.Request.Method
|
|
||||||
|
|
||||||
c.Header("Access-Control-Allow-Origin", "*")
|
|
||||||
c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, DELETE,UPDATE")
|
|
||||||
//允许跨域设置可以返回其他子段,可以自定义字段
|
|
||||||
c.Header("Access-Control-Allow-Headers", "Authorization, Content-Length, X-CSRF-Token, Token,session,Language,Content-Type,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods,Connection,Host,Origin,Referer,User-Agent,X-Requested-With")
|
|
||||||
// 允许浏览器(客户端)可以解析的头部 (重要)
|
|
||||||
c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers")
|
|
||||||
//c.Writer.Header().Set("Access-Control-Allow-Headers", "Accept, Authorization, Content-Type, Content-Length, X-CSRF-Token, Token, session, Origin, Host, Connection, Accept-Encoding, Accept-Language, X-Requested-With")
|
|
||||||
//设置缓存时间
|
|
||||||
c.Header("Access-Control-Max-Age", "172800")
|
|
||||||
c.Header("Access-Control-Allow-Credentials", "true")
|
|
||||||
c.Set("Content-Type", "application/json")
|
|
||||||
//}
|
|
||||||
|
|
||||||
//允许类型校验
|
|
||||||
if method == "OPTIONS" {
|
|
||||||
c.JSON(http.StatusOK, "ok!")
|
|
||||||
}
|
|
||||||
|
|
||||||
defer func() {
|
|
||||||
if err := recover(); err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func WriteLog() gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
if !strings.Contains(c.Request.URL.String(), "password") {
|
|
||||||
loger.Info("request:", zap.Any("path", c.Request.URL.String()), zap.Any("param", c.Params), zap.Any("query", c.Request.URL.Query()), zap.Any("method", c.Request.Method))
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,98 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-07-13 10:43:45
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-08-03 14:45:35
|
|
||||||
* @FilePath: /CasaOS/model/disk.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package model
|
|
||||||
|
|
||||||
type LSBLKModel struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
FsType string `json:"fstype"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
FSSize string `json:"fssize"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Model string `json:"model"` //设备标识符
|
|
||||||
RM bool `json:"rm"` //是否为可移动设备
|
|
||||||
RO bool `json:"ro"` //是否为只读设备
|
|
||||||
State string `json:"state"`
|
|
||||||
PhySec int `json:"phy-sec"` //物理扇区大小
|
|
||||||
Type string `json:"type"`
|
|
||||||
Vendor string `json:"vendor"` //供应商
|
|
||||||
Rev string `json:"rev"` //修订版本
|
|
||||||
FSAvail string `json:"fsavail"` //可用空间
|
|
||||||
FSUse string `json:"fsuse%"` //已用百分比
|
|
||||||
MountPoint string `json:"mountpoint"`
|
|
||||||
Format string `json:"format"`
|
|
||||||
Health string `json:"health"`
|
|
||||||
HotPlug bool `json:"hotplug"`
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
FSUsed string `json:"fsused"`
|
|
||||||
Temperature int `json:"temperature"`
|
|
||||||
Tran string `json:"tran"`
|
|
||||||
MinIO uint64 `json:"min-io"`
|
|
||||||
UsedPercent float64 `json:"used_percent"`
|
|
||||||
Serial string `json:"serial"`
|
|
||||||
Children []LSBLKModel `json:"children"`
|
|
||||||
SubSystems string `json:"subsystems"`
|
|
||||||
Label string `json:"label"`
|
|
||||||
//详情特有
|
|
||||||
StartSector uint64 `json:"start_sector,omitempty"`
|
|
||||||
Rota bool `json:"rota"` //true(hhd) false(ssd)
|
|
||||||
DiskType string `json:"disk_type"`
|
|
||||||
EndSector uint64 `json:"end_sector,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Drive struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Model string `json:"model"`
|
|
||||||
Health string `json:"health"`
|
|
||||||
Temperature int `json:"temperature"`
|
|
||||||
DiskType string `json:"disk_type"`
|
|
||||||
NeedFormat bool `json:"need_format"`
|
|
||||||
Serial string `json:"serial"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
ChildrenNumber int `json:"children_number"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type DriveUSB struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Model string `json:"model"`
|
|
||||||
Avail uint64 `json:"avail"`
|
|
||||||
Children []USBChildren `json:"children"`
|
|
||||||
}
|
|
||||||
type USBChildren struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Avail uint64 `json:"avail"`
|
|
||||||
MountPoint string `json:"mount_point"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Storage struct {
|
|
||||||
MountPoint string `json:"mount_point"`
|
|
||||||
Size string `json:"size"`
|
|
||||||
Avail string `json:"avail"` //可用空间
|
|
||||||
Type string `json:"type"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
DriveName string `json:"drive_name"`
|
|
||||||
Label string `json:"label"`
|
|
||||||
}
|
|
||||||
type Storages struct {
|
|
||||||
DiskName string `json:"disk_name"`
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Children []Storage `json:"children"`
|
|
||||||
}
|
|
||||||
|
|
||||||
type Summary struct {
|
|
||||||
Size uint64 `json:"size"`
|
|
||||||
Avail uint64 `json:"avail"` //可用空间
|
|
||||||
Health bool `json:"health"`
|
|
||||||
Used uint64 `json:"used"`
|
|
||||||
}
|
|
||||||
@@ -16,3 +16,9 @@ type DockerStatsModel struct {
|
|||||||
Data interface{} `json:"data"`
|
Data interface{} `json:"data"`
|
||||||
Previous interface{} `json:"previous"`
|
Previous interface{} `json:"previous"`
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// reference - https://docs.docker.com/engine/reference/commandline/dockerd/#daemon-configuration-file
|
||||||
|
type DockerDaemonConfigurationModel struct {
|
||||||
|
// e.g. `/var/lib/docker`
|
||||||
|
Root string `json:"data-root,omitempty"`
|
||||||
|
}
|
||||||
|
|||||||
@@ -1 +0,0 @@
|
|||||||
package receive
|
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2022-05-13 18:15:46
|
* @Date: 2022-05-13 18:15:46
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-07-14 11:02:06
|
* @LastEditTime: 2022-09-02 22:12:34
|
||||||
* @FilePath: /CasaOS/model/sys_common.go
|
* @FilePath: /CasaOS/model/sys_common.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -12,26 +12,12 @@ package model
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
//系统配置
|
// 系统配置
|
||||||
type SysInfoModel struct {
|
type SysInfoModel struct {
|
||||||
Name string //系统名称
|
Name string //系统名称
|
||||||
}
|
}
|
||||||
|
|
||||||
//用户相关
|
// 服务配置
|
||||||
type UserModel struct {
|
|
||||||
UserName string
|
|
||||||
PWD string
|
|
||||||
Token string
|
|
||||||
Head string
|
|
||||||
Email string
|
|
||||||
Description string
|
|
||||||
Initialized bool
|
|
||||||
Avatar string
|
|
||||||
NickName string
|
|
||||||
Public string
|
|
||||||
}
|
|
||||||
|
|
||||||
//服务配置
|
|
||||||
type ServerModel struct {
|
type ServerModel struct {
|
||||||
HttpPort string
|
HttpPort string
|
||||||
RunMode string
|
RunMode string
|
||||||
@@ -42,7 +28,7 @@ type ServerModel struct {
|
|||||||
SocketPort string
|
SocketPort string
|
||||||
}
|
}
|
||||||
|
|
||||||
//服务配置
|
// 服务配置
|
||||||
type APPModel struct {
|
type APPModel struct {
|
||||||
LogPath string
|
LogPath string
|
||||||
LogSaveName string
|
LogSaveName string
|
||||||
@@ -54,17 +40,19 @@ type APPModel struct {
|
|||||||
DateFormat string
|
DateFormat string
|
||||||
DBPath string
|
DBPath string
|
||||||
ShellPath string
|
ShellPath string
|
||||||
TempPath string
|
}
|
||||||
|
type CommonModel struct {
|
||||||
|
RuntimePath string
|
||||||
}
|
}
|
||||||
|
|
||||||
//公共返回模型
|
// 公共返回模型
|
||||||
type Result struct {
|
type Result struct {
|
||||||
Success int `json:"success" example:"200"`
|
Success int `json:"success" example:"200"`
|
||||||
Message string `json:"message" example:"ok"`
|
Message string `json:"message" example:"ok"`
|
||||||
Data interface{} `json:"data" example:"返回结果"`
|
Data interface{} `json:"data" example:"返回结果"`
|
||||||
}
|
}
|
||||||
|
|
||||||
//redis配置文件
|
// redis配置文件
|
||||||
type RedisModel struct {
|
type RedisModel struct {
|
||||||
Host string
|
Host string
|
||||||
Password string
|
Password string
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2021-09-30 18:18:14
|
* @Date: 2021-09-30 18:18:14
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-06-21 11:09:30
|
* @LastEditTime: 2022-08-31 17:04:02
|
||||||
* @FilePath: /CasaOS/pkg/config/config.go
|
* @FilePath: /CasaOS/pkg/config/config.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -11,5 +11,5 @@
|
|||||||
package config
|
package config
|
||||||
|
|
||||||
const (
|
const (
|
||||||
USERCONFIGURL = "/etc/casaos.conf"
|
USERCONFIGURL = "/etc/casaos/casaos.conf"
|
||||||
)
|
)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2022-05-13 18:15:46
|
* @Date: 2022-05-13 18:15:46
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-07-14 10:58:45
|
* @LastEditTime: 2022-09-05 11:58:02
|
||||||
* @FilePath: /CasaOS/pkg/config/init.go
|
* @FilePath: /CasaOS/pkg/config/init.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -23,18 +23,17 @@ import (
|
|||||||
"github.com/go-ini/ini"
|
"github.com/go-ini/ini"
|
||||||
)
|
)
|
||||||
|
|
||||||
//系统配置
|
// 系统配置
|
||||||
var SysInfo = &model.SysInfoModel{}
|
var SysInfo = &model.SysInfoModel{}
|
||||||
|
|
||||||
//用户相关
|
// 用户相关
|
||||||
var UserInfo = &model.UserModel{}
|
|
||||||
|
|
||||||
//用户相关
|
|
||||||
var AppInfo = &model.APPModel{}
|
var AppInfo = &model.APPModel{}
|
||||||
|
|
||||||
|
var CommonInfo = &model.CommonModel{}
|
||||||
|
|
||||||
//var RedisInfo = &model.RedisModel{}
|
//var RedisInfo = &model.RedisModel{}
|
||||||
|
|
||||||
//server相关
|
// server相关
|
||||||
var ServerInfo = &model.ServerModel{}
|
var ServerInfo = &model.ServerModel{}
|
||||||
|
|
||||||
var SystemConfigInfo = &model.SystemConfig{}
|
var SystemConfigInfo = &model.SystemConfig{}
|
||||||
@@ -45,7 +44,7 @@ var FileSettingInfo = &model.FileSetting{}
|
|||||||
|
|
||||||
var Cfg *ini.File
|
var Cfg *ini.File
|
||||||
|
|
||||||
//初始化设置,获取系统的部分信息。
|
// 初始化设置,获取系统的部分信息。
|
||||||
func InitSetup(config string) {
|
func InitSetup(config string) {
|
||||||
|
|
||||||
var configDir = USERCONFIGURL
|
var configDir = USERCONFIGURL
|
||||||
@@ -59,42 +58,43 @@ func InitSetup(config string) {
|
|||||||
//读取文件
|
//读取文件
|
||||||
Cfg, err = ini.Load(configDir)
|
Cfg, err = ini.Load(configDir)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Printf("Fail to read file: %v", err)
|
Cfg, err = ini.Load("/etc/casaos.conf")
|
||||||
os.Exit(1)
|
if err != nil {
|
||||||
|
Cfg, err = ini.Load("/casaOS/server/conf/conf.ini")
|
||||||
|
if err != nil {
|
||||||
|
fmt.Printf("Fail to read file: %v", err)
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
mapTo("user", UserInfo)
|
|
||||||
mapTo("app", AppInfo)
|
mapTo("app", AppInfo)
|
||||||
//mapTo("redis", RedisInfo)
|
//mapTo("redis", RedisInfo)
|
||||||
mapTo("server", ServerInfo)
|
mapTo("server", ServerInfo)
|
||||||
mapTo("system", SystemConfigInfo)
|
mapTo("system", SystemConfigInfo)
|
||||||
mapTo("file", FileSettingInfo)
|
mapTo("file", FileSettingInfo)
|
||||||
|
mapTo("common", CommonInfo)
|
||||||
SystemConfigInfo.ConfigPath = configDir
|
SystemConfigInfo.ConfigPath = configDir
|
||||||
if len(AppInfo.DBPath) == 0 {
|
if len(AppInfo.DBPath) == 0 {
|
||||||
AppInfo.DBPath = "/var/lib/casaos"
|
AppInfo.DBPath = "/var/lib/casaos"
|
||||||
Cfg.SaveTo(configDir)
|
|
||||||
}
|
}
|
||||||
if len(AppInfo.LogPath) == 0 {
|
if len(AppInfo.LogPath) == 0 {
|
||||||
AppInfo.LogPath = "/var/log/casaos/"
|
AppInfo.LogPath = "/var/log/casaos/"
|
||||||
Cfg.SaveTo(configDir)
|
|
||||||
}
|
}
|
||||||
if len(AppInfo.ShellPath) == 0 {
|
if len(AppInfo.ShellPath) == 0 {
|
||||||
AppInfo.ShellPath = "/usr/share/casaos/shell"
|
AppInfo.ShellPath = "/usr/share/casaos/shell"
|
||||||
Cfg.SaveTo(configDir)
|
|
||||||
}
|
}
|
||||||
if len(AppInfo.UserDataPath) == 0 {
|
if len(AppInfo.UserDataPath) == 0 {
|
||||||
AppInfo.UserDataPath = "/var/lib/casaos/conf"
|
AppInfo.UserDataPath = "/var/lib/casaos/conf"
|
||||||
Cfg.SaveTo(configDir)
|
|
||||||
}
|
}
|
||||||
if len(AppInfo.TempPath) == 0 {
|
if len(CommonInfo.RuntimePath) == 0 {
|
||||||
AppInfo.TempPath = "/var/lib/casaos/temp"
|
CommonInfo.RuntimePath = "/var/run/casaos"
|
||||||
Cfg.SaveTo(configDir)
|
|
||||||
}
|
}
|
||||||
|
Cfg.SaveTo(configDir)
|
||||||
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
// AppInfo.ProjectPath = getCurrentDirectory() //os.Getwd()
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//映射
|
// 映射
|
||||||
func mapTo(section string, v interface{}) {
|
func mapTo(section string, v interface{}) {
|
||||||
err := Cfg.Section(section).MapTo(v)
|
err := Cfg.Section(section).MapTo(v)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -1,32 +0,0 @@
|
|||||||
package config
|
|
||||||
|
|
||||||
import (
|
|
||||||
"runtime"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
|
||||||
)
|
|
||||||
|
|
||||||
//检查目录是否存在
|
|
||||||
func mkdirDATAAll() {
|
|
||||||
sysType := runtime.GOOS
|
|
||||||
var dirArray []string
|
|
||||||
if sysType == "linux" {
|
|
||||||
dirArray = []string{"/DATA/AppData", "/DATA/Documents", "/DATA/Downloads", "/DATA/Gallery", "/DATA/Media/Movies", "/DATA/Media/TV Shows", "/DATA/Media/Music"}
|
|
||||||
}
|
|
||||||
|
|
||||||
if sysType == "windows" {
|
|
||||||
dirArray = []string{"C:\\CasaOS\\DATA\\AppData", "C:\\CasaOS\\DATA\\Documents", "C:\\CasaOS\\DATA\\Downloads", "C:\\CasaOS\\DATA\\Gallery", "C:\\CasaOS\\DATA\\Media/Movies", "C:\\CasaOS\\DATA\\Media\\TV Shows", "C:\\CasaOS\\DATA\\Media\\Music"}
|
|
||||||
}
|
|
||||||
if sysType == "darwin" {
|
|
||||||
dirArray = []string{"./CasaOS/DATA/AppData", "./CasaOS/DATA/Documents", "./CasaOS/DATA/Downloads", "./CasaOS/DATA/Gallery", "./CasaOS/DATA/Media/Movies", "./CasaOS/DATA/Media/TV Shows", "./CasaOS/DATA/Media/Music"}
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range dirArray {
|
|
||||||
file.IsNotExistMkDir(v)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func UpdateSetup() {
|
|
||||||
mkdirDATAAll()
|
|
||||||
}
|
|
||||||
@@ -15,7 +15,6 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func NewSshClient(user, password string, port string) (*ssh.Client, error) {
|
func NewSshClient(user, password string, port string) (*ssh.Client, error) {
|
||||||
|
|
||||||
// connet to ssh
|
// connet to ssh
|
||||||
// addr = fmt.Sprintf("%s:%d", host, port)
|
// addr = fmt.Sprintf("%s:%d", host, port)
|
||||||
|
|
||||||
@@ -23,10 +22,10 @@ func NewSshClient(user, password string, port string) (*ssh.Client, error) {
|
|||||||
Timeout: time.Second * 5,
|
Timeout: time.Second * 5,
|
||||||
User: user,
|
User: user,
|
||||||
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
HostKeyCallback: ssh.InsecureIgnoreHostKey(),
|
||||||
//HostKeyCallback: ,
|
// HostKeyCallback: ,
|
||||||
//HostKeyCallback: hostKeyCallBackFunc(h.Host),
|
// HostKeyCallback: hostKeyCallBackFunc(h.Host),
|
||||||
}
|
}
|
||||||
//if h.Type == "password" {
|
// if h.Type == "password" {
|
||||||
config.Auth = []ssh.AuthMethod{ssh.Password(password)}
|
config.Auth = []ssh.AuthMethod{ssh.Password(password)}
|
||||||
//} else {
|
//} else {
|
||||||
// config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)}
|
// config.Auth = []ssh.AuthMethod{publicKeyAuthFunc(h.Key)}
|
||||||
@@ -90,11 +89,11 @@ func (w *wsBufferWriter) Write(p []byte) (int, error) {
|
|||||||
defer w.mu.Unlock()
|
defer w.mu.Unlock()
|
||||||
return w.buffer.Write(p)
|
return w.buffer.Write(p)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *SshConn) Close() {
|
func (s *SshConn) Close() {
|
||||||
if s.Session != nil {
|
if s.Session != nil {
|
||||||
s.Session.Close()
|
s.Session.Close()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
const (
|
const (
|
||||||
@@ -102,16 +101,15 @@ const (
|
|||||||
wsMsgResize = "resize"
|
wsMsgResize = "resize"
|
||||||
)
|
)
|
||||||
|
|
||||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
||||||
func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
||||||
//tells other go routine quit
|
// tells other go routine quit
|
||||||
username := ""
|
username := ""
|
||||||
for {
|
for {
|
||||||
|
|
||||||
//read websocket msg
|
// read websocket msg
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
_, wsData, err := wsConn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -125,8 +123,8 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
|||||||
//}
|
//}
|
||||||
switch msgObj.Type {
|
switch msgObj.Type {
|
||||||
case wsMsgCmd:
|
case wsMsgCmd:
|
||||||
//handle xterm.js stdin
|
// handle xterm.js stdin
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
||||||
decodeBytes := []byte(msgObj.Cmd)
|
decodeBytes := []byte(msgObj.Cmd)
|
||||||
if msgObj.Cmd == "\u007f" {
|
if msgObj.Cmd == "\u007f" {
|
||||||
if len(username) == 0 {
|
if len(username) == 0 {
|
||||||
@@ -144,7 +142,7 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
|||||||
if err := wsConn.WriteMessage(websocket.TextMessage, decodeBytes); err != nil {
|
if err := wsConn.WriteMessage(websocket.TextMessage, decodeBytes); err != nil {
|
||||||
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
||||||
}
|
}
|
||||||
//write input cmd to log buffer
|
// write input cmd to log buffer
|
||||||
if _, err := logBuff.Write(decodeBytes); err != nil {
|
if _, err := logBuff.Write(decodeBytes); err != nil {
|
||||||
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
||||||
}
|
}
|
||||||
@@ -154,11 +152,11 @@ func ReceiveWsMsgUser(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string {
|
||||||
//tells other go routine quit
|
// tells other go routine quit
|
||||||
password := ""
|
password := ""
|
||||||
for {
|
for {
|
||||||
|
|
||||||
//read websocket msg
|
// read websocket msg
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
_, wsData, err := wsConn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("reading webSocket message failed")
|
logrus.WithError(err).Error("reading webSocket message failed")
|
||||||
@@ -175,8 +173,8 @@ func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string
|
|||||||
//}
|
//}
|
||||||
switch msgObj.Type {
|
switch msgObj.Type {
|
||||||
case wsMsgCmd:
|
case wsMsgCmd:
|
||||||
//handle xterm.js stdin
|
// handle xterm.js stdin
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
||||||
if msgObj.Cmd == "\r" {
|
if msgObj.Cmd == "\r" {
|
||||||
return password
|
return password
|
||||||
}
|
}
|
||||||
@@ -194,16 +192,16 @@ func ReceiveWsMsgPassword(wsConn *websocket.Conn, logBuff *bytes.Buffer) string
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
||||||
func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
||||||
//tells other go routine quit
|
// tells other go routine quit
|
||||||
defer setQuit(exitCh)
|
defer setQuit(exitCh)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-exitCh:
|
case <-exitCh:
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
//read websocket msg
|
// read websocket msg
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
_, wsData, err := wsConn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("reading webSocket message failed")
|
logrus.WithError(err).Error("reading webSocket message failed")
|
||||||
@@ -227,15 +225,15 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe
|
|||||||
switch msgObj.Type {
|
switch msgObj.Type {
|
||||||
|
|
||||||
case wsMsgResize:
|
case wsMsgResize:
|
||||||
//handle xterm.js size change
|
// handle xterm.js size change
|
||||||
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
||||||
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
||||||
logrus.WithError(err).Error("ssh pty change windows size failed")
|
logrus.WithError(err).Error("ssh pty change windows size failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case wsMsgCmd:
|
case wsMsgCmd:
|
||||||
//handle xterm.js stdin
|
// handle xterm.js stdin
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
||||||
decodeBytes := []byte(msgObj.Cmd)
|
decodeBytes := []byte(msgObj.Cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
|
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
|
||||||
@@ -243,7 +241,7 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe
|
|||||||
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
|
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
|
||||||
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
||||||
}
|
}
|
||||||
//write input cmd to log buffer
|
// write input cmd to log buffer
|
||||||
if _, err := logBuff.Write(decodeBytes); err != nil {
|
if _, err := logBuff.Write(decodeBytes); err != nil {
|
||||||
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
||||||
}
|
}
|
||||||
@@ -253,17 +251,17 @@ func (ssConn *SshConn) ReceiveWsMsg(wsConn *websocket.Conn, logBuff *bytes.Buffe
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool) {
|
func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool) {
|
||||||
//tells other go routine quit
|
// tells other go routine quit
|
||||||
//defer setQuit(exitCh)
|
// defer setQuit(exitCh)
|
||||||
|
|
||||||
//every 120ms write combine output bytes into websocket response
|
// every 120ms write combine output bytes into websocket response
|
||||||
tick := time.NewTicker(time.Millisecond * time.Duration(120))
|
tick := time.NewTicker(time.Millisecond * time.Duration(120))
|
||||||
//for range time.Tick(120 * time.Millisecond){}
|
// for range time.Tick(120 * time.Millisecond){}
|
||||||
defer tick.Stop()
|
defer tick.Stop()
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-tick.C:
|
case <-tick.C:
|
||||||
//write combine output bytes into websocket response
|
// write combine output bytes into websocket response
|
||||||
if err := flushComboOutput(ssConn.ComboOutput, wsConn); err != nil {
|
if err := flushComboOutput(ssConn.ComboOutput, wsConn); err != nil {
|
||||||
logrus.WithError(err).Error("ssh sending combo output to webSocket failed")
|
logrus.WithError(err).Error("ssh sending combo output to webSocket failed")
|
||||||
return
|
return
|
||||||
@@ -273,6 +271,7 @@ func (ssConn *SshConn) SendComboOutput(wsConn *websocket.Conn, exitCh chan bool)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error {
|
func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error {
|
||||||
if w.buffer.Len() != 0 {
|
if w.buffer.Len() != 0 {
|
||||||
err := wsConn.WriteMessage(websocket.TextMessage, w.buffer.Bytes())
|
err := wsConn.WriteMessage(websocket.TextMessage, w.buffer.Bytes())
|
||||||
@@ -284,16 +283,16 @@ func flushComboOutput(w *wsBufferWriter, wsConn *websocket.Conn) error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
// ReceiveWsMsg receive websocket msg do some handling then write into ssh.session.stdin
|
||||||
func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exitCh chan bool) {
|
||||||
//tells other go routine quit
|
// tells other go routine quit
|
||||||
defer setQuit(exitCh)
|
defer setQuit(exitCh)
|
||||||
for {
|
for {
|
||||||
select {
|
select {
|
||||||
case <-exitCh:
|
case <-exitCh:
|
||||||
return
|
return
|
||||||
default:
|
default:
|
||||||
//read websocket msg
|
// read websocket msg
|
||||||
_, wsData, err := wsConn.ReadMessage()
|
_, wsData, err := wsConn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("reading webSocket message failed")
|
logrus.WithError(err).Error("reading webSocket message failed")
|
||||||
@@ -317,15 +316,15 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit
|
|||||||
switch msgObj.Type {
|
switch msgObj.Type {
|
||||||
|
|
||||||
case wsMsgResize:
|
case wsMsgResize:
|
||||||
//handle xterm.js size change
|
// handle xterm.js size change
|
||||||
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
if msgObj.Cols > 0 && msgObj.Rows > 0 {
|
||||||
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
if err := ssConn.Session.WindowChange(msgObj.Rows, msgObj.Cols); err != nil {
|
||||||
logrus.WithError(err).Error("ssh pty change windows size failed")
|
logrus.WithError(err).Error("ssh pty change windows size failed")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
case wsMsgCmd:
|
case wsMsgCmd:
|
||||||
//handle xterm.js stdin
|
// handle xterm.js stdin
|
||||||
//decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
// decodeBytes, err := base64.StdEncoding.DecodeString(msgObj.Cmd)
|
||||||
decodeBytes := []byte(msgObj.Cmd)
|
decodeBytes := []byte(msgObj.Cmd)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
|
logrus.WithError(err).Error("websock cmd string base64 decoding failed")
|
||||||
@@ -333,7 +332,7 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit
|
|||||||
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
|
if _, err := ssConn.StdinPipe.Write(decodeBytes); err != nil {
|
||||||
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
logrus.WithError(err).Error("ws cmd bytes write to ssh.stdin pipe failed")
|
||||||
}
|
}
|
||||||
//write input cmd to log buffer
|
// write input cmd to log buffer
|
||||||
if _, err := logBuff.Write(decodeBytes); err != nil {
|
if _, err := logBuff.Write(decodeBytes); err != nil {
|
||||||
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
logrus.WithError(err).Error("write received cmd into log buffer failed")
|
||||||
}
|
}
|
||||||
@@ -341,6 +340,7 @@ func (ssConn *SshConn) Login(wsConn *websocket.Conn, logBuff *bytes.Buffer, exit
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (ssConn *SshConn) SessionWait(quitChan chan bool) {
|
func (ssConn *SshConn) SessionWait(quitChan chan bool) {
|
||||||
if err := ssConn.Session.Wait(); err != nil {
|
if err := ssConn.Session.Wait(); err != nil {
|
||||||
logrus.WithError(err).Error("ssh session wait failed")
|
logrus.WithError(err).Error("ssh session wait failed")
|
||||||
@@ -395,7 +395,7 @@ func WsReaderCopy(reader *websocket.Conn, writer io.Writer) {
|
|||||||
if err = json2.Unmarshal(p, &msgObj); err != nil {
|
if err = json2.Unmarshal(p, &msgObj); err != nil {
|
||||||
writer.Write(p)
|
writer.Write(p)
|
||||||
} else if msgObj.Type == wsMsgResize {
|
} else if msgObj.Type == wsMsgResize {
|
||||||
//writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
|
// writer.Write([]byte("stty rows " + strconv.Itoa(msgObj.Rows) + " && stty cols " + strconv.Itoa(msgObj.Cols) + " \r"))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2022-05-13 18:15:46
|
* @Date: 2022-05-13 18:15:46
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-07-27 11:25:26
|
* @LastEditTime: 2022-08-31 13:39:24
|
||||||
* @FilePath: /CasaOS/pkg/sqlite/db.go
|
* @FilePath: /CasaOS/pkg/sqlite/db.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -43,17 +43,7 @@ func GetDb(dbPath string) *gorm.DB {
|
|||||||
}
|
}
|
||||||
gdb = db
|
gdb = db
|
||||||
|
|
||||||
db.Exec(`alter table o_user rename to old_user;
|
err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{})
|
||||||
|
|
||||||
create table o_users ( id integer primary key,username text,password text,role text,email text,nickname text,avatar text,description text,created_at datetime,updated_at datetime);
|
|
||||||
|
|
||||||
insert into o_users select id,user_name,password,role,email,nick_name,avatar,description,created_at,updated_at from old_user;
|
|
||||||
|
|
||||||
drop table old_user;
|
|
||||||
drop table o_user;
|
|
||||||
`)
|
|
||||||
|
|
||||||
err = db.AutoMigrate(&model2.AppNotify{}, &model2.AppListDBModel{}, &model2.SerialDisk{}, model2.UserDBModel{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{})
|
|
||||||
db.Exec("DROP TABLE IF EXISTS o_application")
|
db.Exec("DROP TABLE IF EXISTS o_application")
|
||||||
db.Exec("DROP TABLE IF EXISTS o_friend")
|
db.Exec("DROP TABLE IF EXISTS o_friend")
|
||||||
db.Exec("DROP TABLE IF EXISTS o_person_download")
|
db.Exec("DROP TABLE IF EXISTS o_person_download")
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ func ExecResultStrArray(cmdStr string) []string {
|
|||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
//str, err := ioutil.ReadAll(stdout)
|
// str, err := ioutil.ReadAll(stdout)
|
||||||
var networklist = []string{}
|
networklist := []string{}
|
||||||
outputBuf := bufio.NewReader(stdout)
|
outputBuf := bufio.NewReader(stdout)
|
||||||
for {
|
for {
|
||||||
output, _, err := outputBuf.ReadLine()
|
output, _, err := outputBuf.ReadLine()
|
||||||
@@ -54,6 +54,8 @@ func ExecResultStrArray(cmdStr string) []string {
|
|||||||
|
|
||||||
func ExecResultStr(cmdStr string) string {
|
func ExecResultStr(cmdStr string) string {
|
||||||
cmd := exec.Command("/bin/bash", "-c", cmdStr)
|
cmd := exec.Command("/bin/bash", "-c", cmdStr)
|
||||||
|
println(cmd.String())
|
||||||
|
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
@@ -73,7 +75,7 @@ func ExecResultStr(cmdStr string) string {
|
|||||||
return string(str)
|
return string(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
//执行 lsblk 命令
|
// 执行 lsblk 命令
|
||||||
func ExecLSBLK() []byte {
|
func ExecLSBLK() []byte {
|
||||||
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
|
output, err := exec.Command("lsblk", "-O", "-J", "-b").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -83,7 +85,7 @@ func ExecLSBLK() []byte {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
//执行 lsblk 命令
|
// 执行 lsblk 命令
|
||||||
func ExecLSBLKByPath(path string) []byte {
|
func ExecLSBLKByPath(path string) []byte {
|
||||||
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
output, err := exec.Command("lsblk", path, "-O", "-J", "-b").Output()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -93,7 +95,7 @@ func ExecLSBLKByPath(path string) []byte {
|
|||||||
return output
|
return output
|
||||||
}
|
}
|
||||||
|
|
||||||
//exec smart
|
// exec smart
|
||||||
func ExecSmartCTLByPath(path string) []byte {
|
func ExecSmartCTLByPath(path string) []byte {
|
||||||
timeout := 3
|
timeout := 3
|
||||||
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
ctx, cancel := context.WithTimeout(context.Background(), time.Duration(timeout)*time.Second)
|
||||||
@@ -107,6 +109,5 @@ func ExecSmartCTLByPath(path string) []byte {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func ExecEnabledSMART(path string) {
|
func ExecEnabledSMART(path string) {
|
||||||
|
|
||||||
exec.Command("smartctl", "-s on", path).Output()
|
exec.Command("smartctl", "-s on", path).Output()
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,6 +5,7 @@ import (
|
|||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
|
"io/fs"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"log"
|
"log"
|
||||||
"mime/multipart"
|
"mime/multipart"
|
||||||
@@ -60,7 +61,7 @@ func MkDir(src string) error {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
os.Chmod(src, 0777)
|
os.Chmod(src, 0o777)
|
||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
@@ -103,7 +104,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) {
|
|||||||
return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err)
|
return nil, fmt.Errorf("file.IsNotExistMkDir src: %s, err: %v", src, err)
|
||||||
}
|
}
|
||||||
|
|
||||||
f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0644)
|
f, err := Open(src+fileName, os.O_APPEND|os.O_CREATE|os.O_RDWR, 0o644)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, fmt.Errorf("Fail to OpenFile :%v", err)
|
return nil, fmt.Errorf("Fail to OpenFile :%v", err)
|
||||||
}
|
}
|
||||||
@@ -113,7 +114,7 @@ func MustOpen(fileName, filePath string) (*os.File, error) {
|
|||||||
|
|
||||||
// 判断所给路径文件/文件夹是否存在
|
// 判断所给路径文件/文件夹是否存在
|
||||||
func Exists(path string) bool {
|
func Exists(path string) bool {
|
||||||
_, err := os.Stat(path) //os.Stat获取文件信息
|
_, err := os.Stat(path) // os.Stat获取文件信息
|
||||||
if err != nil {
|
if err != nil {
|
||||||
if os.IsExist(err) {
|
if os.IsExist(err) {
|
||||||
return true
|
return true
|
||||||
@@ -147,7 +148,7 @@ func CreateFile(path string) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func CreateFileAndWriteContent(path string, content string) error {
|
func CreateFileAndWriteContent(path string, content string) error {
|
||||||
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0666)
|
file, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o666)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -163,7 +164,7 @@ func CreateFileAndWriteContent(path string, content string) error {
|
|||||||
|
|
||||||
// IsNotExistMkDir create a directory if it does not exist
|
// IsNotExistMkDir create a directory if it does not exist
|
||||||
func IsNotExistCreateFile(src string) error {
|
func IsNotExistCreateFile(src string) error {
|
||||||
if notExist := CheckNotExist(src); notExist == true {
|
if notExist := CheckNotExist(src); notExist {
|
||||||
if err := CreateFile(src); err != nil {
|
if err := CreateFile(src); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
@@ -267,7 +268,7 @@ func CopySingleFile(src, dst, style string) error {
|
|||||||
return os.Chmod(dst, srcinfo.Mode())
|
return os.Chmod(dst, srcinfo.Mode())
|
||||||
}
|
}
|
||||||
|
|
||||||
//Check for duplicate file names
|
// Check for duplicate file names
|
||||||
func GetNoDuplicateFileName(fullPath string) string {
|
func GetNoDuplicateFileName(fullPath string) string {
|
||||||
path, fileName := filepath.Split(fullPath)
|
path, fileName := filepath.Split(fullPath)
|
||||||
fileSuffix := path2.Ext(fileName)
|
fileSuffix := path2.Ext(fileName)
|
||||||
@@ -293,7 +294,7 @@ func CopyDir(src string, dst string, style string) error {
|
|||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
//dstPath := dst
|
// dstPath := dst
|
||||||
lastPath := src[strings.LastIndex(src, "/")+1:]
|
lastPath := src[strings.LastIndex(src, "/")+1:]
|
||||||
dst += "/" + lastPath
|
dst += "/" + lastPath
|
||||||
// for i := 0; Exists(dst); i++ {
|
// for i := 0; Exists(dst); i++ {
|
||||||
@@ -314,7 +315,7 @@ func CopyDir(src string, dst string, style string) error {
|
|||||||
}
|
}
|
||||||
for _, fd := range fds {
|
for _, fd := range fds {
|
||||||
srcfp := path.Join(src, fd.Name())
|
srcfp := path.Join(src, fd.Name())
|
||||||
dstfp := dst //path.Join(dst, fd.Name())
|
dstfp := dst // path.Join(dst, fd.Name())
|
||||||
|
|
||||||
if fd.IsDir() {
|
if fd.IsDir() {
|
||||||
if err = CopyDir(srcfp, dstfp, style); err != nil {
|
if err = CopyDir(srcfp, dstfp, style); err != nil {
|
||||||
@@ -336,10 +337,17 @@ func WriteToPath(data []byte, path, name string) error {
|
|||||||
} else {
|
} else {
|
||||||
fullPath += "/" + name
|
fullPath += "/" + name
|
||||||
}
|
}
|
||||||
IsNotExistCreateFile(fullPath)
|
return WriteToFullPath(data, fullPath, 0o666)
|
||||||
|
}
|
||||||
|
|
||||||
|
func WriteToFullPath(data []byte, fullPath string, perm fs.FileMode) error {
|
||||||
|
if err := IsNotExistCreateFile(fullPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
file, err := os.OpenFile(fullPath,
|
file, err := os.OpenFile(fullPath,
|
||||||
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
||||||
0666,
|
perm,
|
||||||
)
|
)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -350,26 +358,31 @@ func WriteToPath(data []byte, path, name string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//最终拼接
|
// 最终拼接
|
||||||
func SpliceFiles(dir, path string, length int, startPoint int) error {
|
func SpliceFiles(dir, path string, length int, startPoint int) error {
|
||||||
|
|
||||||
fullPath := path
|
fullPath := path
|
||||||
|
|
||||||
IsNotExistCreateFile(fullPath)
|
if err := IsNotExistCreateFile(fullPath); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
file, _ := os.OpenFile(fullPath,
|
file, _ := os.OpenFile(fullPath,
|
||||||
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
os.O_WRONLY|os.O_TRUNC|os.O_CREATE,
|
||||||
0666,
|
0o666,
|
||||||
)
|
)
|
||||||
|
|
||||||
defer file.Close()
|
defer file.Close()
|
||||||
|
|
||||||
bufferedWriter := bufio.NewWriter(file)
|
bufferedWriter := bufio.NewWriter(file)
|
||||||
|
|
||||||
|
// todo: here should have a goroutine to remove each partial file after it is read, to save disk space
|
||||||
|
|
||||||
for i := 0; i < length+startPoint; i++ {
|
for i := 0; i < length+startPoint; i++ {
|
||||||
data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint))
|
data, err := ioutil.ReadFile(dir + "/" + strconv.Itoa(i+startPoint))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
_, err = bufferedWriter.Write(data)
|
if _, err := bufferedWriter.Write(data); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster write
|
||||||
if err != nil {
|
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -380,7 +393,6 @@ func SpliceFiles(dir, path string, length int, startPoint int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
|
func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
|
||||||
|
|
||||||
switch t {
|
switch t {
|
||||||
case "zip", "":
|
case "zip", "":
|
||||||
return ".zip", archiver.NewZip(), nil
|
return ".zip", archiver.NewZip(), nil
|
||||||
@@ -400,8 +412,8 @@ func GetCompressionAlgorithm(t string) (string, archiver.Writer, error) {
|
|||||||
return "", nil, errors.New("format not implemented")
|
return "", nil, errors.New("format not implemented")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
func AddFile(ar archiver.Writer, path, commonPath string) error {
|
|
||||||
|
|
||||||
|
func AddFile(ar archiver.Writer, path, commonPath string) error {
|
||||||
info, err := os.Stat(path)
|
info, err := os.Stat(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -447,6 +459,7 @@ func AddFile(ar archiver.Writer, path, commonPath string) error {
|
|||||||
|
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func CommonPrefix(sep byte, paths ...string) string {
|
func CommonPrefix(sep byte, paths ...string) string {
|
||||||
// Handle special cases.
|
// Handle special cases.
|
||||||
switch len(paths) {
|
switch len(paths) {
|
||||||
@@ -513,7 +526,7 @@ func GetFileOrDirSize(path string) (int64, error) {
|
|||||||
return fileInfo.Size(), nil
|
return fileInfo.Size(), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//getFileSize get file size by path(B)
|
// getFileSize get file size by path(B)
|
||||||
func DirSizeB(path string) (int64, error) {
|
func DirSizeB(path string) (int64, error) {
|
||||||
var size int64
|
var size int64
|
||||||
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
|
err := filepath.Walk(path, func(_ string, info os.FileInfo, err error) error {
|
||||||
|
|||||||
@@ -1,63 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2021-09-30 18:18:14
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-07-18 17:30:38
|
|
||||||
* @FilePath: /CasaOS/pkg/utils/jwt/jwt.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package jwt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"time"
|
|
||||||
|
|
||||||
jwt "github.com/golang-jwt/jwt/v4"
|
|
||||||
)
|
|
||||||
|
|
||||||
type Claims struct {
|
|
||||||
Username string `json:"username"`
|
|
||||||
PassWord string `json:"password"`
|
|
||||||
Id int `json:"id"`
|
|
||||||
jwt.RegisteredClaims
|
|
||||||
}
|
|
||||||
|
|
||||||
var jwtSecret []byte
|
|
||||||
|
|
||||||
//创建token
|
|
||||||
func GenerateToken(username, password string, id int, issuer string, t time.Duration) (string, error) {
|
|
||||||
clims := Claims{
|
|
||||||
username,
|
|
||||||
password,
|
|
||||||
id,
|
|
||||||
jwt.RegisteredClaims{
|
|
||||||
ExpiresAt: jwt.NewNumericDate(time.Now().Add(t)),
|
|
||||||
IssuedAt: jwt.NewNumericDate(time.Now()),
|
|
||||||
NotBefore: jwt.NewNumericDate(time.Now()),
|
|
||||||
Issuer: issuer,
|
|
||||||
},
|
|
||||||
}
|
|
||||||
|
|
||||||
tokenClaims := jwt.NewWithClaims(jwt.SigningMethodHS256, clims)
|
|
||||||
token, err := tokenClaims.SignedString(jwtSecret)
|
|
||||||
return token, err
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//解析token
|
|
||||||
func ParseToken(token string, valid bool) (*Claims, error) {
|
|
||||||
tokenClaims, err := jwt.ParseWithClaims(token, &Claims{}, func(token *jwt.Token) (interface{}, error) {
|
|
||||||
return jwtSecret, nil
|
|
||||||
})
|
|
||||||
if tokenClaims != nil {
|
|
||||||
if clims, ok := tokenClaims.Claims.(*Claims); ok {
|
|
||||||
if valid && tokenClaims.Valid {
|
|
||||||
return clims, nil
|
|
||||||
} else if !valid {
|
|
||||||
return clims, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
@@ -1,75 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-06-17 14:01:25
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-07-29 16:22:25
|
|
||||||
* @FilePath: /CasaOS/pkg/utils/jwt/jwt_helper.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package jwt
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
"strconv"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
|
||||||
loger2 "github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
func JWT() gin.HandlerFunc {
|
|
||||||
return func(c *gin.Context) {
|
|
||||||
var code int
|
|
||||||
code = common_err.SUCCESS
|
|
||||||
token := c.GetHeader("Authorization")
|
|
||||||
if len(token) == 0 {
|
|
||||||
token = c.Query("token")
|
|
||||||
}
|
|
||||||
if token == "" {
|
|
||||||
code = common_err.INVALID_PARAMS
|
|
||||||
}
|
|
||||||
|
|
||||||
claims, err := ParseToken(token, false)
|
|
||||||
|
|
||||||
//_, err := ParseToken(token)
|
|
||||||
if err != nil {
|
|
||||||
code = common_err.ERROR_AUTH_TOKEN
|
|
||||||
} else if (c.Request.URL.Path == "/v1/file" || c.Request.URL.Path == "/v1/image" || c.Request.URL.Path == "/v1/file/upload" || c.Request.URL.Path == "/v1/batch") && claims.VerifyIssuer("casaos", true) {
|
|
||||||
//Special treatment
|
|
||||||
} else if !claims.VerifyExpiresAt(time.Now(), true) || !claims.VerifyIssuer("casaos", true) {
|
|
||||||
code = common_err.ERROR_AUTH_TOKEN
|
|
||||||
}
|
|
||||||
if code != common_err.SUCCESS {
|
|
||||||
c.JSON(code, model.Result{Success: code, Message: common_err.GetMsg(code)})
|
|
||||||
c.Abort()
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.Request.Header.Add("user_id", strconv.Itoa(claims.Id))
|
|
||||||
c.Next()
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
//get AccessToken
|
|
||||||
func GetAccessToken(username, pwd string, id int) string {
|
|
||||||
token, err := GenerateToken(username, pwd, id, "casaos", 3*time.Hour*time.Duration(1))
|
|
||||||
if err == nil {
|
|
||||||
return token
|
|
||||||
} else {
|
|
||||||
loger2.Error(fmt.Sprintf("Get Token Fail: %V", err))
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetRefreshToken(username, pwd string, id int) string {
|
|
||||||
token, err := GenerateToken(username, pwd, id, "refresh", 7*24*time.Hour*time.Duration(1))
|
|
||||||
if err == nil {
|
|
||||||
return token
|
|
||||||
} else {
|
|
||||||
loger2.Error(fmt.Sprintf("Get Token Fail: %V", err))
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.org
|
* @Author: LinkLeong link@icewhale.org
|
||||||
* @Date: 2022-08-12 14:22:28
|
* @Date: 2022-08-12 14:22:28
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-08-12 18:41:14
|
* @LastEditTime: 2022-09-05 16:27:55
|
||||||
* @FilePath: /CasaOS/route/darwin.go
|
* @FilePath: /CasaOS/route/darwin.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
|
|||||||
134
route/init.go
@@ -3,150 +3,28 @@ package route
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/samba"
|
"github.com/IceWhaleTech/CasaOS/pkg/samba"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
"go.uber.org/zap"
|
||||||
uuid "github.com/satori/go.uuid"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func InitFunction() {
|
func InitFunction() {
|
||||||
ShellInit()
|
go InitNetworkMount()
|
||||||
CheckSerialDiskMount()
|
|
||||||
CheckToken2_11()
|
|
||||||
ImportApplications()
|
|
||||||
// Soon to be removed
|
|
||||||
ChangeAPIUrl()
|
|
||||||
MoveUserToDB()
|
|
||||||
InitNetworkMount()
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func CheckSerialDiskMount() {
|
|
||||||
// check mount point
|
|
||||||
dbList := service.MyService.Disk().GetSerialAll()
|
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
mountPoint := make(map[string]string, len(dbList))
|
|
||||||
//remount
|
|
||||||
for _, v := range dbList {
|
|
||||||
mountPoint[v.UUID] = v.MountPoint
|
|
||||||
}
|
|
||||||
for _, v := range list {
|
|
||||||
command.ExecEnabledSMART(v.Path)
|
|
||||||
if v.Children != nil {
|
|
||||||
for _, h := range v.Children {
|
|
||||||
//if len(h.MountPoint) == 0 && len(v.Children) == 1 && h.FsType == "ext4" {
|
|
||||||
if m, ok := mountPoint[h.UUID]; ok {
|
|
||||||
//mount point check
|
|
||||||
volume := m
|
|
||||||
if !file.CheckNotExist(m) {
|
|
||||||
for i := 0; file.CheckNotExist(volume); i++ {
|
|
||||||
volume = m + strconv.Itoa(i+1)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
service.MyService.Disk().MountDisk(h.Path, volume)
|
|
||||||
if volume != m {
|
|
||||||
ms := model2.SerialDisk{}
|
|
||||||
ms.UUID = v.UUID
|
|
||||||
ms.MountPoint = volume
|
|
||||||
service.MyService.Disk().UpdateMountPoint(ms)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
//}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
command.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;AutoRemoveUnuseDir")
|
|
||||||
}
|
|
||||||
func ShellInit() {
|
|
||||||
command.OnlyExec("curl -fsSL https://raw.githubusercontent.com/IceWhaleTech/get/main/assist.sh | bash")
|
|
||||||
if !file.CheckNotExist("/casaOS") {
|
|
||||||
command.OnlyExec("source /casaOS/server/shell/update.sh ;")
|
|
||||||
command.OnlyExec("source " + config.AppInfo.ShellPath + "/delete-old-service.sh ;")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
func CheckToken2_11() {
|
|
||||||
if len(config.ServerInfo.Token) == 0 {
|
|
||||||
token := uuid.NewV4().String
|
|
||||||
config.ServerInfo.Token = token()
|
|
||||||
config.Cfg.Section("server").Key("Token").SetValue(token())
|
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(config.UserInfo.Description) == 0 {
|
|
||||||
config.Cfg.Section("user").Key("Description").SetValue("nothing")
|
|
||||||
config.UserInfo.Description = "nothing"
|
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
if service.MyService.System().GetSysInfo().KernelArch == "aarch64" && config.ServerInfo.USBAutoMount != "True" && strings.Contains(service.MyService.System().GetDeviceTree(), "Raspberry Pi") {
|
|
||||||
service.MyService.System().UpdateUSBAutoMount("False")
|
|
||||||
service.MyService.System().ExecUSBAutoMountShell("False")
|
|
||||||
}
|
|
||||||
|
|
||||||
// str := []string{}
|
|
||||||
// str = append(str, "ddd")
|
|
||||||
// str = append(str, "aaa")
|
|
||||||
// ddd := strings.Join(str, "|")
|
|
||||||
// config.Cfg.Section("file").Key("ShareDir").SetValue(ddd)
|
|
||||||
|
|
||||||
// config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func ImportApplications() {
|
|
||||||
service.MyService.App().ImportApplications(true)
|
|
||||||
}
|
|
||||||
|
|
||||||
// 0.3.1
|
|
||||||
func ChangeAPIUrl() {
|
|
||||||
|
|
||||||
newAPIUrl := "https://api.casaos.io/casaos-api"
|
|
||||||
if config.ServerInfo.ServerApi == "https://api.casaos.zimaboard.com" {
|
|
||||||
config.ServerInfo.ServerApi = newAPIUrl
|
|
||||||
config.Cfg.Section("server").Key("ServerApi").SetValue(newAPIUrl)
|
|
||||||
config.Cfg.SaveTo(config.SystemConfigInfo.ConfigPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//0.3.3
|
|
||||||
//Transferring user data to the database
|
|
||||||
func MoveUserToDB() {
|
|
||||||
|
|
||||||
if len(config.UserInfo.UserName) > 0 && service.MyService.User().GetUserInfoByUserName(config.UserInfo.UserName).Id == 0 {
|
|
||||||
user := model2.UserDBModel{}
|
|
||||||
user.Username = config.UserInfo.UserName
|
|
||||||
user.Email = config.UserInfo.Email
|
|
||||||
user.Nickname = config.UserInfo.NickName
|
|
||||||
user.Password = encryption.GetMD5ByStr(config.UserInfo.PWD)
|
|
||||||
user.Role = "admin"
|
|
||||||
user = service.MyService.User().CreateUser(user)
|
|
||||||
if user.Id > 0 {
|
|
||||||
userPath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id)
|
|
||||||
file.MkDir(userPath)
|
|
||||||
os.Rename("/casaOS/server/conf/app_order.json", userPath+"/app_order.json")
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func InitNetworkMount() {
|
func InitNetworkMount() {
|
||||||
|
time.Sleep(time.Second * 10)
|
||||||
connections := service.MyService.Connections().GetConnectionsList()
|
connections := service.MyService.Connections().GetConnectionsList()
|
||||||
for _, v := range connections {
|
for _, v := range connections {
|
||||||
connection := service.MyService.Connections().GetConnectionByID(fmt.Sprint(v.ID))
|
connection := service.MyService.Connections().GetConnectionByID(fmt.Sprint(v.ID))
|
||||||
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 {
|
||||||
service.MyService.Connections().DeleteConnection(fmt.Sprint(connection.ID))
|
service.MyService.Connections().DeleteConnection(fmt.Sprint(connection.ID))
|
||||||
|
loger.Error("mount samba err", zap.Any("err", err), zap.Any("info", connection))
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
baseHostPath := "/mnt/" + connection.Host
|
baseHostPath := "/mnt/" + connection.Host
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2022-07-01 15:11:36
|
* @Date: 2022-07-01 15:11:36
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-08-15 11:50:04
|
* @LastEditTime: 2022-09-05 16:28:46
|
||||||
* @FilePath: /CasaOS/route/periodical.go
|
* @FilePath: /CasaOS/route/periodical.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -14,20 +14,12 @@
|
|||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
|
||||||
"os/signal"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
"syscall"
|
|
||||||
"time"
|
"time"
|
||||||
"unsafe"
|
"unsafe"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/pilebones/go-udev/netlink"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
func SendNetINfoBySocket() {
|
func SendNetINfoBySocket() {
|
||||||
@@ -61,104 +53,6 @@ func SendMemBySocket() {
|
|||||||
service.MyService.Notify().SendMemInfoBySocket(service.MyService.System().GetMemInfo())
|
service.MyService.Notify().SendMemInfoBySocket(service.MyService.System().GetMemInfo())
|
||||||
}
|
}
|
||||||
|
|
||||||
func SendDiskBySocket() {
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
|
|
||||||
summary := model.Summary{}
|
|
||||||
healthy := true
|
|
||||||
findSystem := 0
|
|
||||||
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
if len(list[i].Children) > 0 && findSystem == 0 {
|
|
||||||
|
|
||||||
for j := 0; j < len(list[i].Children); j++ {
|
|
||||||
|
|
||||||
if len(list[i].Children[j].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children[j].Children {
|
|
||||||
if v.MountPoint == "/" {
|
|
||||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if list[i].Children[j].MountPoint == "/" {
|
|
||||||
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if findSystem == 1 {
|
|
||||||
findSystem += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
|
|
||||||
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
|
||||||
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
|
||||||
healthy = true
|
|
||||||
} else {
|
|
||||||
healthy = temp.SmartStatus.Passed
|
|
||||||
}
|
|
||||||
|
|
||||||
//list[i].Temperature = temp.Temperature.Current
|
|
||||||
|
|
||||||
if len(list[i].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children {
|
|
||||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
summary.Health = healthy
|
|
||||||
service.MyService.Notify().SendDiskInfoBySocket(summary)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendUSBBySocket() {
|
|
||||||
usbList := service.MyService.Disk().LSBLK(false)
|
|
||||||
usb := []model.DriveUSB{}
|
|
||||||
for _, v := range usbList {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
isMount := false
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Name
|
|
||||||
temp.Size = v.Size
|
|
||||||
for _, child := range v.Children {
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
isMount = true
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
temp.Avail += avail
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isMount {
|
|
||||||
usb = append(usb, temp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
service.MyService.Notify().SendUSBInfoBySocket(usb)
|
|
||||||
}
|
|
||||||
|
|
||||||
func SendAllHardwareStatusBySocket() {
|
func SendAllHardwareStatusBySocket() {
|
||||||
|
|
||||||
netList := service.MyService.System().GetNetInfo()
|
netList := service.MyService.System().GetNetInfo()
|
||||||
@@ -180,132 +74,47 @@ func SendAllHardwareStatusBySocket() {
|
|||||||
cpuData := make(map[string]interface{})
|
cpuData := make(map[string]interface{})
|
||||||
cpuData["percent"] = cpu
|
cpuData["percent"] = cpu
|
||||||
cpuData["num"] = num
|
cpuData["num"] = num
|
||||||
|
cpuData["temperature"] = service.MyService.System().GetCPUTemperature()
|
||||||
|
cpuData["power"] = service.MyService.System().GetCPUPower()
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
|
|
||||||
summary := model.Summary{}
|
|
||||||
healthy := true
|
|
||||||
findSystem := 0
|
|
||||||
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
if len(list[i].Children) > 0 && findSystem == 0 {
|
|
||||||
|
|
||||||
for j := 0; j < len(list[i].Children); j++ {
|
|
||||||
|
|
||||||
if len(list[i].Children[j].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children[j].Children {
|
|
||||||
if v.MountPoint == "/" {
|
|
||||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if list[i].Children[j].MountPoint == "/" {
|
|
||||||
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if findSystem == 1 {
|
|
||||||
findSystem += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
|
|
||||||
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
|
||||||
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
|
||||||
healthy = true
|
|
||||||
} else {
|
|
||||||
healthy = temp.SmartStatus.Passed
|
|
||||||
}
|
|
||||||
if len(list[i].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children {
|
|
||||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
summary.Health = healthy
|
|
||||||
|
|
||||||
usbList := service.MyService.Disk().LSBLK(false)
|
|
||||||
usb := []model.DriveUSB{}
|
|
||||||
for _, v := range usbList {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
isMount := false
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Name
|
|
||||||
temp.Size = v.Size
|
|
||||||
for _, child := range v.Children {
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
isMount = true
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
temp.Avail += avail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isMount {
|
|
||||||
usb = append(usb, temp)
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
memInfo := service.MyService.System().GetMemInfo()
|
memInfo := service.MyService.System().GetMemInfo()
|
||||||
|
|
||||||
service.MyService.Notify().SendAllHardwareStatusBySocket(summary, usb, memInfo, cpuData, newNet)
|
service.MyService.Notify().SendAllHardwareStatusBySocket(memInfo, cpuData, newNet)
|
||||||
|
|
||||||
}
|
}
|
||||||
func MonitoryUSB() {
|
|
||||||
var matcher netlink.Matcher
|
|
||||||
|
|
||||||
conn := new(netlink.UEventConn)
|
// func MonitoryUSB() {
|
||||||
if err := conn.Connect(netlink.UdevEvent); err != nil {
|
// var matcher netlink.Matcher
|
||||||
loger.Error("udev err", zap.Any("Unable to connect to Netlink Kobject UEvent socket", err))
|
|
||||||
}
|
|
||||||
defer conn.Close()
|
|
||||||
|
|
||||||
queue := make(chan netlink.UEvent)
|
// conn := new(netlink.UEventConn)
|
||||||
errors := make(chan error)
|
// if err := conn.Connect(netlink.UdevEvent); err != nil {
|
||||||
quit := conn.Monitor(queue, errors, matcher)
|
// loger.Error("udev err", zap.Any("Unable to connect to Netlink Kobject UEvent socket", err))
|
||||||
|
// }
|
||||||
|
// defer conn.Close()
|
||||||
|
|
||||||
signals := make(chan os.Signal, 1)
|
// queue := make(chan netlink.UEvent)
|
||||||
signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
// errors := make(chan error)
|
||||||
go func() {
|
// quit := conn.Monitor(queue, errors, matcher)
|
||||||
<-signals
|
|
||||||
close(quit)
|
|
||||||
os.Exit(0)
|
|
||||||
}()
|
|
||||||
|
|
||||||
for {
|
// signals := make(chan os.Signal, 1)
|
||||||
select {
|
// signal.Notify(signals, syscall.SIGINT, syscall.SIGTERM, syscall.SIGQUIT)
|
||||||
case uevent := <-queue:
|
// go func() {
|
||||||
if uevent.Env["DEVTYPE"] == "disk" {
|
// <-signals
|
||||||
time.Sleep(time.Microsecond * 500)
|
// close(quit)
|
||||||
SendUSBBySocket()
|
// os.Exit(0)
|
||||||
continue
|
// }()
|
||||||
}
|
|
||||||
case err := <-errors:
|
|
||||||
loger.Error("udev err", zap.Any("err", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
// for {
|
||||||
|
// select {
|
||||||
|
// case uevent := <-queue:
|
||||||
|
// if uevent.Env["DEVTYPE"] == "disk" {
|
||||||
|
// time.Sleep(time.Microsecond * 500)
|
||||||
|
// SendUSBBySocket()
|
||||||
|
// continue
|
||||||
|
// }
|
||||||
|
// case err := <-errors:
|
||||||
|
// loger.Error("udev err", zap.Any("err", err))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
|
||||||
|
// }
|
||||||
|
|||||||
191
route/route.go
@@ -1,107 +1,118 @@
|
|||||||
package route
|
package route
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"os"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/middleware"
|
"github.com/IceWhaleTech/CasaOS-Common/middleware"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/jwt"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
jwt2 "github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
|
|
||||||
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
||||||
"github.com/IceWhaleTech/CasaOS/web"
|
|
||||||
|
|
||||||
"github.com/gin-contrib/gzip"
|
"github.com/gin-contrib/gzip"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
var OnlineDemo bool = false
|
|
||||||
|
|
||||||
func InitRouter() *gin.Engine {
|
func InitRouter() *gin.Engine {
|
||||||
|
ginMode := gin.ReleaseMode
|
||||||
|
if config.ServerInfo.RunMode != "" {
|
||||||
|
ginMode = config.ServerInfo.RunMode
|
||||||
|
}
|
||||||
|
if os.Getenv(gin.EnvGinMode) != "" {
|
||||||
|
ginMode = os.Getenv(gin.EnvGinMode)
|
||||||
|
}
|
||||||
|
gin.SetMode(ginMode)
|
||||||
|
|
||||||
r := gin.Default()
|
r := gin.New()
|
||||||
|
r.Use(gin.Recovery())
|
||||||
r.Use(middleware.Cors())
|
r.Use(middleware.Cors())
|
||||||
r.Use(middleware.WriteLog())
|
|
||||||
r.Use(gzip.Gzip(gzip.DefaultCompression))
|
r.Use(gzip.Gzip(gzip.DefaultCompression))
|
||||||
gin.SetMode(config.ServerInfo.RunMode)
|
if ginMode != gin.ReleaseMode {
|
||||||
|
r.Use(middleware.WriteLog())
|
||||||
|
}
|
||||||
|
|
||||||
r.StaticFS("/ui", http.FS(web.Static))
|
// r.StaticFS("/ui", http.FS(web.Static))
|
||||||
r.GET("/", WebUIHome)
|
// r.GET("/", WebUIHome)
|
||||||
// r.StaticFS("/assets", http.Dir("./static/assets"))
|
// r.StaticFS("/assets", http.Dir("./static/assets"))
|
||||||
// r.StaticFile("/favicon.ico", "./static/favicon.ico")
|
// r.StaticFile("/favicon.ico", "./static/favicon.ico")
|
||||||
//r.GET("/", func(c *gin.Context) {
|
//r.GET("/", func(c *gin.Context) {
|
||||||
// c.Redirect(http.StatusMovedPermanently, "ui/")
|
// c.Redirect(http.StatusMovedPermanently, "ui/")
|
||||||
//})
|
//})
|
||||||
|
|
||||||
r.POST("/v1/users/register", v1.PostUserRegister)
|
// r.POST("/v1/users/register", v1.PostUserRegister)
|
||||||
r.POST("/v1/users/login", v1.PostUserLogin)
|
// r.POST("/v1/users/login", v1.PostUserLogin)
|
||||||
r.GET("/v1/users/name", v1.GetUserAllUsername) //all/name
|
// r.GET("/v1/users/name", v1.GetUserAllUsername) //all/name
|
||||||
r.POST("/v1/users/refresh", v1.PostUserRefreshToken)
|
// r.POST("/v1/users/refresh", v1.PostUserRefreshToken)
|
||||||
// No short-term modifications
|
// // No short-term modifications
|
||||||
r.GET("/v1/users/image", v1.GetUserImage)
|
// r.GET("/v1/users/image", v1.GetUserImage)
|
||||||
|
|
||||||
r.GET("/v1/users/status", v1.GetUserStatus) //init/check
|
// r.GET("/v1/users/status", v1.GetUserStatus) //init/check
|
||||||
//r.GET("/v1/guide/check", v1.GetGuideCheck) // /v1/sys/guide_check
|
// r.GET("/v1/guide/check", v1.GetGuideCheck) // /v1/sys/guide_check
|
||||||
r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug
|
r.GET("/v1/sys/debug", v1.GetSystemConfigDebug) // //debug
|
||||||
|
|
||||||
r.GET("/v1/sys/socket-port", v1.GetSystemSocketPort) //sys/socket_port
|
r.GET("/v1/sys/socket-port", v1.GetSystemSocketPort) //sys/socket_port
|
||||||
r.GET("/v1/sys/version/check", v1.GetSystemCheckVersion)
|
r.GET("/v1/sys/version/check", v1.GetSystemCheckVersion)
|
||||||
|
r.GET("/ping", func(ctx *gin.Context) {
|
||||||
|
ctx.String(200, "pong")
|
||||||
|
})
|
||||||
v1Group := r.Group("/v1")
|
v1Group := r.Group("/v1")
|
||||||
|
|
||||||
v1Group.Use(jwt2.JWT())
|
v1Group.Use(jwt.ExceptLocalhost())
|
||||||
{
|
{
|
||||||
v1UsersGroup := v1Group.Group("/users")
|
// v1UsersGroup := v1Group.Group("/users")
|
||||||
v1UsersGroup.Use()
|
// v1UsersGroup.Use()
|
||||||
{
|
// {
|
||||||
v1UsersGroup.GET("/current", v1.GetUserInfo)
|
// v1UsersGroup.GET("/current", v1.GetUserInfo)
|
||||||
v1UsersGroup.PUT("/current", v1.PutUserInfo)
|
// v1UsersGroup.PUT("/current", v1.PutUserInfo)
|
||||||
v1UsersGroup.PUT("/current/password", v1.PutUserPassword)
|
// v1UsersGroup.PUT("/current/password", v1.PutUserPassword)
|
||||||
|
|
||||||
v1UsersGroup.GET("/current/custom/:key", v1.GetUserCustomConf)
|
// v1UsersGroup.GET("/current/custom/:key", v1.GetUserCustomConf)
|
||||||
v1UsersGroup.POST("/current/custom/:key", v1.PostUserCustomConf)
|
// v1UsersGroup.POST("/current/custom/:key", v1.PostUserCustomConf)
|
||||||
v1UsersGroup.DELETE("/current/custom/:key", v1.DeleteUserCustomConf)
|
// v1UsersGroup.DELETE("/current/custom/:key", v1.DeleteUserCustomConf)
|
||||||
|
|
||||||
v1UsersGroup.POST("/current/image/:key", v1.PostUserUploadImage)
|
// v1UsersGroup.POST("/current/image/:key", v1.PostUserUploadImage)
|
||||||
v1UsersGroup.PUT("/current/image/:key", v1.PutUserImage)
|
// v1UsersGroup.PUT("/current/image/:key", v1.PutUserImage)
|
||||||
//v1UserGroup.POST("/file/image/:key", v1.PostUserFileImage)
|
// //v1UserGroup.POST("/file/image/:key", v1.PostUserFileImage)
|
||||||
v1UsersGroup.DELETE("/current/image", v1.DeleteUserImage)
|
// v1UsersGroup.DELETE("/current/image", v1.DeleteUserImage)
|
||||||
|
|
||||||
//v1UserGroup.PUT("/avatar", v1.PutUserAvatar)
|
// //v1UserGroup.PUT("/avatar", v1.PutUserAvatar)
|
||||||
//v1UserGroup.GET("/avatar", v1.GetUserAvatar)
|
// //v1UserGroup.GET("/avatar", v1.GetUserAvatar)
|
||||||
v1UsersGroup.DELETE("/:id", v1.DeleteUser)
|
// v1UsersGroup.DELETE("/:id", v1.DeleteUser)
|
||||||
v1UsersGroup.GET("/:username", v1.GetUserInfoByUsername)
|
// v1UsersGroup.GET("/:username", v1.GetUserInfoByUsername)
|
||||||
v1UsersGroup.DELETE("", v1.DeleteUserAll)
|
// v1UsersGroup.DELETE("", v1.DeleteUserAll)
|
||||||
}
|
// }
|
||||||
|
|
||||||
v1AppsGroup := v1Group.Group("/apps")
|
v1AppsGroup := v1Group.Group("/apps")
|
||||||
v1AppsGroup.Use()
|
v1AppsGroup.Use()
|
||||||
{
|
{
|
||||||
v1AppsGroup.GET("", v1.AppList) //list
|
v1AppsGroup.GET("", v1.AppList) // list
|
||||||
v1AppsGroup.GET("/:id", v1.AppInfo)
|
v1AppsGroup.GET("/:id", v1.AppInfo)
|
||||||
}
|
}
|
||||||
v1ContainerGroup := v1Group.Group("/container")
|
v1ContainerGroup := v1Group.Group("/container")
|
||||||
v1ContainerGroup.Use()
|
v1ContainerGroup.Use()
|
||||||
{
|
{
|
||||||
|
|
||||||
v1ContainerGroup.GET("", v1.MyAppList) ///my/list
|
v1ContainerGroup.GET("", v1.MyAppList) ///my/list
|
||||||
v1ContainerGroup.GET("/usage", v1.AppUsageList)
|
v1ContainerGroup.GET("/usage", v1.AppUsageList)
|
||||||
v1ContainerGroup.GET("/:id", v1.ContainerUpdateInfo) ///update/:id/info
|
v1ContainerGroup.GET("/:id", v1.ContainerUpdateInfo) ///update/:id/info
|
||||||
v1ContainerGroup.GET("/:id/logs", v1.ContainerLog) // /app/logs/:id
|
v1ContainerGroup.GET("/:id/logs", v1.ContainerLog) // /app/logs/:id
|
||||||
v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) //app/install/config
|
v1ContainerGroup.GET("/networks", v1.GetDockerNetworks) // app/install/config
|
||||||
|
|
||||||
v1ContainerGroup.GET("/:id/state", v1.GetContainerState) //app/state/:id ?state=install_progress
|
v1ContainerGroup.GET("/:id/state", v1.GetContainerState) // app/state/:id ?state=install_progress
|
||||||
// there are problems, temporarily do not deal with
|
// there are problems, temporarily do not deal with
|
||||||
v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) //app/terminal/:id
|
v1ContainerGroup.GET("/:id/terminal", v1.DockerTerminal) // app/terminal/:id
|
||||||
v1ContainerGroup.POST("", v1.InstallApp) //app/install
|
v1ContainerGroup.POST("", v1.InstallApp) // app/install
|
||||||
//v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id
|
// v1ContainerGroup.GET("/:id", v1.ContainerInfo) // /app/info/:id
|
||||||
|
|
||||||
v1ContainerGroup.PUT("/:id", v1.UpdateSetting) ///update/:id/setting
|
v1ContainerGroup.PUT("/:id", v1.UpdateSetting) ///update/:id/setting
|
||||||
|
|
||||||
v1ContainerGroup.PUT("/:id/state", v1.ChangAppState) // /app/state/:id
|
v1ContainerGroup.PUT("/:id/state", v1.ChangAppState) // /app/state/:id
|
||||||
v1ContainerGroup.DELETE("/:id", v1.UnInstallApp) //app/uninstall/:id
|
v1ContainerGroup.DELETE("/:id", v1.UnInstallApp) // app/uninstall/:id
|
||||||
//Not used
|
// Not used
|
||||||
v1ContainerGroup.PUT("/:id/latest", v1.PutAppUpdate)
|
v1ContainerGroup.PUT("/:id/latest", v1.PutAppUpdate)
|
||||||
//Not used
|
// Not used
|
||||||
v1ContainerGroup.POST("/share", v1.ShareAppFile)
|
v1ContainerGroup.POST("/share", v1.ShareAppFile)
|
||||||
|
v1ContainerGroup.GET("/info", v1.GetDockerDaemonConfiguration)
|
||||||
|
v1ContainerGroup.PUT("/info", v1.PutDockerDaemonConfiguration)
|
||||||
|
|
||||||
}
|
}
|
||||||
v1AppCategoriesGroup := v1Group.Group("/app-categories")
|
v1AppCategoriesGroup := v1Group.Group("/app-categories")
|
||||||
@@ -113,19 +124,19 @@ func InitRouter() *gin.Engine {
|
|||||||
v1SysGroup := v1Group.Group("/sys")
|
v1SysGroup := v1Group.Group("/sys")
|
||||||
v1SysGroup.Use()
|
v1SysGroup.Use()
|
||||||
{
|
{
|
||||||
v1SysGroup.GET("/version", v1.GetSystemCheckVersion) //version/check
|
v1SysGroup.GET("/version", v1.GetSystemCheckVersion) // version/check
|
||||||
|
|
||||||
v1SysGroup.POST("/update", v1.SystemUpdate)
|
v1SysGroup.POST("/update", v1.SystemUpdate)
|
||||||
|
|
||||||
v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) //hardware/info
|
v1SysGroup.GET("/hardware", v1.GetSystemHardwareInfo) // hardware/info
|
||||||
|
|
||||||
v1SysGroup.GET("/wsssh", v1.WsSsh)
|
v1SysGroup.GET("/wsssh", v1.WsSsh)
|
||||||
v1SysGroup.POST("/ssh-login", v1.PostSshLogin)
|
v1SysGroup.POST("/ssh-login", v1.PostSshLogin)
|
||||||
//v1SysGroup.GET("/config", v1.GetSystemConfig) //delete
|
// v1SysGroup.GET("/config", v1.GetSystemConfig) //delete
|
||||||
//v1SysGroup.POST("/config", v1.PostSetSystemConfig)
|
// v1SysGroup.POST("/config", v1.PostSetSystemConfig)
|
||||||
v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) //error/logs
|
v1SysGroup.GET("/logs", v1.GetCasaOSErrorLogs) // error/logs
|
||||||
//v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete
|
// v1SysGroup.GET("/widget/config", v1.GetWidgetConfig)//delete
|
||||||
//v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)//delete
|
// v1SysGroup.POST("/widget/config", v1.PostSetWidgetConfig)//delete
|
||||||
|
|
||||||
v1SysGroup.POST("/stop", v1.PostKillCasaOS)
|
v1SysGroup.POST("/stop", v1.PostKillCasaOS)
|
||||||
|
|
||||||
@@ -141,30 +152,31 @@ func InitRouter() *gin.Engine {
|
|||||||
v1SysGroup.GET("/server-info", nil)
|
v1SysGroup.GET("/server-info", nil)
|
||||||
v1SysGroup.PUT("/server-info", nil)
|
v1SysGroup.PUT("/server-info", nil)
|
||||||
v1SysGroup.GET("/apps-state", v1.GetSystemAppsStatus)
|
v1SysGroup.GET("/apps-state", v1.GetSystemAppsStatus)
|
||||||
v1SysGroup.GET("/port", v1.GetCasaOSPort)
|
// v1SysGroup.GET("/port", v1.GetCasaOSPort)
|
||||||
v1SysGroup.PUT("/port", v1.PutCasaOSPort)
|
// v1SysGroup.PUT("/port", v1.PutCasaOSPort)
|
||||||
|
v1SysGroup.GET("/proxy", v1.GetSystemProxy)
|
||||||
}
|
}
|
||||||
v1PortGroup := v1Group.Group("/port")
|
v1PortGroup := v1Group.Group("/port")
|
||||||
v1PortGroup.Use()
|
v1PortGroup.Use()
|
||||||
{
|
{
|
||||||
v1PortGroup.GET("/", v1.GetPort) //app/port
|
v1PortGroup.GET("/", v1.GetPort) // app/port
|
||||||
v1PortGroup.GET("/state/:port", v1.PortCheck) //app/check/:port
|
v1PortGroup.GET("/state/:port", v1.PortCheck) // app/check/:port
|
||||||
}
|
}
|
||||||
|
|
||||||
v1FileGroup := v1Group.Group("/file")
|
v1FileGroup := v1Group.Group("/file")
|
||||||
v1FileGroup.Use()
|
v1FileGroup.Use()
|
||||||
{
|
{
|
||||||
v1FileGroup.GET("", v1.GetDownloadSingleFile) //download/:path
|
v1FileGroup.GET("", v1.GetDownloadSingleFile) // download/:path
|
||||||
v1FileGroup.POST("", v1.PostCreateFile)
|
v1FileGroup.POST("", v1.PostCreateFile)
|
||||||
v1FileGroup.PUT("", v1.PutFileContent)
|
v1FileGroup.PUT("", v1.PutFileContent)
|
||||||
v1FileGroup.PUT("/name", v1.RenamePath)
|
v1FileGroup.PUT("/name", v1.RenamePath)
|
||||||
//file/rename
|
// file/rename
|
||||||
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.GET("/upload", v1.GetFileUpload)
|
v1FileGroup.GET("/upload", v1.GetFileUpload)
|
||||||
//v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
// v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
||||||
}
|
}
|
||||||
v1FolderGroup := v1Group.Group("/folder")
|
v1FolderGroup := v1Group.Group("/folder")
|
||||||
v1FolderGroup.Use()
|
v1FolderGroup.Use()
|
||||||
@@ -177,9 +189,9 @@ func InitRouter() *gin.Engine {
|
|||||||
v1BatchGroup.Use()
|
v1BatchGroup.Use()
|
||||||
{
|
{
|
||||||
|
|
||||||
v1BatchGroup.DELETE("", v1.DeleteFile) //file/delete
|
v1BatchGroup.DELETE("", v1.DeleteFile) // file/delete
|
||||||
v1BatchGroup.DELETE("/:id/task", v1.DeleteOperateFileOrDir)
|
v1BatchGroup.DELETE("/:id/task", v1.DeleteOperateFileOrDir)
|
||||||
v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) //file/operate
|
v1BatchGroup.POST("/task", v1.PostOperateFileOrDir) // file/operate
|
||||||
v1BatchGroup.GET("", v1.GetDownloadFile)
|
v1BatchGroup.GET("", v1.GetDownloadFile)
|
||||||
}
|
}
|
||||||
v1ImageGroup := v1Group.Group("/image")
|
v1ImageGroup := v1Group.Group("/image")
|
||||||
@@ -187,42 +199,6 @@ func InitRouter() *gin.Engine {
|
|||||||
{
|
{
|
||||||
v1ImageGroup.GET("", v1.GetFileImage)
|
v1ImageGroup.GET("", v1.GetFileImage)
|
||||||
}
|
}
|
||||||
|
|
||||||
v1DisksGroup := v1Group.Group("/disks")
|
|
||||||
v1DisksGroup.Use()
|
|
||||||
{
|
|
||||||
//v1DiskGroup.GET("/check", v1.GetDiskCheck) //delete
|
|
||||||
//v1DisksGroup.GET("", v1.GetDiskInfo)
|
|
||||||
|
|
||||||
//v1DisksGroup.POST("", v1.PostMountDisk)
|
|
||||||
v1DisksGroup.GET("", v1.GetDiskList)
|
|
||||||
v1DisksGroup.GET("/usb", v1.GetDisksUSBList)
|
|
||||||
v1DisksGroup.DELETE("/usb", v1.DeleteDiskUSB)
|
|
||||||
v1DisksGroup.DELETE("", v1.DeleteDisksUmount)
|
|
||||||
// //format storage
|
|
||||||
// v1DiskGroup.POST("/format", v1.PostDiskFormat)
|
|
||||||
|
|
||||||
// //mount SATA disk
|
|
||||||
// v1DiskGroup.POST("/mount", v1.PostMountDisk)
|
|
||||||
|
|
||||||
// //umount sata disk
|
|
||||||
// v1DiskGroup.POST("/umount", v1.PostDiskUmount)
|
|
||||||
|
|
||||||
//v1DiskGroup.GET("/type", v1.FormatDiskType)//delete
|
|
||||||
|
|
||||||
v1DisksGroup.DELETE("/part", v1.RemovePartition) //disk/delpart
|
|
||||||
}
|
|
||||||
|
|
||||||
v1StorageGroup := v1Group.Group("/storage")
|
|
||||||
v1StorageGroup.Use()
|
|
||||||
{
|
|
||||||
v1StorageGroup.POST("", v1.PostDiskAddPartition)
|
|
||||||
|
|
||||||
v1StorageGroup.PUT("", v1.PostDiskFormat)
|
|
||||||
|
|
||||||
v1StorageGroup.DELETE("", v1.PostDiskUmount)
|
|
||||||
v1StorageGroup.GET("", v1.GetStorageList)
|
|
||||||
}
|
|
||||||
v1SambaGroup := v1Group.Group("/samba")
|
v1SambaGroup := v1Group.Group("/samba")
|
||||||
v1SambaGroup.Use()
|
v1SambaGroup.Use()
|
||||||
{
|
{
|
||||||
@@ -242,6 +218,13 @@ func InitRouter() *gin.Engine {
|
|||||||
v1SharesGroup.GET("/status", v1.GetSambaStatus)
|
v1SharesGroup.GET("/status", v1.GetSambaStatus)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
v1NotifyGroup := v1Group.Group("/notify")
|
||||||
|
v1NotifyGroup.Use()
|
||||||
|
{
|
||||||
|
v1NotifyGroup.POST("/:path", v1.PostNotifyMessage)
|
||||||
|
// merge to system
|
||||||
|
v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return r
|
return r
|
||||||
}
|
}
|
||||||
|
|||||||
25
route/ui.go
@@ -1,25 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-06-23 17:27:43
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-06-23 17:27:48
|
|
||||||
* @FilePath: /CasaOS/route/ui.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package route
|
|
||||||
|
|
||||||
import (
|
|
||||||
"html/template"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/web"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
func WebUIHome(c *gin.Context) {
|
|
||||||
c.Writer.Header().Set("Content-Type", "text/html; charset=utf-8")
|
|
||||||
index, _ := template.ParseFS(web.Static, "index.html")
|
|
||||||
index.Execute(c.Writer, nil)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
103
route/v1/app.go
@@ -3,9 +3,12 @@ package v1
|
|||||||
import (
|
import (
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
"net/http"
|
||||||
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
|
||||||
@@ -14,6 +17,11 @@ import (
|
|||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
const (
|
||||||
|
dockerRootDirFilePath = "/var/lib/casaos/docker_root"
|
||||||
|
dockerDaemonConfigurationFilePath = "/etc/docker/daemon.json"
|
||||||
|
)
|
||||||
|
|
||||||
// @Summary 获取远程列表
|
// @Summary 获取远程列表
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
@@ -27,8 +35,7 @@ import (
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /app/list [get]
|
// @Router /app/list [get]
|
||||||
func AppList(c *gin.Context) {
|
func AppList(c *gin.Context) {
|
||||||
|
// service.MyService.Docker().DockerContainerCommit("test2")
|
||||||
//service.MyService.Docker().DockerContainerCommit("test2")
|
|
||||||
|
|
||||||
index := c.DefaultQuery("index", "1")
|
index := c.DefaultQuery("index", "1")
|
||||||
size := c.DefaultQuery("size", "10000")
|
size := c.DefaultQuery("size", "10000")
|
||||||
@@ -137,7 +144,7 @@ func MyAppList(c *gin.Context) {
|
|||||||
func AppUsageList(c *gin.Context) {
|
func AppUsageList(c *gin.Context) {
|
||||||
list := service.MyService.App().GetHardwareUsage()
|
list := service.MyService.App().GetHardwareUsage()
|
||||||
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
|
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: list})
|
||||||
//c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: nil})
|
// c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: nil})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 应用详情
|
// @Summary 应用详情
|
||||||
@@ -149,7 +156,6 @@ func AppUsageList(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /app/appinfo/{id} [get]
|
// @Router /app/appinfo/{id} [get]
|
||||||
func AppInfo(c *gin.Context) {
|
func AppInfo(c *gin.Context) {
|
||||||
|
|
||||||
id := c.Param("id")
|
id := c.Param("id")
|
||||||
language := c.GetHeader("Language")
|
language := c.GetHeader("Language")
|
||||||
info, err := service.MyService.Casa().GetServerAppInfo(id, "", language)
|
info, err := service.MyService.Casa().GetServerAppInfo(id, "", language)
|
||||||
@@ -211,7 +217,7 @@ func AppInfo(c *gin.Context) {
|
|||||||
// return c1.Type < c2.Type
|
// return c1.Type < c2.Type
|
||||||
// }
|
// }
|
||||||
|
|
||||||
//sort
|
// sort
|
||||||
// if info.NetworkModel != "host" {
|
// if info.NetworkModel != "host" {
|
||||||
// sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
|
// sort.PortsSort(portOrder).Sort(info.Configures.TcpPorts)
|
||||||
// sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
|
// sort.PortsSort(portOrder).Sort(info.Configures.UdpPorts)
|
||||||
@@ -220,7 +226,7 @@ func AppInfo(c *gin.Context) {
|
|||||||
// sort.EnvSort(envOrder).Sort(info.Envs)
|
// sort.EnvSort(envOrder).Sort(info.Envs)
|
||||||
// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
|
// sort.VolSort(volOrder).Sort(info.Volumes.([]model.PathMap))
|
||||||
// sort.DevSort(devOrder).Sort(info.Devices)
|
// sort.DevSort(devOrder).Sort(info.Devices)
|
||||||
|
info.Image += ":" + info.ImageVersion
|
||||||
info.MaxMemory = (service.MyService.System().GetMemInfo()["total"]).(uint64) >> 20
|
info.MaxMemory = (service.MyService.System().GetMemInfo()["total"]).(uint64) >> 20
|
||||||
|
|
||||||
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info})
|
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: info})
|
||||||
@@ -262,3 +268,88 @@ func ShareAppFile(c *gin.Context) {
|
|||||||
content := service.MyService.Casa().ShareAppFile(str)
|
content := service.MyService.Casa().ShareAppFile(str)
|
||||||
c.JSON(common_err.SUCCESS, json.RawMessage(content))
|
c.JSON(common_err.SUCCESS, json.RawMessage(content))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetDockerDaemonConfiguration(c *gin.Context) {
|
||||||
|
// info, err := service.MyService.Docker().GetDockerInfo()
|
||||||
|
// if err != nil {
|
||||||
|
// c.JSON(common_err.SERVICE_ERROR, &model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||||
|
// return
|
||||||
|
// }
|
||||||
|
data := make(map[string]interface{})
|
||||||
|
|
||||||
|
if file.Exists(dockerRootDirFilePath) {
|
||||||
|
buf := file.ReadFullFile(dockerRootDirFilePath)
|
||||||
|
err := json.Unmarshal(buf, &data)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(common_err.CLIENT_ERROR, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.JSON(common_err.SUCCESS, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
||||||
|
}
|
||||||
|
|
||||||
|
func PutDockerDaemonConfiguration(c *gin.Context) {
|
||||||
|
request := make(map[string]interface{})
|
||||||
|
if err := c.BindJSON(&request); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
value, ok := request["docker_root_dir"]
|
||||||
|
if !ok {
|
||||||
|
c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "`docker_root_dir` should not empty"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dockerConfig := model.DockerDaemonConfigurationModel{}
|
||||||
|
if file.Exists(dockerDaemonConfigurationFilePath) {
|
||||||
|
byteResult := file.ReadFullFile(dockerDaemonConfigurationFilePath)
|
||||||
|
err := json.Unmarshal(byteResult, &dockerConfig)
|
||||||
|
if err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to deserialize " + dockerDaemonConfigurationFilePath, Data: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
dockerRootDir := value.(string)
|
||||||
|
if dockerRootDir == "/" {
|
||||||
|
dockerConfig.Root = "" // omitempty - empty string will not be serialized
|
||||||
|
} else {
|
||||||
|
if !file.Exists(dockerRootDir) {
|
||||||
|
c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS), Data: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
dockerConfig.Root = filepath.Join(dockerRootDir, "docker")
|
||||||
|
|
||||||
|
if err := file.IsNotExistMkDir(dockerConfig.Root); err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to create " + dockerConfig.Root, Data: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if buf, err := json.Marshal(request); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: "error when trying to serialize docker root json", Data: err})
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
if err := file.WriteToFullPath(buf, dockerRootDirFilePath, 0o644); err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write " + dockerRootDirFilePath, Data: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if buf, err := json.Marshal(dockerConfig); err != nil {
|
||||||
|
c.JSON(http.StatusBadRequest, &model.Result{Success: common_err.CLIENT_ERROR, Message: "error when trying to serialize docker config", Data: dockerConfig})
|
||||||
|
return
|
||||||
|
} else {
|
||||||
|
if err := file.WriteToFullPath(buf, dockerDaemonConfigurationFilePath, 0o644); err != nil {
|
||||||
|
c.JSON(http.StatusInternalServerError, &model.Result{Success: common_err.SERVICE_ERROR, Message: "error when trying to write to " + dockerDaemonConfigurationFilePath, Data: err})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
println(command.ExecResultStr("systemctl daemon-reload"))
|
||||||
|
println(command.ExecResultStr("systemctl restart docker"))
|
||||||
|
|
||||||
|
c.JSON(http.StatusOK, &model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: request})
|
||||||
|
}
|
||||||
|
|||||||
595
route/v1/disk.go
@@ -1,595 +0,0 @@
|
|||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"net/http"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
|
||||||
)
|
|
||||||
|
|
||||||
var diskMap = make(map[string]string)
|
|
||||||
|
|
||||||
// @Summary disk list
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/list [get]
|
|
||||||
func GetDiskList(c *gin.Context) {
|
|
||||||
path := c.Query("path")
|
|
||||||
if len(path) > 0 {
|
|
||||||
m := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
t := c.DefaultQuery("type", "")
|
|
||||||
list := service.MyService.Disk().LSBLK(false)
|
|
||||||
if t == "usb" {
|
|
||||||
data := []model.DriveUSB{}
|
|
||||||
for _, v := range list {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Name
|
|
||||||
temp.Size = v.Size
|
|
||||||
for _, child := range v.Children {
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
temp.Avail += avail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data = append(data, temp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
dbList := service.MyService.Disk().GetSerialAll()
|
|
||||||
part := make(map[string]int64, len(dbList))
|
|
||||||
for _, v := range dbList {
|
|
||||||
part[v.MountPoint] = v.CreatedAt
|
|
||||||
}
|
|
||||||
findSystem := 0
|
|
||||||
|
|
||||||
disks := []model.Drive{}
|
|
||||||
storage := []model.Storage{}
|
|
||||||
avail := []model.Drive{}
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
disk := model.Drive{}
|
|
||||||
if list[i].Rota {
|
|
||||||
disk.DiskType = "HDD"
|
|
||||||
} else {
|
|
||||||
disk.DiskType = "SSD"
|
|
||||||
}
|
|
||||||
disk.Serial = list[i].Serial
|
|
||||||
disk.Name = list[i].Name
|
|
||||||
disk.Size = list[i].Size
|
|
||||||
disk.Path = list[i].Path
|
|
||||||
disk.Model = list[i].Model
|
|
||||||
disk.ChildrenNumber = len(list[i].Children)
|
|
||||||
if len(list[i].Children) > 0 && findSystem == 0 {
|
|
||||||
for j := 0; j < len(list[i].Children); j++ {
|
|
||||||
if len(list[i].Children[j].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children[j].Children {
|
|
||||||
if v.MountPoint == "/" {
|
|
||||||
stor := model.Storage{}
|
|
||||||
stor.MountPoint = v.MountPoint
|
|
||||||
stor.Size = v.FSSize
|
|
||||||
stor.Avail = v.FSAvail
|
|
||||||
stor.Path = v.Path
|
|
||||||
stor.Type = v.FsType
|
|
||||||
stor.DriveName = "System"
|
|
||||||
disk.Model = "System"
|
|
||||||
if strings.Contains(v.SubSystems, "mmc") {
|
|
||||||
disk.DiskType = "MMC"
|
|
||||||
} else if strings.Contains(v.SubSystems, "usb") {
|
|
||||||
disk.DiskType = "USB"
|
|
||||||
}
|
|
||||||
disk.Health = "true"
|
|
||||||
|
|
||||||
disks = append(disks, disk)
|
|
||||||
storage = append(storage, stor)
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if list[i].Children[j].MountPoint == "/" {
|
|
||||||
stor := model.Storage{}
|
|
||||||
stor.MountPoint = list[i].Children[j].MountPoint
|
|
||||||
stor.Size = list[i].Children[j].FSSize
|
|
||||||
stor.Avail = list[i].Children[j].FSAvail
|
|
||||||
stor.Path = list[i].Children[j].Path
|
|
||||||
stor.Type = list[i].Children[j].FsType
|
|
||||||
stor.DriveName = "System"
|
|
||||||
disk.Model = "System"
|
|
||||||
if strings.Contains(list[i].Children[j].SubSystems, "mmc") {
|
|
||||||
disk.DiskType = "MMC"
|
|
||||||
} else if strings.Contains(list[i].Children[j].SubSystems, "usb") {
|
|
||||||
disk.DiskType = "USB"
|
|
||||||
}
|
|
||||||
disk.Health = "true"
|
|
||||||
|
|
||||||
disks = append(disks, disk)
|
|
||||||
storage = append(storage, stor)
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if findSystem == 1 {
|
|
||||||
findSystem += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
|
|
||||||
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
|
|
||||||
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
|
||||||
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
|
||||||
temp.SmartStatus.Passed = true
|
|
||||||
}
|
|
||||||
isAvail := true
|
|
||||||
for _, v := range list[i].Children {
|
|
||||||
if v.MountPoint != "" {
|
|
||||||
stor := model.Storage{}
|
|
||||||
stor.MountPoint = v.MountPoint
|
|
||||||
stor.Size = v.FSSize
|
|
||||||
stor.Avail = v.FSAvail
|
|
||||||
stor.Path = v.Path
|
|
||||||
stor.Type = v.FsType
|
|
||||||
stor.DriveName = list[i].Name
|
|
||||||
storage = append(storage, stor)
|
|
||||||
isAvail = false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if isAvail {
|
|
||||||
//if len(list[i].Children) == 1 && list[i].Children[0].FsType == "ext4" {
|
|
||||||
disk.NeedFormat = false
|
|
||||||
avail = append(avail, disk)
|
|
||||||
// } else {
|
|
||||||
// disk.NeedFormat = true
|
|
||||||
// avail = append(avail, disk)
|
|
||||||
// }
|
|
||||||
}
|
|
||||||
|
|
||||||
disk.Temperature = temp.Temperature.Current
|
|
||||||
disk.Health = strconv.FormatBool(temp.SmartStatus.Passed)
|
|
||||||
|
|
||||||
disks = append(disks, disk)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data := make(map[string]interface{}, 3)
|
|
||||||
data["drive"] = disks
|
|
||||||
data["storage"] = storage
|
|
||||||
data["avail"] = avail
|
|
||||||
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary disk list
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/list [get]
|
|
||||||
func GetDisksUSBList(c *gin.Context) {
|
|
||||||
list := service.MyService.Disk().LSBLK(false)
|
|
||||||
data := []model.DriveUSB{}
|
|
||||||
for _, v := range list {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Label
|
|
||||||
if temp.Name == "" {
|
|
||||||
temp.Name = v.Name
|
|
||||||
}
|
|
||||||
temp.Size = v.Size
|
|
||||||
children := []model.USBChildren{}
|
|
||||||
for _, child := range v.Children {
|
|
||||||
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
tempChildren := model.USBChildren{}
|
|
||||||
tempChildren.MountPoint = child.MountPoint
|
|
||||||
tempChildren.Size, _ = strconv.ParseUint(child.FSSize, 10, 64)
|
|
||||||
tempChildren.Avail, _ = strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
tempChildren.Name = child.Label
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
children = append(children, tempChildren)
|
|
||||||
temp.Avail += avail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
temp.Children = children
|
|
||||||
data = append(data, temp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteDisksUmount(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
js := make(map[string]string)
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
|
|
||||||
path := js["path"]
|
|
||||||
pwd := js["password"]
|
|
||||||
|
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user := service.MyService.User().GetUserAllInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if encryption.GetMD5ByStr(pwd) != user.Password {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := diskMap[path]; ok {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
diskInfo := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
for _, v := range diskInfo.Children {
|
|
||||||
service.MyService.Disk().UmountPointAndRemoveDir(v.Path)
|
|
||||||
//delete data
|
|
||||||
service.MyService.Disk().DeleteMountPoint(v.Path, v.MountPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
|
|
||||||
//send notify to client
|
|
||||||
msg := notify.StorageMessage{}
|
|
||||||
msg.Action = "REMOVED"
|
|
||||||
msg.Path = path
|
|
||||||
msg.Volume = ""
|
|
||||||
msg.Size = 0
|
|
||||||
msg.Type = ""
|
|
||||||
service.MyService.Notify().SendStorageBySocket(msg)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: path})
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteDiskUSB(c *gin.Context) {
|
|
||||||
js := make(map[string]string)
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
mountPoint := js["mount_point"]
|
|
||||||
if file.CheckNotExist(mountPoint) {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.DIR_NOT_EXISTS, Message: common_err.GetMsg(common_err.DIR_NOT_EXISTS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
service.MyService.Disk().UmountUSB(mountPoint)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: mountPoint})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary get disk list
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/lists [get]
|
|
||||||
func GetPlugInDisks(c *gin.Context) {
|
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
var result []*disk.UsageStat
|
|
||||||
for _, item := range list {
|
|
||||||
result = append(result, service.MyService.Disk().GetDiskInfoByPath(item.Path))
|
|
||||||
}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: result})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary disk detail
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path query string true "for example /dev/sda"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/info [get]
|
|
||||||
func GetDiskInfo(c *gin.Context) {
|
|
||||||
path := c.Query("path")
|
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
}
|
|
||||||
m := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: m})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 获取支持的格式
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/type [get]
|
|
||||||
func FormatDiskType(c *gin.Context) {
|
|
||||||
var strArr = [4]string{"fat32", "ntfs", "ext4", "exfat"}
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: strArr})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 删除分区
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "磁盘路径 例如/dev/sda1"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/delpart [delete]
|
|
||||||
func RemovePartition(c *gin.Context) {
|
|
||||||
js := make(map[string]string)
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
path := js["path"]
|
|
||||||
|
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
}
|
|
||||||
var p = path[:len(path)-1]
|
|
||||||
var n = path[len(path)-1:]
|
|
||||||
service.MyService.Disk().DelPartition(p, n)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary add storage
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "disk path e.g. /dev/sda"
|
|
||||||
// @Param serial formData string true "serial"
|
|
||||||
// @Param name formData string true "name"
|
|
||||||
// @Param format formData bool true "need format(true)"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/storage [post]
|
|
||||||
func PostDiskAddPartition(c *gin.Context) {
|
|
||||||
|
|
||||||
js := make(map[string]interface{})
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
path := js["path"].(string)
|
|
||||||
//name := js["name"].(string)
|
|
||||||
format := js["format"].(bool)
|
|
||||||
|
|
||||||
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
|
|
||||||
}
|
|
||||||
if _, ok := diskMap[path]; ok {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//diskInfo := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
|
|
||||||
// if !file.CheckNotExist("/DATA/" + name) {
|
|
||||||
// // /mnt/name exist
|
|
||||||
// c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
diskMap[path] = "busying"
|
|
||||||
currentDisk := service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
if format {
|
|
||||||
// format := service.MyService.Disk().FormatDisk(path+"1", "ext4")
|
|
||||||
// if len(format) == 0 {
|
|
||||||
// delete(diskMap, path)
|
|
||||||
// c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
service.MyService.Disk().AddPartition(path)
|
|
||||||
}
|
|
||||||
|
|
||||||
// formatBool := true
|
|
||||||
// for formatBool {
|
|
||||||
// currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
// if len(currentDisk.Children) > 0 {
|
|
||||||
// formatBool = false
|
|
||||||
// break
|
|
||||||
// }
|
|
||||||
// time.Sleep(time.Second)
|
|
||||||
// }
|
|
||||||
currentDisk = service.MyService.Disk().GetDiskInfo(path)
|
|
||||||
// if len(currentDisk.Children) != 1 {
|
|
||||||
// c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_NEEDS_FORMAT, Message: common_err.GetMsg(common_err.DISK_NEEDS_FORMAT)})
|
|
||||||
// return
|
|
||||||
// }
|
|
||||||
for i := 0; i < len(currentDisk.Children); i++ {
|
|
||||||
childrenName := currentDisk.Children[i].Label
|
|
||||||
if len(childrenName) == 0 {
|
|
||||||
childrenName = "Storage_" + currentDisk.Children[i].Name
|
|
||||||
}
|
|
||||||
mountPath := "/DATA/" + childrenName
|
|
||||||
if !file.CheckNotExist(mountPath) {
|
|
||||||
ls := service.MyService.System().GetDirPath(mountPath)
|
|
||||||
if len(ls) > 0 {
|
|
||||||
// exist
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NAME_NOT_AVAILABLE, Message: common_err.GetMsg(common_err.NAME_NOT_AVAILABLE)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
m := model2.SerialDisk{}
|
|
||||||
m.MountPoint = mountPath
|
|
||||||
m.Path = currentDisk.Children[i].Path
|
|
||||||
m.UUID = currentDisk.Children[i].UUID
|
|
||||||
m.State = 0
|
|
||||||
m.CreatedAt = time.Now().Unix()
|
|
||||||
service.MyService.Disk().SaveMountPoint(m)
|
|
||||||
//mount dir
|
|
||||||
service.MyService.Disk().MountDisk(currentDisk.Children[i].Path, mountPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
|
|
||||||
delete(diskMap, path)
|
|
||||||
|
|
||||||
//send notify to client
|
|
||||||
msg := notify.StorageMessage{}
|
|
||||||
msg.Action = "ADDED"
|
|
||||||
msg.Path = currentDisk.Children[0].Path
|
|
||||||
msg.Volume = "/DATA/"
|
|
||||||
msg.Size = currentDisk.Children[0].Size
|
|
||||||
msg.Type = currentDisk.Children[0].Tran
|
|
||||||
service.MyService.Notify().SendStorageBySocket(msg)
|
|
||||||
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Param pwd formData string true "user password"
|
|
||||||
// @Param volume formData string true "mount point"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/format [post]
|
|
||||||
func PostDiskFormat(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
js := make(map[string]string)
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
path := js["path"]
|
|
||||||
t := "ext4"
|
|
||||||
pwd := js["password"]
|
|
||||||
volume := js["volume"]
|
|
||||||
user := service.MyService.User().GetUserAllInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if encryption.GetMD5ByStr(pwd) != user.Password {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(path) == 0 || len(t) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if _, ok := diskMap[path]; ok {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
diskMap[path] = "busying"
|
|
||||||
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
|
||||||
format := service.MyService.Disk().FormatDisk(path, t)
|
|
||||||
if len(format) == 0 {
|
|
||||||
delete(diskMap, path)
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FORMAT_ERROR, Message: common_err.GetMsg(common_err.FORMAT_ERROR)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
service.MyService.Disk().MountDisk(path, volume)
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
delete(diskMap, path)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary remove mount point
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param path formData string true "e.g. /dev/sda1"
|
|
||||||
// @Param mount_point formData string true "e.g. /mnt/volume1"
|
|
||||||
// @Param pwd formData string true "user password"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/umount [post]
|
|
||||||
func PostDiskUmount(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
js := make(map[string]string)
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
|
|
||||||
path := js["path"]
|
|
||||||
mountPoint := js["volume"]
|
|
||||||
pwd := js["password"]
|
|
||||||
|
|
||||||
if len(path) == 0 || len(mountPoint) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user := service.MyService.User().GetUserAllInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if encryption.GetMD5ByStr(pwd) != user.Password {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if _, ok := diskMap[path]; ok {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.DISK_BUSYING, Message: common_err.GetMsg(common_err.DISK_BUSYING)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
service.MyService.Disk().UmountPointAndRemoveDir(path)
|
|
||||||
//delete data
|
|
||||||
service.MyService.Disk().DeleteMountPoint(path, mountPoint)
|
|
||||||
service.MyService.Disk().RemoveLSBLKCache()
|
|
||||||
|
|
||||||
//send notify to client
|
|
||||||
msg := notify.StorageMessage{}
|
|
||||||
msg.Action = "REMOVED"
|
|
||||||
msg.Path = path
|
|
||||||
msg.Volume = mountPoint
|
|
||||||
msg.Size = 0
|
|
||||||
msg.Type = ""
|
|
||||||
service.MyService.Notify().SendStorageBySocket(msg)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary confirm delete disk
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Param id path string true "id"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/remove/{id} [delete]
|
|
||||||
func DeleteDisk(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
service.MyService.Disk().DeleteMount(id)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary check mount point
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags disk
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /disk/init [get]
|
|
||||||
func GetDiskCheck(c *gin.Context) {
|
|
||||||
|
|
||||||
dbList := service.MyService.Disk().GetSerialAll()
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
|
|
||||||
mapList := make(map[string]string)
|
|
||||||
|
|
||||||
for _, v := range list {
|
|
||||||
mapList[v.Serial] = "1"
|
|
||||||
}
|
|
||||||
|
|
||||||
for _, v := range dbList {
|
|
||||||
if _, ok := mapList[v.UUID]; !ok {
|
|
||||||
//disk undefind
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "disk undefind"})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
@@ -38,7 +38,7 @@ var upgrader = websocket.Upgrader{
|
|||||||
HandshakeTimeout: time.Duration(time.Second * 5),
|
HandshakeTimeout: time.Duration(time.Second * 5),
|
||||||
}
|
}
|
||||||
|
|
||||||
//打开docker的terminal
|
// 打开docker的terminal
|
||||||
func DockerTerminal(c *gin.Context) {
|
func DockerTerminal(c *gin.Context) {
|
||||||
col := c.DefaultQuery("cols", "100")
|
col := c.DefaultQuery("cols", "100")
|
||||||
row := c.DefaultQuery("rows", "30")
|
row := c.DefaultQuery("rows", "30")
|
||||||
@@ -761,7 +761,7 @@ func ChangAppState(c *gin.Context) {
|
|||||||
func ContainerLog(c *gin.Context) {
|
func ContainerLog(c *gin.Context) {
|
||||||
appId := c.Param("id")
|
appId := c.Param("id")
|
||||||
log, _ := service.MyService.Docker().DockerContainerLog(appId)
|
log, _ := service.MyService.Docker().DockerContainerLog(appId)
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: log})
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(log)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary 获取容器状态
|
// @Summary 获取容器状态
|
||||||
@@ -877,7 +877,7 @@ func UpdateSetting(c *gin.Context) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
service.MyService.Docker().DockerContainerUpdateName(m.ContainerName, id)
|
service.MyService.Docker().DockerContainerUpdateName(m.ContainerName, id)
|
||||||
service.MyService.Docker().DockerContainerStart(id)
|
service.MyService.Docker().DockerContainerStart(id)
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
// echo -e "hellow\nworld" >>
|
// echo -e "hellow\nworld" >>
|
||||||
@@ -1120,13 +1120,13 @@ func ContainerUpdateInfo(c *gin.Context) {
|
|||||||
showENV := info.Config.Labels["show_env"]
|
showENV := info.Config.Labels["show_env"]
|
||||||
showENVList := strings.Split(showENV, ",")
|
showENVList := strings.Split(showENV, ",")
|
||||||
showENVMap := make(map[string]string)
|
showENVMap := make(map[string]string)
|
||||||
if len(showENVList) > 0 {
|
if len(showENVList) > 0 && showENVList[0] != "" {
|
||||||
for _, name := range showENVList {
|
for _, name := range showENVList {
|
||||||
showENVMap[name] = "1"
|
showENVMap[name] = "1"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, v := range info.Config.Env {
|
for _, v := range info.Config.Env {
|
||||||
if len(showENVList) > 0 {
|
if len(showENVList) > 0 && info.Config.Labels["origin"] != "local" {
|
||||||
if _, ok := showENVMap[strings.Split(v, "=")[0]]; ok {
|
if _, ok := showENVMap[strings.Split(v, "=")[0]]; ok {
|
||||||
temp := model.Env{
|
temp := model.Env{
|
||||||
Name: strings.Split(v, "=")[0],
|
Name: strings.Split(v, "=")[0],
|
||||||
|
|||||||
147
route/v1/file.go
@@ -16,12 +16,13 @@ import (
|
|||||||
"sync"
|
"sync"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
uuid "github.com/satori/go.uuid"
|
uuid "github.com/satori/go.uuid"
|
||||||
|
"go.uber.org/zap"
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary 读取文件
|
// @Summary 读取文件
|
||||||
@@ -48,7 +49,7 @@ func GetFilerContent(c *gin.Context) {
|
|||||||
})
|
})
|
||||||
return
|
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{
|
c.JSON(common_err.SERVICE_ERROR, model.Result{
|
||||||
@@ -84,7 +85,6 @@ func GetLocalFile(c *gin.Context) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.File(path)
|
c.File(path)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary download
|
// @Summary download
|
||||||
@@ -97,7 +97,6 @@ func GetLocalFile(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/download [get]
|
// @Router /file/download [get]
|
||||||
func GetDownloadFile(c *gin.Context) {
|
func GetDownloadFile(c *gin.Context) {
|
||||||
|
|
||||||
t := c.Query("format")
|
t := c.Query("format")
|
||||||
|
|
||||||
files := c.Query("files")
|
files := c.Query("files")
|
||||||
@@ -136,11 +135,11 @@ func GetDownloadFile(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
if !info.IsDir() {
|
if !info.IsDir() {
|
||||||
|
|
||||||
//打开文件
|
// 打开文件
|
||||||
fileTmp, _ := os.Open(filePath)
|
fileTmp, _ := os.Open(filePath)
|
||||||
defer fileTmp.Close()
|
defer fileTmp.Close()
|
||||||
|
|
||||||
//获取文件的名称
|
// 获取文件的名称
|
||||||
fileName := path.Base(filePath)
|
fileName := path.Base(filePath)
|
||||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
||||||
c.File(filePath)
|
c.File(filePath)
|
||||||
@@ -180,7 +179,6 @@ func GetDownloadFile(c *gin.Context) {
|
|||||||
log.Printf("Failed to archive %s: %v", fname, err)
|
log.Printf("Failed to archive %s: %v", fname, err)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDownloadSingleFile(c *gin.Context) {
|
func GetDownloadSingleFile(c *gin.Context) {
|
||||||
@@ -203,7 +201,7 @@ func GetDownloadSingleFile(c *gin.Context) {
|
|||||||
defer fileTmp.Close()
|
defer fileTmp.Close()
|
||||||
|
|
||||||
fileName := path.Base(filePath)
|
fileName := path.Base(filePath)
|
||||||
//c.Header("Content-Disposition", "inline")
|
// c.Header("Content-Disposition", "inline")
|
||||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
||||||
c.File(filePath)
|
c.File(filePath)
|
||||||
}
|
}
|
||||||
@@ -236,33 +234,8 @@ func DirPath(c *gin.Context) {
|
|||||||
info[i].Type = "application"
|
info[i].Type = "application"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else if path == "/DATA" {
|
|
||||||
disk := make(map[string]string)
|
|
||||||
lsblk := service.MyService.Disk().LSBLK(true)
|
|
||||||
for _, v := range lsblk {
|
|
||||||
if len(v.Children) > 0 {
|
|
||||||
t := v.Tran
|
|
||||||
for _, c := range v.Children {
|
|
||||||
if len(c.Children) > 0 {
|
|
||||||
for _, gc := range c.Children {
|
|
||||||
if len(gc.MountPoint) > 0 {
|
|
||||||
disk[gc.MountPoint] = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(c.MountPoint) > 0 {
|
|
||||||
disk[c.MountPoint] = t
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
for i := 0; i < len(info); i++ {
|
|
||||||
if v, ok := disk[info[i].Path]; ok {
|
|
||||||
info[i].Type = v
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
for i := 0; i < len(info); i++ {
|
for i := 0; i < len(info); i++ {
|
||||||
if v, ok := sharesMap[info[i].Path]; ok {
|
if v, ok := sharesMap[info[i].Path]; ok {
|
||||||
ex := make(map[string]interface{})
|
ex := make(map[string]interface{})
|
||||||
@@ -274,7 +247,7 @@ func DirPath(c *gin.Context) {
|
|||||||
info[i].Extensions = ex
|
info[i].Extensions = ex
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
//Hide the files or folders in operation
|
// Hide the files or folders in operation
|
||||||
fileQueue := make(map[string]string)
|
fileQueue := make(map[string]string)
|
||||||
if len(service.OpStrArr) > 0 {
|
if len(service.OpStrArr) > 0 {
|
||||||
for _, v := range service.OpStrArr {
|
for _, v := range service.OpStrArr {
|
||||||
@@ -292,6 +265,9 @@ func DirPath(c *gin.Context) {
|
|||||||
|
|
||||||
pathList := []model.Path{}
|
pathList := []model.Path{}
|
||||||
for i := 0; i < len(info); i++ {
|
for i := 0; i < len(info); i++ {
|
||||||
|
if info[i].Name == ".temp" && info[i].IsDir {
|
||||||
|
continue
|
||||||
|
}
|
||||||
if _, ok := fileQueue[info[i].Path]; !ok {
|
if _, ok := fileQueue[info[i].Path]; !ok {
|
||||||
pathList = append(pathList, info[i])
|
pathList = append(pathList, info[i])
|
||||||
}
|
}
|
||||||
@@ -384,7 +360,6 @@ func PostCreateFile(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/upload [get]
|
// @Router /file/upload [get]
|
||||||
func GetFileUpload(c *gin.Context) {
|
func GetFileUpload(c *gin.Context) {
|
||||||
|
|
||||||
relative := c.Query("relativePath")
|
relative := c.Query("relativePath")
|
||||||
fileName := c.Query("filename")
|
fileName := c.Query("filename")
|
||||||
chunkNumber := c.Query("chunkNumber")
|
chunkNumber := c.Query("chunkNumber")
|
||||||
@@ -392,7 +367,7 @@ func GetFileUpload(c *gin.Context) {
|
|||||||
path := c.Query("path")
|
path := c.Query("path")
|
||||||
dirPath := ""
|
dirPath := ""
|
||||||
hash := file.GetHashByContent([]byte(fileName))
|
hash := file.GetHashByContent([]byte(fileName))
|
||||||
tempDir := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/"
|
tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
|
||||||
if fileName != relative {
|
if fileName != relative {
|
||||||
dirPath = strings.TrimSuffix(relative, fileName)
|
dirPath = strings.TrimSuffix(relative, fileName)
|
||||||
tempDir += dirPath
|
tempDir += dirPath
|
||||||
@@ -428,55 +403,92 @@ func PostFileUpload(c *gin.Context) {
|
|||||||
hash := file.GetHashByContent([]byte(fileName))
|
hash := file.GetHashByContent([]byte(fileName))
|
||||||
|
|
||||||
if len(path) == 0 {
|
if len(path) == 0 {
|
||||||
c.JSON(common_err.INVALID_PARAMS, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
loger.Error("path should not be empty")
|
||||||
|
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
tempDir := config.AppInfo.TempPath + "/" + hash + strconv.Itoa(totalChunks) + "/"
|
|
||||||
|
tempDir := filepath.Join(path, ".temp", hash+strconv.Itoa(totalChunks)) + "/"
|
||||||
|
|
||||||
if fileName != relative {
|
if fileName != relative {
|
||||||
dirPath = strings.TrimSuffix(relative, fileName)
|
dirPath = strings.TrimSuffix(relative, fileName)
|
||||||
tempDir += dirPath
|
tempDir += dirPath
|
||||||
file.MkDir(path + "/" + dirPath)
|
if err := file.MkDir(path + "/" + dirPath); err != nil {
|
||||||
|
loger.Error("error when trying to create `"+path+"/"+dirPath+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
path += "/" + relative
|
path += "/" + relative
|
||||||
|
|
||||||
if !file.CheckNotExist(tempDir + chunkNumber) {
|
if !file.CheckNotExist(tempDir + chunkNumber) {
|
||||||
file.RMDir(tempDir + chunkNumber)
|
if err := file.RMDir(tempDir + chunkNumber); err != nil {
|
||||||
|
loger.Error("error when trying to remove existing `"+tempDir+chunkNumber+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if totalChunks > 1 {
|
if totalChunks > 1 {
|
||||||
file.IsNotExistMkDir(tempDir)
|
if err := file.IsNotExistMkDir(tempDir); err != nil {
|
||||||
|
loger.Error("error when trying to create `"+tempDir+"`", zap.Error(err))
|
||||||
out, _ := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0644)
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
defer out.Close()
|
|
||||||
_, err := io.Copy(out, f)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
out, err := os.OpenFile(tempDir+chunkNumber, os.O_WRONLY|os.O_CREATE, 0o644)
|
||||||
|
if err != nil {
|
||||||
|
loger.Error("error when trying to open `"+tempDir+chunkNumber+"` for creation", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
defer out.Close()
|
||||||
|
|
||||||
|
if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
|
||||||
|
loger.Error("error when trying to write to `"+tempDir+chunkNumber+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
fileNum, err := ioutil.ReadDir(tempDir)
|
||||||
|
if err != nil {
|
||||||
|
loger.Error("error when trying to read number of files under `"+tempDir+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if totalChunks == len(fileNum) {
|
||||||
|
if err := file.SpliceFiles(tempDir, path, totalChunks, 1); err != nil {
|
||||||
|
loger.Error("error when trying to splice files under `"+tempDir+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := file.RMDir(tempDir); err != nil {
|
||||||
|
loger.Error("error when trying to remove `"+tempDir+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
out, _ := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0644)
|
out, err := os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o644)
|
||||||
defer out.Close()
|
|
||||||
_, err := io.Copy(out, f)
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
loger.Error("error when trying to open `"+path+"` for creation", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fileNum, err := ioutil.ReadDir(tempDir)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if totalChunks == len(fileNum) {
|
|
||||||
file.SpliceFiles(tempDir, path, totalChunks, 1)
|
|
||||||
file.RMDir(tempDir)
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
defer out.Close()
|
||||||
|
|
||||||
|
if _, err := io.Copy(out, f); err != nil { // recommend to use https://github.com/iceber/iouring-go for faster copy
|
||||||
|
loger.Error("error when trying to write to `"+path+"`", zap.Error(err))
|
||||||
|
c.JSON(http.StatusInternalServerError, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary copy or move file
|
// @Summary copy or move file
|
||||||
@@ -488,7 +500,6 @@ func PostFileUpload(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/operate [post]
|
// @Router /file/operate [post]
|
||||||
func PostOperateFileOrDir(c *gin.Context) {
|
func PostOperateFileOrDir(c *gin.Context) {
|
||||||
|
|
||||||
list := model.FileOperate{}
|
list := model.FileOperate{}
|
||||||
c.ShouldBind(&list)
|
c.ShouldBind(&list)
|
||||||
|
|
||||||
@@ -538,7 +549,6 @@ func PostOperateFileOrDir(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/delete [delete]
|
// @Router /file/delete [delete]
|
||||||
func DeleteFile(c *gin.Context) {
|
func DeleteFile(c *gin.Context) {
|
||||||
|
|
||||||
paths := []string{}
|
paths := []string{}
|
||||||
c.ShouldBind(&paths)
|
c.ShouldBind(&paths)
|
||||||
if len(paths) == 0 {
|
if len(paths) == 0 {
|
||||||
@@ -570,7 +580,6 @@ func DeleteFile(c *gin.Context) {
|
|||||||
// @Success 200 {string} string "ok"
|
// @Success 200 {string} string "ok"
|
||||||
// @Router /file/update [put]
|
// @Router /file/update [put]
|
||||||
func PutFileContent(c *gin.Context) {
|
func PutFileContent(c *gin.Context) {
|
||||||
|
|
||||||
fi := model.FileUpdate{}
|
fi := model.FileUpdate{}
|
||||||
c.ShouldBind(&fi)
|
c.ShouldBind(&fi)
|
||||||
|
|
||||||
@@ -580,7 +589,7 @@ func PutFileContent(c *gin.Context) {
|
|||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_ALREADY_EXISTS, Message: common_err.GetMsg(common_err.FILE_ALREADY_EXISTS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
//err := os.Remove(path)
|
// err := os.Remove(path)
|
||||||
err := os.RemoveAll(fi.FilePath)
|
err := os.RemoveAll(fi.FilePath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DELETE_ERROR, Message: common_err.GetMsg(common_err.FILE_DELETE_ERROR), Data: err})
|
||||||
|
|||||||
23
route/v1/notiry.go
Normal file
@@ -0,0 +1,23 @@
|
|||||||
|
package v1
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
"github.com/gin-gonic/gin"
|
||||||
|
)
|
||||||
|
|
||||||
|
func PostNotifyMessage(c *gin.Context) {
|
||||||
|
path := c.Param("path")
|
||||||
|
message := make(map[string]interface{})
|
||||||
|
c.ShouldBind(&message)
|
||||||
|
service.MyService.Notify().SendNotify(path, message)
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
func PostSystemStatusNotify(c *gin.Context) {
|
||||||
|
message := make(map[string]interface{})
|
||||||
|
c.ShouldBind(&message)
|
||||||
|
service.MyService.Notify().SettingSystemTempData(message)
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2022-07-26 11:08:48
|
* @Date: 2022-07-26 11:08:48
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-08-05 12:16:39
|
* @LastEditTime: 2022-08-17 18:25:42
|
||||||
* @FilePath: /CasaOS/route/v1/samba.go
|
* @FilePath: /CasaOS/route/v1/samba.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -85,6 +85,7 @@ func PostSambaSharesCreate(c *gin.Context) {
|
|||||||
shareDBModel.Anonymous = true
|
shareDBModel.Anonymous = true
|
||||||
shareDBModel.Path = v.Path
|
shareDBModel.Path = v.Path
|
||||||
shareDBModel.Name = filepath.Base(v.Path)
|
shareDBModel.Name = filepath.Base(v.Path)
|
||||||
|
os.Chmod(v.Path, 0777)
|
||||||
service.MyService.Shares().CreateShare(shareDBModel)
|
service.MyService.Shares().CreateShare(shareDBModel)
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -127,8 +128,8 @@ func PostSambaConnectionsCreate(c *gin.Context) {
|
|||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
connection.Host = strings.Split(connection.Host, "/")[0]
|
||||||
// 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)})
|
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)})
|
||||||
|
|||||||
@@ -1,104 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-07-11 16:02:29
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-08-11 14:20:02
|
|
||||||
* @FilePath: /CasaOS/route/v1/storage.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
func GetStorageList(c *gin.Context) {
|
|
||||||
system := c.Query("system")
|
|
||||||
storages := []model.Storages{}
|
|
||||||
disks := service.MyService.Disk().LSBLK(false)
|
|
||||||
diskNumber := 1
|
|
||||||
children := 1
|
|
||||||
findSystem := 0
|
|
||||||
for _, d := range disks {
|
|
||||||
if d.Tran != "usb" {
|
|
||||||
tempSystemDisk := false
|
|
||||||
children = 1
|
|
||||||
tempDisk := model.Storages{
|
|
||||||
DiskName: d.Model,
|
|
||||||
Path: d.Path,
|
|
||||||
Size: d.Size,
|
|
||||||
}
|
|
||||||
|
|
||||||
storageArr := []model.Storage{}
|
|
||||||
temp := service.MyService.Disk().SmartCTL(d.Path)
|
|
||||||
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
|
||||||
temp.SmartStatus.Passed = true
|
|
||||||
}
|
|
||||||
for _, v := range d.Children {
|
|
||||||
if v.MountPoint != "" {
|
|
||||||
if findSystem == 0 {
|
|
||||||
if v.MountPoint == "/" {
|
|
||||||
tempDisk.DiskName = "System"
|
|
||||||
findSystem = 1
|
|
||||||
tempSystemDisk = true
|
|
||||||
}
|
|
||||||
if len(v.Children) > 0 {
|
|
||||||
for _, c := range v.Children {
|
|
||||||
if c.MountPoint == "/" {
|
|
||||||
tempDisk.DiskName = "System"
|
|
||||||
findSystem = 1
|
|
||||||
tempSystemDisk = true
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
stor := model.Storage{}
|
|
||||||
stor.MountPoint = v.MountPoint
|
|
||||||
stor.Size = v.FSSize
|
|
||||||
stor.Avail = v.FSAvail
|
|
||||||
stor.Path = v.Path
|
|
||||||
stor.Type = v.FsType
|
|
||||||
stor.DriveName = v.Name
|
|
||||||
if len(v.Label) == 0 {
|
|
||||||
stor.Label = "Storage" + strconv.Itoa(diskNumber) + "_" + strconv.Itoa(children)
|
|
||||||
children += 1
|
|
||||||
} else {
|
|
||||||
stor.Label = v.Label
|
|
||||||
}
|
|
||||||
storageArr = append(storageArr, stor)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(storageArr) > 0 {
|
|
||||||
if tempSystemDisk && len(system) > 0 {
|
|
||||||
tempStorageArr := []model.Storage{}
|
|
||||||
for i := 0; i < len(storageArr); i++ {
|
|
||||||
if storageArr[i].MountPoint != "/boot/efi" && storageArr[i].Type != "swap" {
|
|
||||||
tempStorageArr = append(tempStorageArr, storageArr[i])
|
|
||||||
}
|
|
||||||
}
|
|
||||||
tempDisk.Children = tempStorageArr
|
|
||||||
storages = append(storages, tempDisk)
|
|
||||||
diskNumber += 1
|
|
||||||
} else if !tempSystemDisk {
|
|
||||||
tempDisk.Children = storageArr
|
|
||||||
storages = append(storages, tempDisk)
|
|
||||||
diskNumber += 1
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: storages})
|
|
||||||
}
|
|
||||||
@@ -1,10 +1,12 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"bytes"
|
||||||
"fmt"
|
"fmt"
|
||||||
|
"io"
|
||||||
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"reflect"
|
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
@@ -13,14 +15,12 @@ import (
|
|||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
|
||||||
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
port2 "github.com/IceWhaleTech/CasaOS/pkg/utils/port"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/version"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/version"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/IceWhaleTech/CasaOS/types"
|
"github.com/IceWhaleTech/CasaOS/types"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
// @Summary check version
|
// @Summary check version
|
||||||
@@ -76,7 +76,7 @@ func GetCasaOSErrorLogs(c *gin.Context) {
|
|||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: service.MyService.System().GetCasaOSLogs(line)})
|
||||||
}
|
}
|
||||||
|
|
||||||
//系统配置
|
// 系统配置
|
||||||
func GetSystemConfigDebug(c *gin.Context) {
|
func GetSystemConfigDebug(c *gin.Context) {
|
||||||
array := service.MyService.System().GetSystemConfigDebug()
|
array := service.MyService.System().GetSystemConfigDebug()
|
||||||
disk := service.MyService.System().GetDiskInfo()
|
disk := service.MyService.System().GetDiskInfo()
|
||||||
@@ -182,31 +182,6 @@ func PutSystemUSBAutoMount(c *gin.Context) {
|
|||||||
service.MyService.System().UpdateUSBAutoMount("False")
|
service.MyService.System().UpdateUSBAutoMount("False")
|
||||||
service.MyService.System().ExecUSBAutoMountShell("False")
|
service.MyService.System().ExecUSBAutoMountShell("False")
|
||||||
}
|
}
|
||||||
go func() {
|
|
||||||
usbList := service.MyService.Disk().LSBLK(false)
|
|
||||||
usb := []model.DriveUSB{}
|
|
||||||
for _, v := range usbList {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
isMount := false
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Name
|
|
||||||
temp.Size = v.Size
|
|
||||||
for _, child := range v.Children {
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
isMount = true
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
temp.Avail += avail
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isMount {
|
|
||||||
usb = append(usb, temp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
service.MyService.Notify().SendUSBInfoBySocket(usb)
|
|
||||||
}()
|
|
||||||
c.JSON(common_err.SUCCESS,
|
c.JSON(common_err.SUCCESS,
|
||||||
model.Result{
|
model.Result{
|
||||||
Success: common_err.SUCCESS,
|
Success: common_err.SUCCESS,
|
||||||
@@ -226,31 +201,6 @@ func GetSystemUSBAutoMount(c *gin.Context) {
|
|||||||
if config.ServerInfo.USBAutoMount == "False" {
|
if config.ServerInfo.USBAutoMount == "False" {
|
||||||
state = "False"
|
state = "False"
|
||||||
}
|
}
|
||||||
go func() {
|
|
||||||
usbList := service.MyService.Disk().LSBLK(false)
|
|
||||||
usb := []model.DriveUSB{}
|
|
||||||
for _, v := range usbList {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
isMount := false
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Name
|
|
||||||
temp.Size = v.Size
|
|
||||||
for _, child := range v.Children {
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
isMount = true
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
temp.Avail += avail
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if isMount {
|
|
||||||
usb = append(usb, temp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
service.MyService.Notify().SendUSBInfoBySocket(usb)
|
|
||||||
}()
|
|
||||||
c.JSON(common_err.SUCCESS,
|
c.JSON(common_err.SUCCESS,
|
||||||
model.Result{
|
model.Result{
|
||||||
Success: common_err.SUCCESS,
|
Success: common_err.SUCCESS,
|
||||||
@@ -321,103 +271,14 @@ func GetSystemHardwareInfo(c *gin.Context) {
|
|||||||
// @Router /sys/utilization [get]
|
// @Router /sys/utilization [get]
|
||||||
func GetSystemUtilization(c *gin.Context) {
|
func GetSystemUtilization(c *gin.Context) {
|
||||||
var data = make(map[string]interface{}, 6)
|
var data = make(map[string]interface{}, 6)
|
||||||
|
|
||||||
list := service.MyService.Disk().LSBLK(true)
|
|
||||||
|
|
||||||
summary := model.Summary{}
|
|
||||||
healthy := true
|
|
||||||
findSystem := 0
|
|
||||||
|
|
||||||
for i := 0; i < len(list); i++ {
|
|
||||||
if len(list[i].Children) > 0 && findSystem == 0 {
|
|
||||||
|
|
||||||
for j := 0; j < len(list[i].Children); j++ {
|
|
||||||
|
|
||||||
if len(list[i].Children[j].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children[j].Children {
|
|
||||||
if v.MountPoint == "/" {
|
|
||||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
|
||||||
loger.Info("disk info", zap.Any("/ total:", s))
|
|
||||||
loger.Info("disk path", zap.Any("path", v.Path))
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if list[i].Children[j].MountPoint == "/" {
|
|
||||||
s, _ := strconv.ParseUint(list[i].Children[j].FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(list[i].Children[j].FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(list[i].Children[j].FSUsed, 10, 64)
|
|
||||||
loger.Info("disk info", zap.Any("/ total:", s))
|
|
||||||
loger.Info("disk path", zap.Any("path", list[i].Path))
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
findSystem = 1
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
if findSystem == 1 {
|
|
||||||
findSystem += 1
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
if list[i].Tran == "sata" || list[i].Tran == "nvme" || list[i].Tran == "spi" || list[i].Tran == "sas" || strings.Contains(list[i].SubSystems, "virtio") || (list[i].Tran == "ata" && list[i].Type == "disk") {
|
|
||||||
temp := service.MyService.Disk().SmartCTL(list[i].Path)
|
|
||||||
if reflect.DeepEqual(temp, model.SmartctlA{}) {
|
|
||||||
healthy = true
|
|
||||||
} else {
|
|
||||||
healthy = temp.SmartStatus.Passed
|
|
||||||
}
|
|
||||||
if len(list[i].Children) > 0 {
|
|
||||||
for _, v := range list[i].Children {
|
|
||||||
s, _ := strconv.ParseUint(v.FSSize, 10, 64)
|
|
||||||
a, _ := strconv.ParseUint(v.FSAvail, 10, 64)
|
|
||||||
u, _ := strconv.ParseUint(v.FSUsed, 10, 64)
|
|
||||||
loger.Info("disk info", zap.Any("/ total:", s))
|
|
||||||
loger.Info("disk path", zap.Any("path", list[i].Path))
|
|
||||||
summary.Size += s
|
|
||||||
summary.Avail += a
|
|
||||||
summary.Used += u
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
summary.Health = healthy
|
|
||||||
data["disk"] = summary
|
|
||||||
usbList := service.MyService.Disk().LSBLK(false)
|
|
||||||
usb := []model.DriveUSB{}
|
|
||||||
for _, v := range usbList {
|
|
||||||
if v.Tran == "usb" {
|
|
||||||
temp := model.DriveUSB{}
|
|
||||||
temp.Model = v.Model
|
|
||||||
temp.Name = v.Name
|
|
||||||
temp.Size = v.Size
|
|
||||||
|
|
||||||
for _, child := range v.Children {
|
|
||||||
if len(child.MountPoint) > 0 {
|
|
||||||
avail, _ := strconv.ParseUint(child.FSAvail, 10, 64)
|
|
||||||
temp.Avail += avail
|
|
||||||
}
|
|
||||||
}
|
|
||||||
usb = append(usb, temp)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
data["usb"] = usb
|
|
||||||
cpu := service.MyService.System().GetCpuPercent()
|
cpu := service.MyService.System().GetCpuPercent()
|
||||||
num := service.MyService.System().GetCpuCoreNum()
|
num := service.MyService.System().GetCpuCoreNum()
|
||||||
cpuData := make(map[string]interface{})
|
cpuData := make(map[string]interface{})
|
||||||
cpuData["percent"] = cpu
|
cpuData["percent"] = cpu
|
||||||
cpuData["num"] = num
|
cpuData["num"] = num
|
||||||
|
cpuData["temperature"] = service.MyService.System().GetCPUTemperature()
|
||||||
|
cpuData["power"] = service.MyService.System().GetCPUPower()
|
||||||
|
|
||||||
data["cpu"] = cpuData
|
data["cpu"] = cpuData
|
||||||
data["mem"] = service.MyService.System().GetMemInfo()
|
data["mem"] = service.MyService.System().GetMemInfo()
|
||||||
|
|
||||||
@@ -525,3 +386,21 @@ func GetSystemNetInfo(c *gin.Context) {
|
|||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: newNet})
|
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: newNet})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func GetSystemProxy(c *gin.Context) {
|
||||||
|
url := c.Query("url")
|
||||||
|
resp, err := http.Get(url)
|
||||||
|
if err != nil {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
defer resp.Body.Close()
|
||||||
|
for k, v := range c.Request.Header {
|
||||||
|
c.Header(k, v[0])
|
||||||
|
}
|
||||||
|
rda, _ := ioutil.ReadAll(resp.Body)
|
||||||
|
// json.NewEncoder(c.Writer).Encode(json.RawMessage(string(rda)))
|
||||||
|
// 响应状态码
|
||||||
|
c.Writer.WriteHeader(resp.StatusCode)
|
||||||
|
// 复制转发的响应Body到响应Body
|
||||||
|
io.Copy(c.Writer, ioutil.NopCloser(bytes.NewBuffer(rda)))
|
||||||
|
}
|
||||||
|
|||||||
683
route/v1/user.go
@@ -1,683 +0,0 @@
|
|||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
json2 "encoding/json"
|
|
||||||
"io/ioutil"
|
|
||||||
"net/http"
|
|
||||||
url2 "net/url"
|
|
||||||
"os"
|
|
||||||
"path"
|
|
||||||
"path/filepath"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model/system_model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/encryption"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/jwt"
|
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
|
||||||
uuid "github.com/satori/go.uuid"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
// @Summary register user
|
|
||||||
// @Router /user/register/ [post]
|
|
||||||
func PostUserRegister(c *gin.Context) {
|
|
||||||
json := make(map[string]string)
|
|
||||||
c.ShouldBind(&json)
|
|
||||||
|
|
||||||
username := json["username"]
|
|
||||||
pwd := json["password"]
|
|
||||||
key := json["key"]
|
|
||||||
if _, ok := service.UserRegisterHash[key]; !ok {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR,
|
|
||||||
model.Result{Success: common_err.KEY_NOT_EXIST, Message: common_err.GetMsg(common_err.KEY_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(username) == 0 || len(pwd) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR,
|
|
||||||
model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(pwd) < 6 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR,
|
|
||||||
model.Result{Success: common_err.PWD_IS_TOO_SIMPLE, Message: common_err.GetMsg(common_err.PWD_IS_TOO_SIMPLE)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
oldUser := service.MyService.User().GetUserInfoByUserName(username)
|
|
||||||
if oldUser.Id > 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR,
|
|
||||||
model.Result{Success: common_err.USER_EXIST, Message: common_err.GetMsg(common_err.USER_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user := model2.UserDBModel{}
|
|
||||||
user.Username = username
|
|
||||||
user.Password = encryption.GetMD5ByStr(pwd)
|
|
||||||
user.Role = "admin"
|
|
||||||
|
|
||||||
user = service.MyService.User().CreateUser(user)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
file.MkDir(config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id))
|
|
||||||
delete(service.UserRegisterHash, key)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary login
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags user
|
|
||||||
// @Param user_name query string true "User name"
|
|
||||||
// @Param pwd query string true "password"
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /user/login [post]
|
|
||||||
func PostUserLogin(c *gin.Context) {
|
|
||||||
json := make(map[string]string)
|
|
||||||
c.ShouldBind(&json)
|
|
||||||
|
|
||||||
username := json["username"]
|
|
||||||
|
|
||||||
password := json["password"]
|
|
||||||
//check params is empty
|
|
||||||
if len(username) == 0 || len(password) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR,
|
|
||||||
model.Result{
|
|
||||||
Success: common_err.CLIENT_ERROR,
|
|
||||||
Message: common_err.GetMsg(common_err.INVALID_PARAMS),
|
|
||||||
})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user := service.MyService.User().GetUserAllInfoByName(username)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR,
|
|
||||||
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if user.Password != encryption.GetMD5ByStr(password) {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR,
|
|
||||||
model.Result{Success: common_err.PWD_INVALID, Message: common_err.GetMsg(common_err.PWD_INVALID)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
token := system_model.VerifyInformation{}
|
|
||||||
token.AccessToken = jwt.GetAccessToken(user.Username, user.Password, user.Id)
|
|
||||||
token.RefreshToken = jwt.GetRefreshToken(user.Username, user.Password, user.Id)
|
|
||||||
token.ExpiresAt = time.Now().Add(3 * time.Hour * time.Duration(1)).Unix()
|
|
||||||
data := make(map[string]interface{}, 2)
|
|
||||||
user.Password = ""
|
|
||||||
data["token"] = token
|
|
||||||
|
|
||||||
// TODO:1 Database fields cannot be external
|
|
||||||
data["user"] = user
|
|
||||||
|
|
||||||
c.JSON(common_err.SUCCESS,
|
|
||||||
model.Result{
|
|
||||||
Success: common_err.SUCCESS,
|
|
||||||
Message: common_err.GetMsg(common_err.SUCCESS),
|
|
||||||
Data: data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary edit user head
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags user
|
|
||||||
// @Param file formData file true "用户头像"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /user/avatar [put]
|
|
||||||
func PutUserAvatar(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
user := service.MyService.User().GetUserInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR,
|
|
||||||
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
f, err := c.FormFile("file")
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR,
|
|
||||||
model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(user.Avatar) > 0 {
|
|
||||||
os.RemoveAll(config.AppInfo.UserDataPath + "/" + id + "/" + user.Avatar)
|
|
||||||
}
|
|
||||||
ext := filepath.Ext(f.Filename)
|
|
||||||
avatarPath := config.AppInfo.UserDataPath + "/" + id + "/avatar" + ext
|
|
||||||
c.SaveUploadedFile(f, avatarPath)
|
|
||||||
user.Avatar = avatarPath
|
|
||||||
service.MyService.User().UpdateUser(user)
|
|
||||||
c.JSON(http.StatusOK,
|
|
||||||
model.Result{
|
|
||||||
Success: common_err.SUCCESS,
|
|
||||||
Message: common_err.GetMsg(common_err.SUCCESS),
|
|
||||||
Data: user,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary edit user name
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags user
|
|
||||||
// @Param old_name query string true "Old user name"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /user/name/:id [put]
|
|
||||||
func PutUserInfo(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
json := model2.UserDBModel{}
|
|
||||||
c.ShouldBind(&json)
|
|
||||||
user := service.MyService.User().GetUserInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR,
|
|
||||||
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if len(json.Username) > 0 {
|
|
||||||
u := service.MyService.User().GetUserInfoByUserName(json.Username)
|
|
||||||
if u.Id > 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR,
|
|
||||||
model.Result{Success: common_err.USER_EXIST, Message: common_err.GetMsg(common_err.USER_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(json.Email) == 0 {
|
|
||||||
json.Email = user.Email
|
|
||||||
}
|
|
||||||
if len(json.Avatar) == 0 {
|
|
||||||
json.Avatar = user.Avatar
|
|
||||||
}
|
|
||||||
if len(json.Role) == 0 {
|
|
||||||
json.Role = user.Role
|
|
||||||
}
|
|
||||||
if len(json.Description) == 0 {
|
|
||||||
json.Description = user.Description
|
|
||||||
}
|
|
||||||
if len(json.Nickname) == 0 {
|
|
||||||
json.Nickname = user.Nickname
|
|
||||||
}
|
|
||||||
service.MyService.User().UpdateUser(json)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary edit user password
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags user
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /user/password/:id [put]
|
|
||||||
func PutUserPassword(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
json := make(map[string]string)
|
|
||||||
c.ShouldBind(&json)
|
|
||||||
oldPwd := json["old_password"]
|
|
||||||
pwd := json["password"]
|
|
||||||
if len(oldPwd) == 0 || len(pwd) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user := service.MyService.User().GetUserAllInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR,
|
|
||||||
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if user.Password != encryption.GetMD5ByStr(oldPwd) {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.PWD_INVALID_OLD, Message: common_err.GetMsg(common_err.PWD_INVALID_OLD)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user.Password = encryption.GetMD5ByStr(pwd)
|
|
||||||
service.MyService.User().UpdateUserPassword(user)
|
|
||||||
user.Password = ""
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary edit user nick
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags user
|
|
||||||
// @Param nick_name query string false "nick name"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /user/nick [put]
|
|
||||||
func PutUserNick(c *gin.Context) {
|
|
||||||
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
json := make(map[string]string)
|
|
||||||
c.ShouldBind(&json)
|
|
||||||
Nickname := json["nick_name"]
|
|
||||||
if len(Nickname) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user := service.MyService.User().GetUserInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(http.StatusOK,
|
|
||||||
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user.Nickname = Nickname
|
|
||||||
service.MyService.User().UpdateUser(user)
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary edit user description
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept multipart/form-data
|
|
||||||
// @Tags user
|
|
||||||
// @Param description formData string false "Description"
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /user/desc [put]
|
|
||||||
func PutUserDesc(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
json := make(map[string]string)
|
|
||||||
c.ShouldBind(&json)
|
|
||||||
desc := json["description"]
|
|
||||||
if len(desc) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user := service.MyService.User().GetUserInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(http.StatusOK,
|
|
||||||
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user.Description = desc
|
|
||||||
|
|
||||||
service.MyService.User().UpdateUser(user)
|
|
||||||
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: user})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary get user info
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags user
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /user/info/:id [get]
|
|
||||||
func GetUserInfo(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
user := service.MyService.User().GetUserInfoById(id)
|
|
||||||
|
|
||||||
c.JSON(common_err.SUCCESS,
|
|
||||||
model.Result{
|
|
||||||
Success: common_err.SUCCESS,
|
|
||||||
Message: common_err.GetMsg(common_err.SUCCESS),
|
|
||||||
Data: user,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description:
|
|
||||||
* @param {*gin.Context} c
|
|
||||||
* @param {string} Username
|
|
||||||
* @return {*}
|
|
||||||
* @method:
|
|
||||||
* @router:
|
|
||||||
*/
|
|
||||||
func GetUserInfoByUsername(c *gin.Context) {
|
|
||||||
username := c.Param("username")
|
|
||||||
if len(username) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user := service.MyService.User().GetUserInfoByUserName(username)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
c.JSON(common_err.SUCCESS,
|
|
||||||
model.Result{
|
|
||||||
Success: common_err.SUCCESS,
|
|
||||||
Message: common_err.GetMsg(common_err.SUCCESS),
|
|
||||||
Data: user,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: get all Usernames
|
|
||||||
* @method:GET
|
|
||||||
* @router:/user/all/name
|
|
||||||
*/
|
|
||||||
func GetUserAllUsername(c *gin.Context) {
|
|
||||||
users := service.MyService.User().GetAllUserName()
|
|
||||||
names := []string{}
|
|
||||||
for _, v := range users {
|
|
||||||
names = append(names, v.Username)
|
|
||||||
}
|
|
||||||
c.JSON(common_err.SUCCESS,
|
|
||||||
model.Result{
|
|
||||||
Success: common_err.SUCCESS,
|
|
||||||
Message: common_err.GetMsg(common_err.SUCCESS),
|
|
||||||
Data: names,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description:get custom file by user
|
|
||||||
* @param {path} name string "file name"
|
|
||||||
* @method: GET
|
|
||||||
* @router: /user/custom/:key
|
|
||||||
*/
|
|
||||||
func GetUserCustomConf(c *gin.Context) {
|
|
||||||
name := c.Param("key")
|
|
||||||
if len(name) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
|
|
||||||
user := service.MyService.User().GetUserInfoById(id)
|
|
||||||
// user := service.MyService.User().GetUserInfoByUsername(Username)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR,
|
|
||||||
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
filePath := config.AppInfo.UserDataPath + "/" + id + "/" + name + ".json"
|
|
||||||
|
|
||||||
data := file.ReadFullFile(filePath)
|
|
||||||
if !gjson.ValidBytes(data) {
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: string(data)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description:create or update custom conf by user
|
|
||||||
* @param {path} name string "file name"
|
|
||||||
* @method:POST
|
|
||||||
* @router:/user/custom/:key
|
|
||||||
*/
|
|
||||||
func PostUserCustomConf(c *gin.Context) {
|
|
||||||
|
|
||||||
name := c.Param("key")
|
|
||||||
if len(name) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
user := service.MyService.User().GetUserInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR,
|
|
||||||
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
data, _ := ioutil.ReadAll(c.Request.Body)
|
|
||||||
filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id)
|
|
||||||
|
|
||||||
file.WriteToPath(data, filePath, name+".json")
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: json2.RawMessage(string(data))})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: delete user custom config
|
|
||||||
* @param {path} key string
|
|
||||||
* @method:delete
|
|
||||||
* @router:/user/custom/:key
|
|
||||||
*/
|
|
||||||
func DeleteUserCustomConf(c *gin.Context) {
|
|
||||||
name := c.Param("key")
|
|
||||||
if len(name) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
user := service.MyService.User().GetUserInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR,
|
|
||||||
model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + name + ".json"
|
|
||||||
err := os.Remove(filePath)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description:
|
|
||||||
* @param {path} id string "user id"
|
|
||||||
* @method:DELETE
|
|
||||||
* @router:/user/delete/:id
|
|
||||||
*/
|
|
||||||
func DeleteUser(c *gin.Context) {
|
|
||||||
id := c.Param("id")
|
|
||||||
service.MyService.User().DeleteUserById(id)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: id})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description:update user image
|
|
||||||
* @method:POST
|
|
||||||
* @router:/user/current/image/:key
|
|
||||||
*/
|
|
||||||
func PutUserImage(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
json := make(map[string]string)
|
|
||||||
c.ShouldBind(&json)
|
|
||||||
|
|
||||||
path := json["path"]
|
|
||||||
key := c.Param("key")
|
|
||||||
if len(path) == 0 || len(key) == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !file.Exists(path) {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err := file.GetImageExt(path)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.NOT_IMAGE, Message: common_err.GetMsg(common_err.NOT_IMAGE)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
user := service.MyService.User().GetUserInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
fstat, _ := os.Stat(path)
|
|
||||||
if fstat.Size() > 10<<20 {
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.IMAGE_TOO_LARGE, Message: common_err.GetMsg(common_err.IMAGE_TOO_LARGE)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ext := file.GetExt(path)
|
|
||||||
filePath := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + key + ext
|
|
||||||
file.CopySingleFile(path, filePath, "overwrite")
|
|
||||||
|
|
||||||
data := make(map[string]string, 3)
|
|
||||||
data["path"] = filePath
|
|
||||||
data["file_name"] = key + ext
|
|
||||||
data["online_path"] = "/v1/users/image?path=" + filePath
|
|
||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description:
|
|
||||||
* @param {*gin.Context} c
|
|
||||||
* @param {file} file
|
|
||||||
* @param {string} key
|
|
||||||
* @param {string} type:avatar,background
|
|
||||||
* @return {*}
|
|
||||||
* @method:
|
|
||||||
* @router:
|
|
||||||
*/
|
|
||||||
func PostUserUploadImage(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
f, err := c.FormFile("file")
|
|
||||||
key := c.Param("key")
|
|
||||||
t := c.PostForm("type")
|
|
||||||
if len(key) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
_, err = file.GetImageExtByName(f.Filename)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.NOT_IMAGE, Message: common_err.GetMsg(common_err.NOT_IMAGE)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
ext := filepath.Ext(f.Filename)
|
|
||||||
user := service.MyService.User().GetUserInfoById(id)
|
|
||||||
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if t == "avatar" {
|
|
||||||
key = "avatar"
|
|
||||||
}
|
|
||||||
path := config.AppInfo.UserDataPath + "/" + strconv.Itoa(user.Id) + "/" + key + ext
|
|
||||||
|
|
||||||
c.SaveUploadedFile(f, path)
|
|
||||||
data := make(map[string]string, 3)
|
|
||||||
data["path"] = path
|
|
||||||
data["file_name"] = key + ext
|
|
||||||
data["online_path"] = "/v1/users/image?path=" + path
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: data})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description: get current user's image
|
|
||||||
* @method:GET
|
|
||||||
* @router:/user/image/:id
|
|
||||||
*/
|
|
||||||
func GetUserImage(c *gin.Context) {
|
|
||||||
filePath := c.Query("path")
|
|
||||||
if len(filePath) == 0 {
|
|
||||||
c.JSON(http.StatusNotFound, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !file.Exists(filePath) {
|
|
||||||
c.JSON(http.StatusNotFound, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !strings.Contains(filePath, config.AppInfo.UserDataPath) {
|
|
||||||
c.JSON(http.StatusNotFound, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
fileTmp, _ := os.Open(filePath)
|
|
||||||
defer fileTmp.Close()
|
|
||||||
|
|
||||||
fileName := path.Base(filePath)
|
|
||||||
|
|
||||||
// @tiger - RESTful 规范下不应该返回文件本身内容,而是返回文件的静态URL,由前端去解析
|
|
||||||
c.Header("Content-Disposition", "attachment; filename*=utf-8''"+url2.PathEscape(fileName))
|
|
||||||
c.File(filePath)
|
|
||||||
}
|
|
||||||
func DeleteUserImage(c *gin.Context) {
|
|
||||||
id := c.GetHeader("user_id")
|
|
||||||
path := c.Query("path")
|
|
||||||
if len(path) == 0 {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
user := service.MyService.User().GetUserInfoById(id)
|
|
||||||
if user.Id == 0 {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.USER_NOT_EXIST, Message: common_err.GetMsg(common_err.USER_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !file.Exists(path) {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.FILE_DOES_NOT_EXIST, Message: common_err.GetMsg(common_err.FILE_DOES_NOT_EXIST)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !strings.Contains(path, config.AppInfo.UserDataPath+"/"+strconv.Itoa(user.Id)) {
|
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.INSUFFICIENT_PERMISSIONS, Message: common_err.GetMsg(common_err.INSUFFICIENT_PERMISSIONS)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
os.Remove(path)
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
|
||||||
* @description:
|
|
||||||
* @param {*gin.Context} c
|
|
||||||
* @param {string} refresh_token
|
|
||||||
* @return {*}
|
|
||||||
* @method:
|
|
||||||
* @router:
|
|
||||||
*/
|
|
||||||
func PostUserRefreshToken(c *gin.Context) {
|
|
||||||
js := make(map[string]string)
|
|
||||||
c.ShouldBind(&js)
|
|
||||||
refresh := js["refresh_token"]
|
|
||||||
claims, err := jwt.ParseToken(refresh, true)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.VERIFICATION_FAILURE, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if !claims.VerifyExpiresAt(time.Now(), true) || !claims.VerifyIssuer("refresh", true) {
|
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.VERIFICATION_FAILURE, Message: common_err.GetMsg(common_err.VERIFICATION_FAILURE)})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
newToken := jwt.GetAccessToken(claims.Username, claims.PassWord, claims.Id)
|
|
||||||
verifyInfo := system_model.VerifyInformation{}
|
|
||||||
verifyInfo.AccessToken = newToken
|
|
||||||
verifyInfo.RefreshToken = jwt.GetRefreshToken(claims.Username, claims.PassWord, claims.Id)
|
|
||||||
verifyInfo.ExpiresAt = time.Now().Add(3 * time.Hour * time.Duration(1)).Unix()
|
|
||||||
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: verifyInfo})
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteUserAll(c *gin.Context) {
|
|
||||||
service.MyService.User().DeleteAllUser()
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
|
||||||
}
|
|
||||||
|
|
||||||
// @Summary 检查是否进入引导状态
|
|
||||||
// @Produce application/json
|
|
||||||
// @Accept application/json
|
|
||||||
// @Tags sys
|
|
||||||
// @Security ApiKeyAuth
|
|
||||||
// @Success 200 {string} string "ok"
|
|
||||||
// @Router /sys/init/check [get]
|
|
||||||
func GetUserStatus(c *gin.Context) {
|
|
||||||
data := make(map[string]interface{}, 2)
|
|
||||||
|
|
||||||
if service.MyService.User().GetUserCount() > 0 {
|
|
||||||
data["initialized"] = true
|
|
||||||
data["key"] = ""
|
|
||||||
} else {
|
|
||||||
key := uuid.NewV4().String()
|
|
||||||
service.UserRegisterHash[key] = key
|
|
||||||
data["key"] = key
|
|
||||||
data["initialized"] = false
|
|
||||||
}
|
|
||||||
c.JSON(common_err.SUCCESS,
|
|
||||||
model.Result{
|
|
||||||
Success: common_err.SUCCESS,
|
|
||||||
Message: common_err.GetMsg(common_err.SUCCESS),
|
|
||||||
Data: data,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
@@ -439,7 +439,7 @@ func (a *appStruct) GetHardwareUsageStream() {
|
|||||||
wg.Add(1)
|
wg.Add(1)
|
||||||
go func(v types.Container, i int) {
|
go func(v types.Container, i int) {
|
||||||
defer wg.Done()
|
defer wg.Done()
|
||||||
stats, err := cli.ContainerStats(ctx, v.ID, true)
|
stats, err := cli.ContainerStatsOneShot(ctx, v.ID)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -130,10 +130,6 @@ func (o *casaService) AsyncGetServerList() (collection model.ServerAppListCollec
|
|||||||
errr := json2.Unmarshal(results, &collection)
|
errr := json2.Unmarshal(results, &collection)
|
||||||
if errr != nil {
|
if errr != nil {
|
||||||
loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
|
loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
|
||||||
} else {
|
|
||||||
if collection.Version == o.GetCasaosVersion().Version {
|
|
||||||
return collection, err
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
head := make(map[string]string)
|
head := make(map[string]string)
|
||||||
@@ -144,7 +140,7 @@ func (o *casaService) AsyncGetServerList() (collection model.ServerAppListCollec
|
|||||||
listModel := []model.ServerAppList{}
|
listModel := []model.ServerAppList{}
|
||||||
communityModel := []model.ServerAppList{}
|
communityModel := []model.ServerAppList{}
|
||||||
recommendModel := []model.ServerAppList{}
|
recommendModel := []model.ServerAppList{}
|
||||||
json2.Unmarshal([]byte(gjson.Get(listS, "data.list").String()), &listModel)
|
err = json2.Unmarshal([]byte(gjson.Get(listS, "data.list").String()), &listModel)
|
||||||
json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommendModel)
|
json2.Unmarshal([]byte(gjson.Get(listS, "data.recommend").String()), &recommendModel)
|
||||||
json2.Unmarshal([]byte(gjson.Get(listS, "data.community").String()), &communityModel)
|
json2.Unmarshal([]byte(gjson.Get(listS, "data.community").String()), &communityModel)
|
||||||
|
|
||||||
@@ -204,10 +200,6 @@ func (o *casaService) AsyncGetServerCategoryList() ([]model.CategoryList, error)
|
|||||||
err := json2.Unmarshal(results, &list)
|
err := json2.Unmarshal(results, &list)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
|
loger.Error("marshal error", zap.Any("err", err), zap.Any("content", string(results)))
|
||||||
} else {
|
|
||||||
if list.Version == o.GetCasaosVersion().Version {
|
|
||||||
return list.Item, nil
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
item := []model.CategoryList{}
|
item := []model.CategoryList{}
|
||||||
head := make(map[string]string)
|
head := make(map[string]string)
|
||||||
|
|||||||
285
service/disk.go
@@ -1,285 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
json2 "encoding/json"
|
|
||||||
"fmt"
|
|
||||||
"reflect"
|
|
||||||
"strconv"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/config"
|
|
||||||
command2 "github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/loger"
|
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
|
||||||
"github.com/shirou/gopsutil/v3/disk"
|
|
||||||
"github.com/tidwall/gjson"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type DiskService interface {
|
|
||||||
GetPlugInDisk() []string
|
|
||||||
LSBLK(isUseCache bool) []model.LSBLKModel
|
|
||||||
SmartCTL(path string) model.SmartctlA
|
|
||||||
FormatDisk(path, format string) []string
|
|
||||||
UmountPointAndRemoveDir(path string) []string
|
|
||||||
GetDiskInfo(path string) model.LSBLKModel
|
|
||||||
DelPartition(path, num string) string
|
|
||||||
AddPartition(path string) string
|
|
||||||
GetDiskInfoByPath(path string) *disk.UsageStat
|
|
||||||
MountDisk(path, volume string)
|
|
||||||
GetSerialAll() []model2.SerialDisk
|
|
||||||
SaveMountPoint(m model2.SerialDisk)
|
|
||||||
DeleteMountPoint(path, mountPoint string)
|
|
||||||
DeleteMount(id string)
|
|
||||||
UpdateMountPoint(m model2.SerialDisk)
|
|
||||||
RemoveLSBLKCache()
|
|
||||||
UmountUSB(path string)
|
|
||||||
}
|
|
||||||
type diskService struct {
|
|
||||||
db *gorm.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) RemoveLSBLKCache() {
|
|
||||||
key := "system_lsblk"
|
|
||||||
Cache.Delete(key)
|
|
||||||
}
|
|
||||||
func (d *diskService) UmountUSB(path string) {
|
|
||||||
r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;UDEVILUmount " + path)
|
|
||||||
fmt.Println(r)
|
|
||||||
}
|
|
||||||
func (d *diskService) SmartCTL(path string) model.SmartctlA {
|
|
||||||
|
|
||||||
key := "system_smart_" + path
|
|
||||||
if result, ok := Cache.Get(key); ok {
|
|
||||||
|
|
||||||
res, ok := result.(model.SmartctlA)
|
|
||||||
if ok {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
var m model.SmartctlA
|
|
||||||
str := command2.ExecSmartCTLByPath(path)
|
|
||||||
if str == nil {
|
|
||||||
loger.Error("failed to exec shell ", zap.Any("err", "smartctl exec error"))
|
|
||||||
Cache.Add(key, m, time.Minute*10)
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
err := json2.Unmarshal([]byte(str), &m)
|
|
||||||
if err != nil {
|
|
||||||
loger.Error("Failed to unmarshal json", zap.Any("err", err))
|
|
||||||
}
|
|
||||||
if !reflect.DeepEqual(m, model.SmartctlA{}) {
|
|
||||||
Cache.Add(key, m, time.Hour*24)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
//通过脚本获取外挂磁盘
|
|
||||||
func (d *diskService) GetPlugInDisk() []string {
|
|
||||||
return command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPlugInDisk")
|
|
||||||
}
|
|
||||||
|
|
||||||
//格式化硬盘
|
|
||||||
func (d *diskService) FormatDisk(path, format string) []string {
|
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;FormatDisk " + path + " " + format)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
//移除挂载点,删除目录
|
|
||||||
func (d *diskService) UmountPointAndRemoveDir(path string) []string {
|
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;UMountPorintAndRemoveDir " + path)
|
|
||||||
return r
|
|
||||||
}
|
|
||||||
|
|
||||||
//删除分区
|
|
||||||
func (d *diskService) DelPartition(path, num string) string {
|
|
||||||
r := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;DelPartition " + path + " " + num)
|
|
||||||
fmt.Println(r)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
//part
|
|
||||||
func (d *diskService) AddPartition(path string) string {
|
|
||||||
command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;AddPartition " + path)
|
|
||||||
return ""
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) AddAllPartition(path string) {
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取硬盘详情
|
|
||||||
func (d *diskService) GetDiskInfoByPath(path string) *disk.UsageStat {
|
|
||||||
diskInfo, err := disk.Usage(path + "1")
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
|
||||||
diskInfo.UsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.UsedPercent), 64)
|
|
||||||
diskInfo.InodesUsedPercent, _ = strconv.ParseFloat(fmt.Sprintf("%.1f", diskInfo.InodesUsedPercent), 64)
|
|
||||||
return diskInfo
|
|
||||||
}
|
|
||||||
|
|
||||||
//get disk details
|
|
||||||
func (d *diskService) LSBLK(isUseCache bool) []model.LSBLKModel {
|
|
||||||
key := "system_lsblk"
|
|
||||||
var n []model.LSBLKModel
|
|
||||||
|
|
||||||
if result, ok := Cache.Get(key); ok && isUseCache {
|
|
||||||
|
|
||||||
res, ok := result.([]model.LSBLKModel)
|
|
||||||
if ok {
|
|
||||||
return res
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
str := command2.ExecLSBLK()
|
|
||||||
if str == nil {
|
|
||||||
loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error"))
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
var m []model.LSBLKModel
|
|
||||||
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &m)
|
|
||||||
if err != nil {
|
|
||||||
loger.Error("Failed to unmarshal json", zap.Any("err", err))
|
|
||||||
}
|
|
||||||
|
|
||||||
var c []model.LSBLKModel
|
|
||||||
|
|
||||||
var fsused uint64
|
|
||||||
|
|
||||||
var health = true
|
|
||||||
for _, i := range m {
|
|
||||||
if i.Type != "loop" && !i.RO {
|
|
||||||
fsused = 0
|
|
||||||
for _, child := range i.Children {
|
|
||||||
if child.RM {
|
|
||||||
child.Health = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskHealthState " + child.Path))
|
|
||||||
if strings.ToLower(strings.TrimSpace(child.State)) != "ok" {
|
|
||||||
health = false
|
|
||||||
}
|
|
||||||
f, _ := strconv.ParseUint(child.FSUsed, 10, 64)
|
|
||||||
fsused += f
|
|
||||||
} else {
|
|
||||||
health = false
|
|
||||||
}
|
|
||||||
c = append(c, child)
|
|
||||||
}
|
|
||||||
//i.Format = strings.TrimSpace(command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskType " + i.Path))
|
|
||||||
if health {
|
|
||||||
i.Health = "OK"
|
|
||||||
}
|
|
||||||
i.FSUsed = strconv.FormatUint(fsused, 10)
|
|
||||||
i.Children = c
|
|
||||||
if fsused > 0 {
|
|
||||||
i.UsedPercent, err = strconv.ParseFloat(fmt.Sprintf("%.4f", float64(fsused)/float64(i.Size)), 64)
|
|
||||||
if err != nil {
|
|
||||||
loger.Error("Failed to parse float", zap.Any("err", err))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
n = append(n, i)
|
|
||||||
health = true
|
|
||||||
c = []model.LSBLKModel{}
|
|
||||||
fsused = 0
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if len(n) > 0 {
|
|
||||||
Cache.Add(key, n, time.Second*100)
|
|
||||||
}
|
|
||||||
return n
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) GetDiskInfo(path string) model.LSBLKModel {
|
|
||||||
str := command2.ExecLSBLKByPath(path)
|
|
||||||
if str == nil {
|
|
||||||
loger.Error("Failed to exec shell", zap.Any("err", "lsblk exec error"))
|
|
||||||
return model.LSBLKModel{}
|
|
||||||
}
|
|
||||||
|
|
||||||
var ml []model.LSBLKModel
|
|
||||||
err := json2.Unmarshal([]byte(gjson.Get(string(str), "blockdevices").String()), &ml)
|
|
||||||
if err != nil {
|
|
||||||
loger.Error("Failed to unmarshal json", zap.Any("err", err))
|
|
||||||
return model.LSBLKModel{}
|
|
||||||
}
|
|
||||||
|
|
||||||
m := model.LSBLKModel{}
|
|
||||||
if len(ml) > 0 {
|
|
||||||
m = ml[0]
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
// 下面为计算是否可以继续分区的部分,暂时不需要
|
|
||||||
chiArr := make(map[string]string)
|
|
||||||
chiList := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetPartitionSectors " + m.Path)
|
|
||||||
if len(chiList) == 0 {
|
|
||||||
loger.Error("chiList length error", zap.Any("err", "chiList length error"))
|
|
||||||
}
|
|
||||||
for i := 0; i < len(chiList); i++ {
|
|
||||||
tempArr := strings.Split(chiList[i], ",")
|
|
||||||
chiArr[tempArr[0]] = chiList[i]
|
|
||||||
}
|
|
||||||
var maxSector uint64 = 0
|
|
||||||
for i := 0; i < len(m.Children); i++ {
|
|
||||||
tempArr := strings.Split(chiArr[m.Children[i].Path], ",")
|
|
||||||
m.Children[i].StartSector, _ = strconv.ParseUint(tempArr[1], 10, 64)
|
|
||||||
m.Children[i].EndSector, _ = strconv.ParseUint(tempArr[2], 10, 64)
|
|
||||||
if m.Children[i].EndSector > maxSector {
|
|
||||||
maxSector = m.Children[i].EndSector
|
|
||||||
}
|
|
||||||
|
|
||||||
}
|
|
||||||
diskEndSector := command2.ExecResultStrArray("source " + config.AppInfo.ShellPath + "/helper.sh ;GetDiskSizeAndSectors " + m.Path)
|
|
||||||
|
|
||||||
if len(diskEndSector) < 2 {
|
|
||||||
loger.Error("diskEndSector length error", zap.Any("err", "diskEndSector length error"))
|
|
||||||
}
|
|
||||||
diskEndSectorInt, _ := strconv.ParseUint(diskEndSector[len(diskEndSector)-1], 10, 64)
|
|
||||||
if (diskEndSectorInt-maxSector)*m.MinIO/1024/1024 > 100 {
|
|
||||||
//添加可以分区情况
|
|
||||||
p := model.LSBLKModel{}
|
|
||||||
p.Path = "可以添加"
|
|
||||||
m.Children = append(m.Children, p)
|
|
||||||
}
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) MountDisk(path, volume string) {
|
|
||||||
//fmt.Println("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
|
|
||||||
r := command2.ExecResultStr("source " + config.AppInfo.ShellPath + "/helper.sh ;do_mount " + path + " " + volume)
|
|
||||||
fmt.Println(r)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) SaveMountPoint(m model2.SerialDisk) {
|
|
||||||
d.db.Where("uuid = ?", m.UUID).Delete(&model2.SerialDisk{})
|
|
||||||
d.db.Create(&m)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) UpdateMountPoint(m model2.SerialDisk) {
|
|
||||||
d.db.Model(&model2.SerialDisk{}).Where("uui = ?", m.UUID).Update("mount_point", m.MountPoint)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) DeleteMount(id string) {
|
|
||||||
|
|
||||||
d.db.Delete(&model2.SerialDisk{}).Where("id = ?", id)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) DeleteMountPoint(path, mountPoint string) {
|
|
||||||
|
|
||||||
d.db.Where("path = ? AND mount_point = ?", path, mountPoint).Delete(&model2.SerialDisk{})
|
|
||||||
|
|
||||||
command2.OnlyExec("source " + config.AppInfo.ShellPath + "/helper.sh ;do_umount " + path)
|
|
||||||
}
|
|
||||||
|
|
||||||
func (d *diskService) GetSerialAll() []model2.SerialDisk {
|
|
||||||
var m []model2.SerialDisk
|
|
||||||
d.db.Find(&m)
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewDiskService(db *gorm.DB) DiskService {
|
|
||||||
return &diskService{db: db}
|
|
||||||
}
|
|
||||||
@@ -7,13 +7,8 @@ import (
|
|||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
json2 "encoding/json"
|
json2 "encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"syscall"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model/notify"
|
"github.com/IceWhaleTech/CasaOS/model/notify"
|
||||||
"github.com/containerd/containerd"
|
|
||||||
"github.com/containerd/containerd/cio"
|
|
||||||
"github.com/containerd/containerd/namespaces"
|
|
||||||
"github.com/containerd/containerd/oci"
|
|
||||||
"github.com/pkg/errors"
|
"github.com/pkg/errors"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
@@ -57,13 +52,14 @@ type DockerService interface {
|
|||||||
DockerContainerStop(id string) error
|
DockerContainerStop(id string) error
|
||||||
DockerContainerUpdateName(name, id string) (err error)
|
DockerContainerUpdateName(name, id string) (err error)
|
||||||
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
|
DockerContainerUpdate(m model.CustomizationPostData, id string) (err error)
|
||||||
DockerContainerLog(name string) (string, error)
|
DockerContainerLog(name string) ([]byte, error)
|
||||||
DockerContainerCommit(name string)
|
DockerContainerCommit(name string)
|
||||||
DockerContainerList() []types.Container
|
DockerContainerList() []types.Container
|
||||||
DockerNetworkModelList() []types.NetworkResource
|
DockerNetworkModelList() []types.NetworkResource
|
||||||
DockerImageInfo(image string) (types.ImageInspect, error)
|
DockerImageInfo(image string) (types.ImageInspect, error)
|
||||||
GetNetWorkNameByNetWorkID(id string) (string, error)
|
GetNetWorkNameByNetWorkID(id string) (string, error)
|
||||||
ContainerExecShell(container_id string) string
|
ContainerExecShell(container_id string) string
|
||||||
|
GetDockerInfo() (types.Info, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type dockerService struct {
|
type dockerService struct {
|
||||||
@@ -99,7 +95,7 @@ func (ds *dockerService) ContainerExecShell(container_id string) string {
|
|||||||
return exec.ID
|
return exec.ID
|
||||||
}
|
}
|
||||||
|
|
||||||
//创建默认网络
|
// 创建默认网络
|
||||||
func DockerNetwork() {
|
func DockerNetwork() {
|
||||||
|
|
||||||
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
@@ -114,7 +110,7 @@ func DockerNetwork() {
|
|||||||
cli.NetworkCreate(context.Background(), docker.NETWORKNAME, types.NetworkCreate{})
|
cli.NetworkCreate(context.Background(), docker.NETWORKNAME, types.NetworkCreate{})
|
||||||
}
|
}
|
||||||
|
|
||||||
//根据网络id获取网络名
|
// 根据网络id获取网络名
|
||||||
func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
|
func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
|
||||||
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
@@ -127,7 +123,7 @@ func (ds *dockerService) GetNetWorkNameByNetWorkID(id string) (string, error) {
|
|||||||
return "", err
|
return "", err
|
||||||
}
|
}
|
||||||
|
|
||||||
//拉取镜像
|
// 拉取镜像
|
||||||
func DockerPull() {
|
func DockerPull() {
|
||||||
|
|
||||||
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
@@ -146,7 +142,7 @@ func DockerPull() {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
//拉取镜像
|
// 拉取镜像
|
||||||
func DockerEx() {
|
func DockerEx() {
|
||||||
|
|
||||||
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
@@ -297,7 +293,7 @@ func DockerLogs() {
|
|||||||
|
|
||||||
//正式内容
|
//正式内容
|
||||||
|
|
||||||
//检查镜像是否存在
|
// 检查镜像是否存在
|
||||||
func (ds *dockerService) IsExistImage(imageName string) bool {
|
func (ds *dockerService) IsExistImage(imageName string) bool {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -316,7 +312,7 @@ func (ds *dockerService) IsExistImage(imageName string) bool {
|
|||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
|
|
||||||
//安装镜像
|
// 安装镜像
|
||||||
func (ds *dockerService) DockerPullImage(imageName string, icon, name string) error {
|
func (ds *dockerService) DockerPullImage(imageName string, icon, name string) error {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -370,12 +366,12 @@ func (ds *dockerService) DockerContainerCopyCreate(info *types.ContainerJSON) (c
|
|||||||
return container.ID, err
|
return container.ID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//param imageName 镜像名称
|
// param imageName 镜像名称
|
||||||
//param containerDbId 数据库的id
|
// param containerDbId 数据库的id
|
||||||
//param port 容器内部主端口
|
// param port 容器内部主端口
|
||||||
//param mapPort 容器主端口映射到外部的端口
|
// param mapPort 容器主端口映射到外部的端口
|
||||||
//param tcp 容器其他tcp端口
|
// param tcp 容器其他tcp端口
|
||||||
//param udp 容器其他udp端口
|
// param udp 容器其他udp端口
|
||||||
func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error) {
|
func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id string) (containerId string, err error) {
|
||||||
if len(m.NetworkModel) == 0 {
|
if len(m.NetworkModel) == 0 {
|
||||||
m.NetworkModel = "bridge"
|
m.NetworkModel = "bridge"
|
||||||
@@ -535,13 +531,21 @@ func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id
|
|||||||
// info.NetworkSettings = &types.NetworkSettings{}
|
// info.NetworkSettings = &types.NetworkSettings{}
|
||||||
hostConfig = info.HostConfig
|
hostConfig = info.HostConfig
|
||||||
config = info.Config
|
config = info.Config
|
||||||
|
if config.Labels["casaos"] == "casaos" {
|
||||||
|
config.Cmd = m.Cmd
|
||||||
|
config.Image = m.Image
|
||||||
|
config.Env = envArr
|
||||||
|
config.Hostname = m.HostName
|
||||||
|
config.ExposedPorts = ports
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
config.Cmd = m.Cmd
|
||||||
|
config.Image = m.Image
|
||||||
|
config.Env = envArr
|
||||||
|
config.Hostname = m.HostName
|
||||||
|
config.ExposedPorts = ports
|
||||||
}
|
}
|
||||||
|
|
||||||
config.Cmd = m.Cmd
|
|
||||||
config.Image = m.Image
|
|
||||||
config.Env = envArr
|
|
||||||
config.Hostname = m.HostName
|
|
||||||
config.ExposedPorts = ports
|
|
||||||
config.Labels["origin"] = m.Origin
|
config.Labels["origin"] = m.Origin
|
||||||
config.Labels["casaos"] = "casaos"
|
config.Labels["casaos"] = "casaos"
|
||||||
config.Labels["web"] = m.PortMap
|
config.Labels["web"] = m.PortMap
|
||||||
@@ -578,7 +582,7 @@ func (ds *dockerService) DockerContainerCreate(m model.CustomizationPostData, id
|
|||||||
return containerDb.ID, err
|
return containerDb.ID, err
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除容器
|
// 删除容器
|
||||||
func (ds *dockerService) DockerContainerRemove(name string, update bool) error {
|
func (ds *dockerService) DockerContainerRemove(name string, update bool) error {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -602,7 +606,7 @@ func (ds *dockerService) DockerContainerRemove(name string, update bool) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//删除镜像
|
// 删除镜像
|
||||||
func (ds *dockerService) DockerImageRemove(name string) error {
|
func (ds *dockerService) DockerImageRemove(name string) error {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -650,7 +654,7 @@ Loop:
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//停止镜像
|
// 停止镜像
|
||||||
func (ds *dockerService) DockerContainerStop(id string) error {
|
func (ds *dockerService) DockerContainerStop(id string) error {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -661,7 +665,7 @@ func (ds *dockerService) DockerContainerStop(id string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//启动容器
|
// 启动容器
|
||||||
func (ds *dockerService) DockerContainerStart(name string) error {
|
func (ds *dockerService) DockerContainerStart(name string) error {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -672,24 +676,27 @@ func (ds *dockerService) DockerContainerStart(name string) error {
|
|||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
||||||
//查看日志
|
// 查看日志
|
||||||
func (ds *dockerService) DockerContainerLog(name string) (string, error) {
|
func (ds *dockerService) DockerContainerLog(name string) ([]byte, error) {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return []byte(""), err
|
||||||
}
|
}
|
||||||
defer cli.Close()
|
defer cli.Close()
|
||||||
body, err := cli.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{ShowStderr: true, ShowStdout: true})
|
//body, err := cli.ContainerAttach(context.Background(), name, types.ContainerAttachOptions{Logs: true, Stream: false, Stdin: false, Stdout: false, Stderr: false})
|
||||||
|
body, err := cli.ContainerLogs(context.Background(), name, types.ContainerLogsOptions{ShowStdout: true, ShowStderr: true})
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return []byte(""), err
|
||||||
}
|
}
|
||||||
|
|
||||||
defer body.Close()
|
defer body.Close()
|
||||||
content, err := ioutil.ReadAll(body)
|
content, err := ioutil.ReadAll(body)
|
||||||
|
//content, err := ioutil.ReadAll(body)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return "", err
|
return []byte(""), err
|
||||||
}
|
}
|
||||||
return string(content), nil
|
return content, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func DockerContainerStats1() error {
|
func DockerContainerStats1() error {
|
||||||
@@ -711,7 +718,7 @@ func DockerContainerStats1() error {
|
|||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取容器状态
|
// 获取容器状态
|
||||||
func (ds *dockerService) DockerContainerStats(name string) (string, error) {
|
func (ds *dockerService) DockerContainerStats(name string) (string, error) {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -730,7 +737,7 @@ func (ds *dockerService) DockerContainerStats(name string) (string, error) {
|
|||||||
return string(sts), nil
|
return string(sts), nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//备份容器
|
// 备份容器
|
||||||
func (ds *dockerService) DockerContainerCommit(name string) {
|
func (ds *dockerService) DockerContainerCommit(name string) {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -775,7 +782,7 @@ func (ds *dockerService) DockerListByImage(image, version string) (*types.Contai
|
|||||||
return &containers[0], nil
|
return &containers[0], nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取容器详情
|
// 获取容器详情
|
||||||
func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON, error) {
|
func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON, error) {
|
||||||
|
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
@@ -790,13 +797,13 @@ func (ds *dockerService) DockerContainerInfo(name string) (*types.ContainerJSON,
|
|||||||
return &d, nil
|
return &d, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
//更新容器
|
// 更新容器
|
||||||
//param shares cpu优先级
|
// param shares cpu优先级
|
||||||
//param containerDbId 数据库的id
|
// param containerDbId 数据库的id
|
||||||
//param port 容器内部主端口
|
// param port 容器内部主端口
|
||||||
//param mapPort 容器主端口映射到外部的端口
|
// param mapPort 容器主端口映射到外部的端口
|
||||||
//param tcp 容器其他tcp端口
|
// param tcp 容器其他tcp端口
|
||||||
//param udp 容器其他udp端口
|
// param udp 容器其他udp端口
|
||||||
func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) {
|
func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id string) (err error) {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -831,9 +838,9 @@ func (ds *dockerService) DockerContainerUpdate(m model.CustomizationPostData, id
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//更新容器名称
|
// 更新容器名称
|
||||||
//param name 容器名称
|
// param name 容器名称
|
||||||
//param id 老的容器名称
|
// param id 老的容器名称
|
||||||
func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error) {
|
func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error) {
|
||||||
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -848,7 +855,7 @@ func (ds *dockerService) DockerContainerUpdateName(name, id string) (err error)
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取网络列表
|
// 获取网络列表
|
||||||
func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
|
func (ds *dockerService) DockerNetworkModelList() []types.NetworkResource {
|
||||||
|
|
||||||
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
cli, _ := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
@@ -860,6 +867,17 @@ func NewDockerService() DockerService {
|
|||||||
return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`)}
|
return &dockerService{rootDir: command2.ExecResultStr(`source ./shell/helper.sh ;GetDockerRootDir`)}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (ds *dockerService) GetDockerInfo() (types.Info, error) {
|
||||||
|
cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
|
if err != nil {
|
||||||
|
return types.Info{}, err
|
||||||
|
}
|
||||||
|
defer cli.Close()
|
||||||
|
|
||||||
|
return cli.Info(context.Background())
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
// ---------------------------------------test------------------------------------
|
// ---------------------------------------test------------------------------------
|
||||||
//func ServiceCreate() {
|
//func ServiceCreate() {
|
||||||
// cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
// cli, err := client2.NewClientWithOpts(client2.FromEnv)
|
||||||
@@ -871,73 +889,73 @@ func NewDockerService() DockerService {
|
|||||||
//
|
//
|
||||||
//}
|
//}
|
||||||
|
|
||||||
func Containerd() {
|
// func Containerd() {
|
||||||
// create a new client connected to the default socket path for containerd
|
// // create a new client connected to the default socket path for containerd
|
||||||
cli, err := containerd.New("/run/containerd/containerd.sock")
|
// cli, err := containerd.New("/run/containerd/containerd.sock")
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
fmt.Println("111")
|
// fmt.Println("111")
|
||||||
fmt.Println(err)
|
// fmt.Println(err)
|
||||||
}
|
// }
|
||||||
defer cli.Close()
|
// defer cli.Close()
|
||||||
|
|
||||||
// create a new context with an "example" namespace
|
// // create a new context with an "example" namespace
|
||||||
ctx := namespaces.WithNamespace(context.Background(), "default")
|
// ctx := namespaces.WithNamespace(context.Background(), "default")
|
||||||
|
|
||||||
// pull the redis image from DockerHub
|
// // pull the redis image from DockerHub
|
||||||
image, err := cli.Pull(ctx, "docker.io/library/busybox:latest", containerd.WithPullUnpack)
|
// image, err := cli.Pull(ctx, "docker.io/library/busybox:latest", containerd.WithPullUnpack)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
fmt.Println("222")
|
// fmt.Println("222")
|
||||||
fmt.Println(err)
|
// fmt.Println(err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
// create a container
|
// // create a container
|
||||||
container, err := cli.NewContainer(
|
// container, err := cli.NewContainer(
|
||||||
ctx,
|
// ctx,
|
||||||
"test1",
|
// "test1",
|
||||||
containerd.WithImage(image),
|
// containerd.WithImage(image),
|
||||||
containerd.WithNewSnapshot("redis-server-snapshot1", image),
|
// containerd.WithNewSnapshot("redis-server-snapshot1", image),
|
||||||
containerd.WithNewSpec(oci.WithImageConfig(image)),
|
// containerd.WithNewSpec(oci.WithImageConfig(image)),
|
||||||
)
|
// )
|
||||||
|
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
fmt.Println(err)
|
// fmt.Println(err)
|
||||||
}
|
// }
|
||||||
defer container.Delete(ctx, containerd.WithSnapshotCleanup)
|
// defer container.Delete(ctx, containerd.WithSnapshotCleanup)
|
||||||
|
|
||||||
// create a task from the container
|
// // create a task from the container
|
||||||
task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
|
// task, err := container.NewTask(ctx, cio.NewCreator(cio.WithStdio))
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
fmt.Println(err)
|
// fmt.Println(err)
|
||||||
}
|
// }
|
||||||
defer task.Delete(ctx)
|
// defer task.Delete(ctx)
|
||||||
|
|
||||||
// make sure we wait before calling start
|
// // make sure we wait before calling start
|
||||||
exitStatusC, err := task.Wait(ctx)
|
// exitStatusC, err := task.Wait(ctx)
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
fmt.Println(err)
|
// fmt.Println(err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
// call start on the task to execute the redis server
|
// // call start on the task to execute the redis server
|
||||||
if err = task.Start(ctx); err != nil {
|
// if err = task.Start(ctx); err != nil {
|
||||||
fmt.Println(err)
|
// fmt.Println(err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
fmt.Println("执行完成等待")
|
// fmt.Println("执行完成等待")
|
||||||
// sleep for a lil bit to see the logs
|
// // sleep for a lil bit to see the logs
|
||||||
time.Sleep(3 * time.Second)
|
// time.Sleep(3 * time.Second)
|
||||||
|
|
||||||
// kill the process and get the exit status
|
// // kill the process and get the exit status
|
||||||
if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
|
// if err = task.Kill(ctx, syscall.SIGTERM); err != nil {
|
||||||
fmt.Println(err)
|
// fmt.Println(err)
|
||||||
}
|
// }
|
||||||
|
|
||||||
// wait for the process to fully exit and print out the exit status
|
// // wait for the process to fully exit and print out the exit status
|
||||||
|
|
||||||
status := <-exitStatusC
|
// status := <-exitStatusC
|
||||||
code, _, err := status.Result()
|
// code, _, err := status.Result()
|
||||||
if err != nil {
|
// if err != nil {
|
||||||
fmt.Println(err)
|
// fmt.Println(err)
|
||||||
}
|
// }
|
||||||
fmt.Printf("redis-server exited with status: %d\n", code)
|
// fmt.Printf("redis-server exited with status: %d\n", code)
|
||||||
|
|
||||||
}
|
// }
|
||||||
|
|||||||
@@ -1,15 +0,0 @@
|
|||||||
package model
|
|
||||||
|
|
||||||
//SerialAdvanced Technology Attachment (STAT)
|
|
||||||
type SerialDisk struct {
|
|
||||||
Id uint `gorm:"column:id;primary_key" json:"id"`
|
|
||||||
UUID string `json:"uuid"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
State int `json:"state"`
|
|
||||||
MountPoint string `json:"mount_point"`
|
|
||||||
CreatedAt int64 `json:"created_at"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *SerialDisk) TableName() string {
|
|
||||||
return "o_disk"
|
|
||||||
}
|
|
||||||
@@ -1,31 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-05-13 18:15:46
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-07-11 17:57:00
|
|
||||||
* @FilePath: /CasaOS/service/model/o_user.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package model
|
|
||||||
|
|
||||||
import "time"
|
|
||||||
|
|
||||||
//Soon to be removed
|
|
||||||
type UserDBModel struct {
|
|
||||||
Id int `gorm:"column:id;primary_key" json:"id"`
|
|
||||||
Username string `json:"username"`
|
|
||||||
Password string `json:"password,omitempty"`
|
|
||||||
Role string `json:"role"`
|
|
||||||
Email string `json:"email"`
|
|
||||||
Nickname string `json:"nickname"`
|
|
||||||
Avatar string `json:"avatar"`
|
|
||||||
Description string `json:"description"`
|
|
||||||
CreatedAt time.Time `gorm:"<-:create;autoCreateTime" json:"created_at,omitempty"`
|
|
||||||
UpdatedAt time.Time `gorm:"<-:create;<-:update;autoUpdateTime" json:"updated_at,omitempty"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func (p *UserDBModel) TableName() string {
|
|
||||||
return "o_users"
|
|
||||||
}
|
|
||||||
@@ -31,16 +31,37 @@ type NotifyServer interface {
|
|||||||
SendNetInfoBySocket(netList []model2.IOCountersStat)
|
SendNetInfoBySocket(netList []model2.IOCountersStat)
|
||||||
SendCPUInfoBySocket(cpu map[string]interface{})
|
SendCPUInfoBySocket(cpu map[string]interface{})
|
||||||
SendMemInfoBySocket(mem map[string]interface{})
|
SendMemInfoBySocket(mem map[string]interface{})
|
||||||
SendUSBInfoBySocket(list []model2.DriveUSB)
|
|
||||||
SendDiskInfoBySocket(disk model2.Summary)
|
|
||||||
SendFileOperateNotify(nowSend bool)
|
SendFileOperateNotify(nowSend bool)
|
||||||
SendInstallAppBySocket(app notify.Application)
|
SendInstallAppBySocket(app notify.Application)
|
||||||
SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat)
|
SendAllHardwareStatusBySocket(mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat)
|
||||||
SendStorageBySocket(message notify.StorageMessage)
|
SendStorageBySocket(message notify.StorageMessage)
|
||||||
|
SendNotify(path string, message map[string]interface{})
|
||||||
|
SettingSystemTempData(message map[string]interface{})
|
||||||
}
|
}
|
||||||
|
|
||||||
type notifyServer struct {
|
type notifyServer struct {
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
|
SystemTempMap map[string]interface{}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *notifyServer) SettingSystemTempData(message map[string]interface{}) {
|
||||||
|
for k, v := range message {
|
||||||
|
i.SystemTempMap[k] = v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (i *notifyServer) SendNotify(path string, message map[string]interface{}) {
|
||||||
|
msg := gosf.Message{}
|
||||||
|
msg.Body = message
|
||||||
|
msg.Success = true
|
||||||
|
msg.Text = path
|
||||||
|
|
||||||
|
notify := notify.Message{}
|
||||||
|
notify.Path = path
|
||||||
|
notify.Msg = msg
|
||||||
|
|
||||||
|
NotifyMsg <- notify
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) {
|
func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) {
|
||||||
@@ -58,12 +79,9 @@ func (i *notifyServer) SendStorageBySocket(message notify.StorageMessage) {
|
|||||||
|
|
||||||
NotifyMsg <- notify
|
NotifyMsg <- notify
|
||||||
}
|
}
|
||||||
func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list []model2.DriveUSB, mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) {
|
func (i *notifyServer) SendAllHardwareStatusBySocket(mem map[string]interface{}, cpu map[string]interface{}, netList []model2.IOCountersStat) {
|
||||||
|
|
||||||
body := make(map[string]interface{})
|
body := make(map[string]interface{})
|
||||||
body["sys_disk"] = disk
|
|
||||||
|
|
||||||
body["sys_usb"] = list
|
|
||||||
|
|
||||||
body["sys_mem"] = mem
|
body["sys_mem"] = mem
|
||||||
|
|
||||||
@@ -71,6 +89,10 @@ func (i *notifyServer) SendAllHardwareStatusBySocket(disk model2.Summary, list [
|
|||||||
|
|
||||||
body["sys_net"] = netList
|
body["sys_net"] = netList
|
||||||
|
|
||||||
|
for k, v := range i.SystemTempMap {
|
||||||
|
body[k] = v
|
||||||
|
}
|
||||||
|
|
||||||
msg := gosf.Message{}
|
msg := gosf.Message{}
|
||||||
msg.Body = body
|
msg.Body = body
|
||||||
msg.Success = true
|
msg.Success = true
|
||||||
@@ -239,38 +261,6 @@ func (i *notifyServer) SendFileOperateNotify(nowSend bool) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (i *notifyServer) SendDiskInfoBySocket(disk model2.Summary) {
|
|
||||||
body := make(map[string]interface{})
|
|
||||||
body["data"] = disk
|
|
||||||
|
|
||||||
msg := gosf.Message{}
|
|
||||||
msg.Body = body
|
|
||||||
msg.Success = true
|
|
||||||
msg.Text = "sys_disk"
|
|
||||||
|
|
||||||
notify := notify.Message{}
|
|
||||||
notify.Path = "sys_disk"
|
|
||||||
notify.Msg = msg
|
|
||||||
|
|
||||||
NotifyMsg <- notify
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *notifyServer) SendUSBInfoBySocket(list []model2.DriveUSB) {
|
|
||||||
body := make(map[string]interface{})
|
|
||||||
body["data"] = list
|
|
||||||
|
|
||||||
msg := gosf.Message{}
|
|
||||||
msg.Body = body
|
|
||||||
msg.Success = true
|
|
||||||
msg.Text = "sys_usb"
|
|
||||||
|
|
||||||
notify := notify.Message{}
|
|
||||||
notify.Path = "sys_usb"
|
|
||||||
notify.Msg = msg
|
|
||||||
|
|
||||||
NotifyMsg <- notify
|
|
||||||
}
|
|
||||||
|
|
||||||
func (i *notifyServer) SendMemInfoBySocket(mem map[string]interface{}) {
|
func (i *notifyServer) SendMemInfoBySocket(mem map[string]interface{}) {
|
||||||
body := make(map[string]interface{})
|
body := make(map[string]interface{})
|
||||||
body["data"] = mem
|
body["data"] = mem
|
||||||
@@ -454,5 +444,5 @@ func SendMeg() {
|
|||||||
// }
|
// }
|
||||||
|
|
||||||
func NewNotifyService(db *gorm.DB) NotifyServer {
|
func NewNotifyService(db *gorm.DB) NotifyServer {
|
||||||
return ¬ifyServer{db: db}
|
return ¬ifyServer{db: db, SystemTempMap: make(map[string]interface{})}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.com
|
* @Author: LinkLeong link@icewhale.com
|
||||||
* @Date: 2022-07-12 09:48:56
|
* @Date: 2022-07-12 09:48:56
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-07-27 10:28:48
|
* @LastEditTime: 2022-09-02 22:10:05
|
||||||
* @FilePath: /CasaOS/service/service.go
|
* @FilePath: /CasaOS/service/service.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -11,6 +11,7 @@
|
|||||||
package service
|
package service
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
gateway "github.com/IceWhaleTech/CasaOS-Gateway/common"
|
||||||
"github.com/gorilla/websocket"
|
"github.com/gorilla/websocket"
|
||||||
"github.com/patrickmn/go-cache"
|
"github.com/patrickmn/go-cache"
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
@@ -26,24 +27,29 @@ var SocketRun bool
|
|||||||
|
|
||||||
type Repository interface {
|
type Repository interface {
|
||||||
App() AppService
|
App() AppService
|
||||||
User() UserService
|
//User() UserService
|
||||||
Docker() DockerService
|
Docker() DockerService
|
||||||
Casa() CasaService
|
Casa() CasaService
|
||||||
Disk() DiskService
|
|
||||||
Notify() NotifyServer
|
Notify() NotifyServer
|
||||||
Rely() RelyService
|
Rely() RelyService
|
||||||
System() SystemService
|
System() SystemService
|
||||||
Shares() SharesService
|
Shares() SharesService
|
||||||
Connections() ConnectionsService
|
Connections() ConnectionsService
|
||||||
|
Gateway() gateway.ManagementService
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewService(db *gorm.DB) Repository {
|
func NewService(db *gorm.DB, RuntimePath string) Repository {
|
||||||
|
|
||||||
|
gatewayManagement, err := gateway.NewManagementService(RuntimePath)
|
||||||
|
if err != nil && len(RuntimePath) > 0 {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
|
||||||
return &store{
|
return &store{
|
||||||
|
gateway: gatewayManagement,
|
||||||
app: NewAppService(db),
|
app: NewAppService(db),
|
||||||
user: NewUserService(db),
|
|
||||||
docker: NewDockerService(),
|
docker: NewDockerService(),
|
||||||
casa: NewCasaService(),
|
casa: NewCasaService(),
|
||||||
disk: NewDiskService(db),
|
|
||||||
notify: NewNotifyService(db),
|
notify: NewNotifyService(db),
|
||||||
rely: NewRelyService(db),
|
rely: NewRelyService(db),
|
||||||
system: NewSystemService(),
|
system: NewSystemService(),
|
||||||
@@ -55,17 +61,19 @@ func NewService(db *gorm.DB) Repository {
|
|||||||
type store struct {
|
type store struct {
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
app AppService
|
app AppService
|
||||||
user UserService
|
|
||||||
docker DockerService
|
docker DockerService
|
||||||
casa CasaService
|
casa CasaService
|
||||||
disk DiskService
|
|
||||||
notify NotifyServer
|
notify NotifyServer
|
||||||
rely RelyService
|
rely RelyService
|
||||||
system SystemService
|
system SystemService
|
||||||
shares SharesService
|
shares SharesService
|
||||||
connections ConnectionsService
|
connections ConnectionsService
|
||||||
|
gateway gateway.ManagementService
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *store) Gateway() gateway.ManagementService {
|
||||||
|
return c.gateway
|
||||||
|
}
|
||||||
func (s *store) Connections() ConnectionsService {
|
func (s *store) Connections() ConnectionsService {
|
||||||
return s.connections
|
return s.connections
|
||||||
}
|
}
|
||||||
@@ -89,10 +97,6 @@ func (c *store) App() AppService {
|
|||||||
return c.app
|
return c.app
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *store) User() UserService {
|
|
||||||
return c.user
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *store) Docker() DockerService {
|
func (c *store) Docker() DockerService {
|
||||||
return c.docker
|
return c.docker
|
||||||
}
|
}
|
||||||
@@ -100,7 +104,3 @@ func (c *store) Docker() DockerService {
|
|||||||
func (c *store) Casa() CasaService {
|
func (c *store) Casa() CasaService {
|
||||||
return c.casa
|
return c.casa
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *store) Disk() DiskService {
|
|
||||||
return c.disk
|
|
||||||
}
|
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
* @Author: LinkLeong link@icewhale.org
|
* @Author: LinkLeong link@icewhale.org
|
||||||
* @Date: 2022-07-26 11:21:14
|
* @Date: 2022-07-26 11:21:14
|
||||||
* @LastEditors: LinkLeong
|
* @LastEditors: LinkLeong
|
||||||
* @LastEditTime: 2022-08-11 14:04:00
|
* @LastEditTime: 2022-08-18 11:16:25
|
||||||
* @FilePath: /CasaOS/service/shares.go
|
* @FilePath: /CasaOS/service/shares.go
|
||||||
* @Description:
|
* @Description:
|
||||||
* @Website: https://www.casaos.io
|
* @Website: https://www.casaos.io
|
||||||
@@ -30,12 +30,18 @@ type SharesService interface {
|
|||||||
DeleteShare(id string)
|
DeleteShare(id string)
|
||||||
UpdateConfigFile()
|
UpdateConfigFile()
|
||||||
InitSambaConfig()
|
InitSambaConfig()
|
||||||
|
DeleteShareByPath(path string)
|
||||||
}
|
}
|
||||||
|
|
||||||
type sharesStruct struct {
|
type sharesStruct struct {
|
||||||
db *gorm.DB
|
db *gorm.DB
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *sharesStruct) DeleteShareByPath(path string) {
|
||||||
|
s.db.Where("path LIKE ?", path+"%").Delete(&model.SharesDBModel{})
|
||||||
|
s.UpdateConfigFile()
|
||||||
|
}
|
||||||
|
|
||||||
func (s *sharesStruct) GetSharesByName(name string) (shares []model2.SharesDBModel) {
|
func (s *sharesStruct) GetSharesByName(name string) (shares []model2.SharesDBModel) {
|
||||||
s.db.Select("anonymous,path,id").Where("name = ?", name).Find(&shares)
|
s.db.Select("anonymous,path,id").Where("name = ?", name).Find(&shares)
|
||||||
|
|
||||||
|
|||||||
@@ -50,6 +50,8 @@ type SystemService interface {
|
|||||||
RenameFile(oldF, newF string) (int, error)
|
RenameFile(oldF, newF string) (int, error)
|
||||||
MkdirAll(path string) (int, error)
|
MkdirAll(path string) (int, error)
|
||||||
IsServiceRunning(name string) bool
|
IsServiceRunning(name string) bool
|
||||||
|
GetCPUTemperature() int
|
||||||
|
GetCPUPower() map[string]string
|
||||||
}
|
}
|
||||||
type systemService struct {
|
type systemService struct {
|
||||||
}
|
}
|
||||||
@@ -294,6 +296,33 @@ func (s *systemService) IsServiceRunning(name string) bool {
|
|||||||
return strings.TrimSpace(status) == "running"
|
return strings.TrimSpace(status) == "running"
|
||||||
|
|
||||||
}
|
}
|
||||||
|
func (s *systemService) GetCPUTemperature() int {
|
||||||
|
outPut := ""
|
||||||
|
if file.Exists("/sys/class/thermal/thermal_zone0/temp") {
|
||||||
|
outPut = string(file.ReadFullFile("/sys/class/thermal/thermal_zone0/temp"))
|
||||||
|
} else if file.Exists("/sys/class/hwmon/hwmon0/temp1_input") {
|
||||||
|
outPut = string(file.ReadFullFile("/sys/class/hwmon/hwmon0/temp1_input"))
|
||||||
|
} else {
|
||||||
|
outPut = "0"
|
||||||
|
}
|
||||||
|
|
||||||
|
celsius, _ := strconv.Atoi(strings.TrimSpace(outPut))
|
||||||
|
|
||||||
|
if celsius > 1000 {
|
||||||
|
celsius = celsius / 1000
|
||||||
|
}
|
||||||
|
return celsius
|
||||||
|
}
|
||||||
|
func (s *systemService) GetCPUPower() map[string]string {
|
||||||
|
data := make(map[string]string, 2)
|
||||||
|
data["timestamp"] = strconv.FormatInt(time.Now().Unix(), 10)
|
||||||
|
if file.Exists("/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj") {
|
||||||
|
data["value"] = strings.TrimSpace(string(file.ReadFullFile("/sys/class/powercap/intel-rapl/intel-rapl:0/energy_uj")))
|
||||||
|
} else {
|
||||||
|
data["value"] = "0"
|
||||||
|
}
|
||||||
|
return data
|
||||||
|
}
|
||||||
func NewSystemService() SystemService {
|
func NewSystemService() SystemService {
|
||||||
return &systemService{}
|
return &systemService{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,99 +0,0 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.com
|
|
||||||
* @Date: 2022-03-18 11:40:55
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-07-12 10:05:37
|
|
||||||
* @FilePath: /CasaOS/service/user.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"io"
|
|
||||||
"mime/multipart"
|
|
||||||
"os"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service/model"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type UserService interface {
|
|
||||||
UpLoadFile(file multipart.File, name string) error
|
|
||||||
CreateUser(m model.UserDBModel) model.UserDBModel
|
|
||||||
GetUserCount() (userCount int64)
|
|
||||||
UpdateUser(m model.UserDBModel)
|
|
||||||
UpdateUserPassword(m model.UserDBModel)
|
|
||||||
GetUserInfoById(id string) (m model.UserDBModel)
|
|
||||||
GetUserAllInfoById(id string) (m model.UserDBModel)
|
|
||||||
GetUserAllInfoByName(userName string) (m model.UserDBModel)
|
|
||||||
DeleteUserById(id string)
|
|
||||||
DeleteAllUser()
|
|
||||||
GetUserInfoByUserName(userName string) (m model.UserDBModel)
|
|
||||||
GetAllUserName() (list []model.UserDBModel)
|
|
||||||
}
|
|
||||||
|
|
||||||
var UserRegisterHash = make(map[string]string)
|
|
||||||
|
|
||||||
type userService struct {
|
|
||||||
db *gorm.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *userService) DeleteAllUser() {
|
|
||||||
u.db.Where("1=1").Delete(&model.UserDBModel{})
|
|
||||||
}
|
|
||||||
func (u *userService) DeleteUserById(id string) {
|
|
||||||
u.db.Where("id= ?", id).Delete(&model.UserDBModel{})
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *userService) GetAllUserName() (list []model.UserDBModel) {
|
|
||||||
u.db.Select("username").Find(&list)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (u *userService) CreateUser(m model.UserDBModel) model.UserDBModel {
|
|
||||||
u.db.Create(&m)
|
|
||||||
return m
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *userService) GetUserCount() (userCount int64) {
|
|
||||||
u.db.Find(&model.UserDBModel{}).Count(&userCount)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *userService) UpdateUser(m model.UserDBModel) {
|
|
||||||
u.db.Model(&m).Omit("password").Updates(&m)
|
|
||||||
}
|
|
||||||
func (u *userService) UpdateUserPassword(m model.UserDBModel) {
|
|
||||||
u.db.Model(&m).Update("password", m.Password)
|
|
||||||
}
|
|
||||||
func (u *userService) GetUserAllInfoById(id string) (m model.UserDBModel) {
|
|
||||||
u.db.Where("id= ?", id).First(&m)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (u *userService) GetUserAllInfoByName(userName string) (m model.UserDBModel) {
|
|
||||||
u.db.Where("username= ?", userName).First(&m)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func (u *userService) GetUserInfoById(id string) (m model.UserDBModel) {
|
|
||||||
u.db.Select("username", "id", "role", "nickname", "description", "avatar", "email").Where("id= ?", id).First(&m)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
func (u *userService) GetUserInfoByUserName(userName string) (m model.UserDBModel) {
|
|
||||||
u.db.Select("username", "id", "role", "nickname", "description", "avatar", "email").Where("username= ?", userName).First(&m)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
|
|
||||||
//上传文件
|
|
||||||
func (c *userService) UpLoadFile(file multipart.File, url string) error {
|
|
||||||
out, _ := os.OpenFile(url, os.O_WRONLY|os.O_TRUNC|os.O_CREATE, 0644)
|
|
||||||
defer out.Close()
|
|
||||||
io.Copy(out, file)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//获取用户Service
|
|
||||||
func NewUserService(db *gorm.DB) UserService {
|
|
||||||
return &userService{db: db}
|
|
||||||
}
|
|
||||||
@@ -1,6 +0,0 @@
|
|||||||
|
|
||||||
# copy to /etc/udev/rules.d path
|
|
||||||
|
|
||||||
KERNEL=="sd[a-z]*[0-9]", SUBSYSTEMS=="usb", ACTION=="add", RUN+="/bin/systemctl start usb-mount@%k.service"
|
|
||||||
|
|
||||||
KERNEL=="sd[a-z]*[0-9]", SUBSYSTEMS=="usb", ACTION=="remove", RUN+="/bin/systemctl stop usb-mount@%k.service"
|
|
||||||
268
shell/update.sh
@@ -1,268 +0,0 @@
|
|||||||
#!/bin/bash
|
|
||||||
###
|
|
||||||
# @Author: LinkLeong link@icewhale.com
|
|
||||||
# @Date: 2022-06-30 10:08:33
|
|
||||||
# @LastEditors: LinkLeong
|
|
||||||
# @LastEditTime: 2022-07-01 11:18:07
|
|
||||||
# @FilePath: /CasaOS/shell/update.sh
|
|
||||||
# @Description:
|
|
||||||
###
|
|
||||||
|
|
||||||
((EUID)) && sudo_cmd="sudo"
|
|
||||||
|
|
||||||
# SYSTEM INFO
|
|
||||||
readonly UNAME_M="$(uname -m)"
|
|
||||||
|
|
||||||
# CasaOS PATHS
|
|
||||||
readonly CASA_REPO=IceWhaleTech/CasaOS
|
|
||||||
readonly CASA_UNZIP_TEMP_FOLDER=/tmp/casaos
|
|
||||||
readonly CASA_BIN=casaos
|
|
||||||
readonly CASA_BIN_PATH=/usr/bin/casaos
|
|
||||||
readonly CASA_CONF_PATH=/etc/casaos.conf
|
|
||||||
readonly CASA_SERVICE_PATH=/etc/systemd/system/casaos.service
|
|
||||||
readonly CASA_HELPER_PATH=/usr/share/casaos/shell/
|
|
||||||
readonly CASA_USER_CONF_PATH=/var/lib/casaos/conf/
|
|
||||||
readonly CASA_DB_PATH=/var/lib/casaos/db/
|
|
||||||
readonly CASA_TEMP_PATH=/var/lib/casaos/temp/
|
|
||||||
readonly CASA_LOGS_PATH=/var/log/casaos/
|
|
||||||
readonly CASA_PACKAGE_EXT=".tar.gz"
|
|
||||||
readonly CASA_RELEASE_API="https://api.github.com/repos/${CASA_REPO}/releases"
|
|
||||||
readonly CASA_OPENWRT_DOCS="https://github.com/IceWhaleTech/CasaOS-OpenWrt"
|
|
||||||
|
|
||||||
readonly COLOUR_RESET='\e[0m'
|
|
||||||
readonly aCOLOUR=(
|
|
||||||
'\e[38;5;154m' # green | Lines, bullets and separators
|
|
||||||
'\e[1m' # Bold white | Main descriptions
|
|
||||||
'\e[90m' # Grey | Credits
|
|
||||||
'\e[91m' # Red | Update notifications Alert
|
|
||||||
'\e[33m' # Yellow | Emphasis
|
|
||||||
)
|
|
||||||
|
|
||||||
Target_Arch=""
|
|
||||||
Target_Distro="debian"
|
|
||||||
Target_OS="linux"
|
|
||||||
Casa_Tag=""
|
|
||||||
|
|
||||||
|
|
||||||
#######################################
|
|
||||||
# Custom printing function
|
|
||||||
# Globals:
|
|
||||||
# None
|
|
||||||
# Arguments:
|
|
||||||
# $1 0:OK 1:FAILED 2:INFO 3:NOTICE
|
|
||||||
# message
|
|
||||||
# Returns:
|
|
||||||
# None
|
|
||||||
#######################################
|
|
||||||
|
|
||||||
Show() {
|
|
||||||
# OK
|
|
||||||
if (($1 == 0)); then
|
|
||||||
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} OK $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
|
||||||
# FAILED
|
|
||||||
elif (($1 == 1)); then
|
|
||||||
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[3]}FAILED$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
|
||||||
# INFO
|
|
||||||
elif (($1 == 2)); then
|
|
||||||
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[0]} INFO $COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
|
||||||
# NOTICE
|
|
||||||
elif (($1 == 3)); then
|
|
||||||
echo -e "${aCOLOUR[2]}[$COLOUR_RESET${aCOLOUR[4]}NOTICE$COLOUR_RESET${aCOLOUR[2]}]$COLOUR_RESET $2"
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
Warn() {
|
|
||||||
echo -e "${aCOLOUR[3]}$1$COLOUR_RESET"
|
|
||||||
}
|
|
||||||
|
|
||||||
# 0 Check_exist
|
|
||||||
Check_Exist() {
|
|
||||||
#Create Dir
|
|
||||||
Show 2 "Create Folders."
|
|
||||||
${sudo_cmd} mkdir -p ${CASA_HELPER_PATH}
|
|
||||||
${sudo_cmd} mkdir -p ${CASA_LOGS_PATH}
|
|
||||||
${sudo_cmd} mkdir -p ${CASA_USER_CONF_PATH}
|
|
||||||
${sudo_cmd} mkdir -p ${CASA_DB_PATH}
|
|
||||||
${sudo_cmd} mkdir -p ${CASA_TEMP_PATH}
|
|
||||||
|
|
||||||
|
|
||||||
Show 2 "Start cleaning up the old version."
|
|
||||||
|
|
||||||
${sudo_cmd} rm -rf /usr/lib/systemd/system/casaos.service
|
|
||||||
|
|
||||||
${sudo_cmd} rm -rf /lib/systemd/system/casaos.service
|
|
||||||
|
|
||||||
if [[ -f "/casaOS/server/conf/conf.ini" ]]; then
|
|
||||||
${sudo_cmd} cp -rf /casaOS/server/conf/conf.ini ${CASA_CONF_PATH}
|
|
||||||
${sudo_cmd} cp -rf /casaOS/server/conf/*.json ${CASA_USER_CONF_PATH}
|
|
||||||
fi
|
|
||||||
|
|
||||||
if [[ -d "/casaOS/server/db" ]]; then
|
|
||||||
${sudo_cmd} cp -rf /casaOS/server/db/* ${CASA_DB_PATH}
|
|
||||||
fi
|
|
||||||
|
|
||||||
Show 0 "Clearance completed."
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
# 1 Check Arch
|
|
||||||
Check_Arch() {
|
|
||||||
case $UNAME_M in
|
|
||||||
*aarch64*)
|
|
||||||
Target_Arch="arm64"
|
|
||||||
;;
|
|
||||||
*64*)
|
|
||||||
Target_Arch="amd64"
|
|
||||||
;;
|
|
||||||
*armv7*)
|
|
||||||
Target_Arch="arm-7"
|
|
||||||
;;
|
|
||||||
*)
|
|
||||||
Show 1 "Aborted, unsupported or unknown architecture: $UNAME_M"
|
|
||||||
exit 1
|
|
||||||
;;
|
|
||||||
esac
|
|
||||||
Show 0 "Your hardware architecture is : $UNAME_M"
|
|
||||||
}
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
#Download CasaOS Package
|
|
||||||
Download_CasaOS() {
|
|
||||||
Show 2 "Downloading CasaOS for ${Target_OS}/${Target_Arch}..."
|
|
||||||
Net_Getter="curl -fsSLk"
|
|
||||||
Casa_Package="${Target_OS}-${Target_Arch}-casaos${CASA_PACKAGE_EXT}"
|
|
||||||
if [[ ! -n "$version" ]]; then
|
|
||||||
Casa_Tag="$(${Net_Getter} ${CASA_RELEASE_API}/latest | grep -o '"tag_name": ".*"' | sed 's/"//g' | sed 's/tag_name: //g')"
|
|
||||||
elif [[ $version == "pre" ]]; then
|
|
||||||
Casa_Tag="$(${net_getter} ${CASA_RELEASE_API} | grep -o '"tag_name": ".*"' | sed 's/"//g' | sed 's/tag_name: //g' | sed -n '1p')"
|
|
||||||
else
|
|
||||||
Casa_Tag="$version"
|
|
||||||
fi
|
|
||||||
Casa_Package_URL="https://github.com/${CASA_REPO}/releases/download/${Casa_Tag}/${Casa_Package}"
|
|
||||||
echo
|
|
||||||
# Remove Temp File
|
|
||||||
${sudo_cmd} rm -rf "$PREFIX/tmp/${Casa_Package}"
|
|
||||||
# Download Package
|
|
||||||
${Net_Getter} "${Casa_Package_URL}" >"$PREFIX/tmp/${Casa_Package}"
|
|
||||||
if [[ $? -ne 0 ]]; then
|
|
||||||
Show 1 "Download failed, Please check if your internet connection is working and retry."
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
Show 0 "Download successful!"
|
|
||||||
fi
|
|
||||||
#Extract CasaOS Package
|
|
||||||
Show 2 "Extracting..."
|
|
||||||
case "${Casa_Package}" in
|
|
||||||
*.zip) ${sudo_cmd} unzip -o "$PREFIX/tmp/${Casa_Package}" -d "$PREFIX/tmp/" ;;
|
|
||||||
*.tar.gz) ${sudo_cmd} tar -xzf "$PREFIX/tmp/${Casa_Package}" -C "$PREFIX/tmp/" ;;
|
|
||||||
esac
|
|
||||||
#Setting Executable Permissions
|
|
||||||
${sudo_cmd} chmod +x "$PREFIX${CASA_UNZIP_TEMP_FOLDER}/${CASA_BIN}"
|
|
||||||
|
|
||||||
}
|
|
||||||
|
|
||||||
#Install Addons
|
|
||||||
Install_Addons() {
|
|
||||||
Show 2 "Installing CasaOS Addons"
|
|
||||||
${sudo_cmd} cp -rf "$PREFIX${CASA_UNZIP_TEMP_FOLDER}/shell/11-usb-mount.rules" "/etc/udev/rules.d/"
|
|
||||||
${sudo_cmd} cp -rf "$PREFIX${CASA_UNZIP_TEMP_FOLDER}/shell/usb-mount@.service" "/etc/systemd/system/"
|
|
||||||
sync
|
|
||||||
}
|
|
||||||
|
|
||||||
#Clean Temp Files
|
|
||||||
Clean_Temp_Files() {
|
|
||||||
Show 0 "Clean..."
|
|
||||||
${sudo_cmd} rm -rf "$PREFIX${CASA_UNZIP_TEMP_FOLDER}"
|
|
||||||
sync
|
|
||||||
}
|
|
||||||
|
|
||||||
#Install CasaOS
|
|
||||||
Install_CasaOS() {
|
|
||||||
Show 2 "Installing..."
|
|
||||||
|
|
||||||
# Install Bin
|
|
||||||
${sudo_cmd} mv -f $PREFIX${CASA_UNZIP_TEMP_FOLDER}/${CASA_BIN} ${CASA_BIN_PATH}
|
|
||||||
|
|
||||||
# Install Helper
|
|
||||||
if [[ -d ${CASA_HELPER_PATH} ]]; then
|
|
||||||
${sudo_cmd} rm -rf ${CASA_HELPER_PATH}*
|
|
||||||
fi
|
|
||||||
${sudo_cmd} cp -rf $PREFIX${CASA_UNZIP_TEMP_FOLDER}/shell/* ${CASA_HELPER_PATH}
|
|
||||||
#Setting Executable Permissions
|
|
||||||
${sudo_cmd} chmod +x $PREFIX${CASA_HELPER_PATH}*
|
|
||||||
|
|
||||||
# Install Conf
|
|
||||||
if [[ ! -f ${CASA_CONF_PATH} ]]; then
|
|
||||||
if [[ -f $PREFIX${CASA_UNZIP_TEMP_FOLDER}/conf/conf.ini.sample ]]; then
|
|
||||||
${sudo_cmd} mv -f $PREFIX${CASA_UNZIP_TEMP_FOLDER}/conf/conf.ini.sample ${CASA_CONF_PATH}
|
|
||||||
else
|
|
||||||
${sudo_cmd} mv -f $PREFIX${CASA_UNZIP_TEMP_FOLDER}/conf/conf.conf.sample ${CASA_CONF_PATH}
|
|
||||||
fi
|
|
||||||
|
|
||||||
fi
|
|
||||||
sync
|
|
||||||
|
|
||||||
if [[ ! -x "$(command -v ${CASA_BIN})" ]]; then
|
|
||||||
Show 1 "Installation failed, please try again."
|
|
||||||
exit 1
|
|
||||||
else
|
|
||||||
Show 0 "CasaOS Successfully installed."
|
|
||||||
fi
|
|
||||||
}
|
|
||||||
|
|
||||||
#Generate Service File
|
|
||||||
Generate_Service() {
|
|
||||||
if [ -f ${CASA_SERVICE_PATH} ]; then
|
|
||||||
Show 2 "Try stop CasaOS system service."
|
|
||||||
# Stop before generation
|
|
||||||
if [[ $(systemctl is-active ${CASA_BIN} &>/dev/null) ]]; then
|
|
||||||
${sudo_cmd} systemctl stop ${CASA_BIN}
|
|
||||||
fi
|
|
||||||
fi
|
|
||||||
Show 2 "Create system service for CasaOS."
|
|
||||||
|
|
||||||
${sudo_cmd} tee ${CASA_SERVICE_PATH} >/dev/null <<EOF
|
|
||||||
[Unit]
|
|
||||||
Description=CasaOS Service
|
|
||||||
StartLimitIntervalSec=0
|
|
||||||
|
|
||||||
[Service]
|
|
||||||
Type=simple
|
|
||||||
LimitNOFILE=15210
|
|
||||||
Restart=always
|
|
||||||
RestartSec=1
|
|
||||||
User=root
|
|
||||||
ExecStart=${CASA_BIN_PATH} -c ${CASA_CONF_PATH}
|
|
||||||
|
|
||||||
[Install]
|
|
||||||
WantedBy=multi-user.target
|
|
||||||
EOF
|
|
||||||
Show 0 "CasaOS service Successfully created."
|
|
||||||
}
|
|
||||||
|
|
||||||
# Start CasaOS
|
|
||||||
Start_CasaOS() {
|
|
||||||
Show 2 "Create a system startup service for CasaOS."
|
|
||||||
$sudo_cmd systemctl daemon-reload
|
|
||||||
$sudo_cmd systemctl enable ${CASA_BIN}
|
|
||||||
}
|
|
||||||
|
|
||||||
Check_Arch
|
|
||||||
|
|
||||||
# Step 7: Download CasaOS
|
|
||||||
Check_Exist
|
|
||||||
Download_CasaOS
|
|
||||||
|
|
||||||
# Step 8: Install Addon
|
|
||||||
Install_Addons
|
|
||||||
|
|
||||||
# Step 9: Install CasaOS
|
|
||||||
Install_CasaOS
|
|
||||||
|
|
||||||
# Step 10: Generate_Service
|
|
||||||
Generate_Service
|
|
||||||
|
|
||||||
# Step 11: Start CasaOS
|
|
||||||
Start_CasaOS
|
|
||||||
Clean_Temp_Files
|
|
||||||
@@ -1,15 +1,14 @@
|
|||||||
/*
|
/*@Author: LinkLeong link@icewhale.com
|
||||||
* @Author: LinkLeong link@icewhale.com
|
*@Date: 2022-02-17 18:53:22
|
||||||
* @Date: 2022-02-17 18:53:22
|
*@LastEditors: LinkLeong
|
||||||
* @LastEditors: LinkLeong
|
*@LastEditTime: 2022-09-06 14:27:42
|
||||||
* @LastEditTime: 2022-08-10 13:50:57
|
*@FilePath: /CasaOS/types/system.go
|
||||||
* @FilePath: /CasaOS/types/system.go
|
*@Description:
|
||||||
* @Description:
|
*@Website: https://www.casaos.io
|
||||||
* @Website: https://www.casaos.io
|
*Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
*/
|
||||||
package types
|
package types
|
||||||
|
|
||||||
const CURRENTVERSION = "0.3.5"
|
const CURRENTVERSION = "0.3.7"
|
||||||
|
|
||||||
const BODY = " "
|
const BODY = " "
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<browserconfig>
|
|
||||||
<msapplication>
|
|
||||||
<tile>
|
|
||||||
<square150x150logo src="/ui/img/icon/mstile-150x150.png"/>
|
|
||||||
<TileColor>#da532c</TileColor>
|
|
||||||
</tile>
|
|
||||||
</msapplication>
|
|
||||||
</browserconfig>
|
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
|
||||||
<!-- Generator: Adobe Illustrator 25.2.3, SVG Export Plug-In . SVG Version: 6.00 Build 0) -->
|
|
||||||
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px"
|
|
||||||
viewBox="0 0 24 24" style="enable-background:new 0 0 24 24;" xml:space="preserve">
|
|
||||||
<style type="text/css">
|
|
||||||
.st0{fill:none;stroke:#363636;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
|
|
||||||
@media ( prefers-color-scheme: dark ) {
|
|
||||||
.st0{fill:none;stroke:#FFFFFF;stroke-width:2;stroke-linejoin:round;stroke-miterlimit:2;}
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
<path class="st0" d="M12,22c5.5,0,10-4.5,10-10S17.5,2,12,2S2,6.5,2,12S6.5,22,12,22z"/>
|
|
||||||
<path class="st0" d="M12,22c3.9,0,7-3.1,7-7s-3.1-7-7-7s-7,3.1-7,7S8.1,22,12,22z"/>
|
|
||||||
<path class="st0" d="M12,22c2.2,0,4-1.8,4-4s-1.8-4-4-4s-4,1.8-4,4S9.8,22,12,22z"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 863 B |
@@ -1,55 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg width="64" height="64" version="1.1" viewBox="0 0 16.933 16.933" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<defs>
|
|
||||||
<linearGradient id="linearGradient1911" x1="25.085" x2="25.085" y1="24.031" y2="26.412" gradientTransform="translate(-35.822,-21.385)" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#fcbc19" stop-opacity=".99608" offset="0"/>
|
|
||||||
<stop stop-color="#f4b61f" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="linearGradient4625" x1=".52918" x2="16.404" y1="5.0665" y2="5.0665" gradientTransform="translate(-17.925)" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#b78815" offset="0"/>
|
|
||||||
<stop stop-color="#e2b24b" stop-opacity="0" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="linearGradient1951" x1="100" x2="133.19" y1="17.453" y2="51.606" gradientTransform="matrix(.26458 0 0 .26458 -38.033 -.13539)" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#fce798" offset="0"/>
|
|
||||||
<stop stop-color="#ffc937" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="linearGradient11110" x1=".52917" x2="16.404" y1="5.3815" y2="5.3815" gradientTransform="translate(-17.925)" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#fff" offset="0"/>
|
|
||||||
<stop stop-color="#fff" stop-opacity="0" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="linearGradient1119" x1="8.4665" x2="8.4665" y1="6.0853" y2="9.4879" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#fddb7a" offset="0"/>
|
|
||||||
<stop stop-color="#ffd970" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="linearGradient1284" x1="8.4665" x2="8.4665" y1="10.26" y2="13.229" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#ffd96e" offset="0"/>
|
|
||||||
<stop stop-color="#ffd561" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="linearGradient1272" x1="-3.9033" x2="-3.9033" y1="7.7839" y2="15.613" gradientTransform="translate(12.362 -2.1249)" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#c68d00" offset="0"/>
|
|
||||||
<stop stop-color="#a67100" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<metadata>
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<g transform="translate(17.925 4.2e-5)">
|
|
||||||
<path d="m-16.728 2.2489c-0.3653 0-0.66145 0.32575-0.66145 0.72759v2.9636c-0.0026 0.02629-0.0072 0.052-0.0072 0.07906v7.9373c0 0.40184 0.29614 0.72759 0.66144 0.72759h14.552c0.36531 0 0.66144-0.32575 0.66144-0.72759v-9.393c0-0.40184-0.29614-0.72759-0.66144-0.72759v5.16e-4h-8.1993l-0.89864-1.1095s-0.36607-0.478-1.0583-0.478h-1.3229z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="url(#linearGradient1911)" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stop-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;isolation:auto;mix-blend-mode:normal;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
|
|
||||||
<path d="m-9.5646 3.8364c-0.11312 0.0018-0.30848-0.01542-0.51986 0.09508-0.73647 0.37946-0.77226 0.59366-1.557 0.71415h-4.9608c-0.21986 0-0.41824 0.08855-0.56171 0.23202-0.13937 0.13936-0.22041 0.33333-0.2253 0.54569v0.2775c0.0049-0.21236 0.08593-0.40633 0.2253-0.54569 0.14347-0.14347 0.34185-0.23202 0.56171-0.23202h4.9608c0.78472-0.1205 0.82051-0.33469 1.557-0.71415 0.21138-0.1105 0.40673-0.09328 0.51986-0.09508h7.3828c0.18216 3.65e-4 0.3472 0.08101 0.46663 0.21239 0.1197 0.13167 0.19378 0.31377 0.19378 0.51469v-0.2775c0-0.20092-0.07408-0.38302-0.19378-0.51469-0.11943-0.13137-0.28447-0.21202-0.46663-0.21239h-1.1652zm-7.8247 2.1037c-0.0026 0.02629-0.0067 0.05201-0.0067 0.07906v0.2775c0-0.02705 0.0041-0.05277 0.0067-0.07906z" fill="url(#linearGradient4625)" opacity=".001" stroke-width=".26458"/>
|
|
||||||
<path d="m-17.396 13.674v0.28215c0 0.20092 0.07357 0.3825 0.19327 0.51417s0.28553 0.21342 0.46818 0.21342h14.552c0.18265 0 0.34796-0.08175 0.46766-0.21342s0.19378-0.31325 0.19378-0.51417v-0.28215c0 0.20092-0.07409 0.3825-0.19378 0.51417-0.1197 0.13167-0.28501 0.21342-0.46766 0.21342h-14.552c-0.18265 0-0.34848-0.08176-0.46818-0.21342s-0.19327-0.31325-0.19327-0.51417z" fill="#e4a729" fill-opacity=".99608" stroke-width=".26458"/>
|
|
||||||
<path d="m-10.383 4.0979s-0.35919 0.47868-1.1575 0.79218c-0.03271 0.00587-0.06509 0.011575-0.10077 0.017052h-4.9608c-0.21986 0-0.41824 0.088552-0.56171 0.23202-0.13937 0.13936-0.22042 0.33333-0.2253 0.54569v0.51675c-0.0026 0.02629-0.0067 0.05201-0.0067 0.07906v7.3953c0 0.20092 0.07357 0.3825 0.19327 0.51417s0.28553 0.21342 0.46818 0.21342h14.552c0.18265 0 0.34796-0.08175 0.46766-0.21342s0.19378-0.31325 0.19378-0.51417v-8.851c0-0.20092-0.07408-0.38302-0.19378-0.51469-0.11945-0.13137-0.28449-0.21202-0.46665-0.21239h-7.4821z" fill="url(#linearGradient1951)"/>
|
|
||||||
<path d="m-10.383 4.0979s-0.35919 0.47868-1.1575 0.79218c-0.03271 0.00587-0.06509 0.011575-0.10077 0.017052h-4.9608c-0.21986 0-0.41824 0.088552-0.56171 0.23202-0.13937 0.13936-0.22041 0.33333-0.2253 0.54569v0.38446c0.0049-0.21236 0.08593-0.40633 0.2253-0.54569 0.14347-0.14347 0.34185-0.23202 0.56171-0.23202h4.9608c0.03568-0.00548 0.06806-0.011184 0.10077-0.017052 0.75911-0.26303 1.2883-0.79218 1.2883-0.79218h8.0707c0.18216 3.704e-4 0.34718 0.081016 0.46663 0.21239 0.1197 0.13167 0.19378 0.31377 0.19378 0.51469v-0.38446c0-0.20092-0.07408-0.38302-0.19378-0.51469-0.11945-0.13137-0.28447-0.21202-0.46663-0.21239h-7.4821zm-7.0062 2.1037c-0.0026 0.02629-0.0067 0.05201-0.0067 0.07906v0.38446c0-0.02705 0.0041-0.05277 0.0067-0.07906z" fill="url(#linearGradient11110)" opacity=".3"/>
|
|
||||||
</g>
|
|
||||||
<circle cx="8.4665" cy="9.525" r="3.9687" fill="url(#linearGradient1272)" stroke-linecap="round" stroke-linejoin="round" stroke-width=".1726"/>
|
|
||||||
<g transform="matrix(.77756 0 0 .77756 10.567 2.0159)">
|
|
||||||
<g transform="matrix(1.0741 0 0 1.0741 -11.796 -.7153)">
|
|
||||||
<circle cx="8.4665" cy="7.8051" r="1.7198" fill="url(#linearGradient1119)" stroke-linecap="round" stroke-linejoin="round" stroke-width=".34395" style="paint-order:stroke fill markers"/>
|
|
||||||
<path d="m5.2916 11.064 5.4e-6 -0.14432c0-0.43295 0.43294-0.72158 0.72157-0.72158h4.9067c0.28863 0 0.72158 0.28863 0.72158 0.72158v0.14432c0 1.3096-1.416 2.1647-3.1749 2.1647-1.7589 0-3.1749-0.85514-3.1749-2.1647z" fill="url(#linearGradient1284)" stroke-width=".14049"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 6.7 KiB |
@@ -1,67 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?>
|
|
||||||
<svg width="64" height="64" version="1.1" viewBox="0 0 16.933 16.933" xmlns="http://www.w3.org/2000/svg" xmlns:cc="http://creativecommons.org/ns#" xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:rdf="http://www.w3.org/1999/02/22-rdf-syntax-ns#" xmlns:xlink="http://www.w3.org/1999/xlink">
|
|
||||||
<defs>
|
|
||||||
<style type="text/css"/>
|
|
||||||
<linearGradient id="linearGradient1951" x1="100" x2="133.19" y1="17.453" y2="51.606" gradientTransform="matrix(.26458 0 0 .24792 -20.108 .79576)" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#26abe7" offset="0"/>
|
|
||||||
<stop stop-color="#0669bc" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="linearGradient11110" x1=".52917" x2="16.404" y1="5.3815" y2="5.3815" gradientTransform="matrix(1 0 0 .93702 6.5e-7 .92263)" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#fff" offset="0"/>
|
|
||||||
<stop stop-color="#fff" stop-opacity="0" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="linearGradient1911" x1="25.085" x2="25.085" y1="24.031" y2="26.412" gradientTransform="translate(-17.897,-21.369)" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#0271ca" offset="0"/>
|
|
||||||
<stop stop-color="#0768ba" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="linearGradient9169" x1="7.4082" x2="7.4082" y1="4.2333" y2="5.5561" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#fff" offset="0"/>
|
|
||||||
<stop stop-color="#e3e4e5" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
<linearGradient id="linearGradient23227" x1=".52916" x2="16.404" y1="14.196" y2="14.196" gradientTransform="translate(-18.282 -.015458)" gradientUnits="userSpaceOnUse">
|
|
||||||
<stop stop-color="#0a5ba8" stop-opacity=".99608" offset="0"/>
|
|
||||||
<stop stop-color="#104a8c" stop-opacity=".99608" offset="1"/>
|
|
||||||
</linearGradient>
|
|
||||||
</defs>
|
|
||||||
<metadata>
|
|
||||||
<rdf:RDF>
|
|
||||||
<cc:Work rdf:about="">
|
|
||||||
<dc:format>image/svg+xml</dc:format>
|
|
||||||
<dc:type rdf:resource="http://purl.org/dc/dcmitype/StillImage"/>
|
|
||||||
</cc:Work>
|
|
||||||
</rdf:RDF>
|
|
||||||
</metadata>
|
|
||||||
<path d="m1.1977 2.2644c-0.3653 0-0.66145 0.32575-0.66145 0.72759v2.9636c-0.0026 0.02629-0.0072 0.052-0.0072 0.07906v7.9373c0 0.40184 0.29614 0.72759 0.66144 0.72759h14.552c0.36531 0 0.66144-0.32575 0.66144-0.72759v-9.393c0-0.40184-0.29614-0.72759-0.66144-0.72759v5.16e-4h-8.1993l-0.89864-1.1095s-0.36607-0.478-1.0583-0.478h-1.3229z" color="#000000" color-rendering="auto" dominant-baseline="auto" fill="url(#linearGradient1911)" image-rendering="auto" shape-rendering="auto" solid-color="#000000" stop-color="#000000" style="font-feature-settings:normal;font-variant-alternates:normal;font-variant-caps:normal;font-variant-east-asian:normal;font-variant-ligatures:normal;font-variant-numeric:normal;font-variant-position:normal;font-variation-settings:normal;inline-size:0;isolation:auto;mix-blend-mode:normal;shape-margin:0;shape-padding:0;text-decoration-color:#000000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-orientation:mixed;text-transform:none;white-space:normal"/>
|
|
||||||
<g fill="#5e4aa6" stroke-width=".26458">
|
|
||||||
<circle cx="-330.35" cy="-328.38" r="0"/>
|
|
||||||
<circle cx="-312.11" cy="-326.25" r="0"/>
|
|
||||||
<circle cx="-306.02" cy="-333.07" r="0"/>
|
|
||||||
<circle cx="-308.84" cy="-326.01" r="0"/>
|
|
||||||
<circle cx="-328.8" cy="-330.45" r="0"/>
|
|
||||||
<g transform="translate(24.108 -4.592)">
|
|
||||||
<circle cx="-330.35" cy="-328.38" r="0"/>
|
|
||||||
<circle cx="-312.11" cy="-326.25" r="0"/>
|
|
||||||
<circle cx="-306.02" cy="-333.07" r="0"/>
|
|
||||||
<circle cx="-308.84" cy="-326.01" r="0"/>
|
|
||||||
<circle cx="-328.8" cy="-330.45" r="0"/>
|
|
||||||
</g>
|
|
||||||
<g transform="translate(2.3479 -14.944)">
|
|
||||||
<circle cx="-330.35" cy="-328.38" r="0"/>
|
|
||||||
<circle cx="-312.11" cy="-326.25" r="0"/>
|
|
||||||
<circle cx="-306.02" cy="-333.07" r="0"/>
|
|
||||||
<circle cx="-308.84" cy="-326.01" r="0"/>
|
|
||||||
<circle cx="-328.8" cy="-330.45" r="0"/>
|
|
||||||
</g>
|
|
||||||
<g transform="translate(.000295 -.00036978)">
|
|
||||||
<circle cx="-330.35" cy="-328.38" r="0"/>
|
|
||||||
<circle cx="-312.11" cy="-326.25" r="0"/>
|
|
||||||
<circle cx="-306.02" cy="-333.07" r="0"/>
|
|
||||||
<circle cx="-308.84" cy="-326.01" r="0"/>
|
|
||||||
<circle cx="-328.8" cy="-330.45" r="0"/>
|
|
||||||
</g>
|
|
||||||
</g>
|
|
||||||
<path d="m0.52916 13.691v0.28215c0 0.20092 0.07357 0.3825 0.19327 0.51417s0.28553 0.21342 0.46818 0.21342h14.552c0.18265 0 0.34796-0.08175 0.46766-0.21342s0.19378-0.31325 0.19378-0.51417v-0.28215c0 0.20092-0.07409 0.3825-0.19378 0.51417-0.1197 0.13167-0.28501 0.21342-0.46766 0.21342h-14.552c-0.18265 0-0.34848-0.08176-0.46818-0.21342s-0.19327-0.31325-0.19327-0.51417z" fill="url(#linearGradient23227)" stroke-width=".26458"/>
|
|
||||||
<rect x=".79373" y="4.2333" width="15.346" height="8.9957" ry=".79373" fill="url(#linearGradient9169)" stroke-linecap="round" stroke-linejoin="round" stroke-width=".1077"/>
|
|
||||||
<path d="m7.542 4.7624s-0.35919 0.44853-1.1575 0.74229c-0.03271 0.0055-0.06509 0.010846-0.10077 0.015978h-5.4967c-0.21986 0-0.41824 0.082975-0.56171 0.21741-0.13937 0.13058-0.22042 0.31234-0.2253 0.51133v0.48421c0 0.02369-0.0021296 0.045593 0 0.073482l0.52916 6.9301c0.014339 0.18779 0.07357 0.35841 0.19327 0.48179s0.28553 0.19998 0.46818 0.19998h14.552c0.18265 0 0.34796-0.0766 0.46766-0.19998s0.18179-0.29386 0.19378-0.48179l0.52916-8.2935c0.011991-0.18793-0.07408-0.35889-0.19378-0.48227-0.11945-0.1231-0.28449-0.19866-0.46665-0.19901h-8.0112z" fill="url(#linearGradient1951)"/>
|
|
||||||
<path d="m7.542 4.7624s-0.35919 0.44853-1.1575 0.74229c-0.03271 0.0055-0.06509 0.010846-0.10077 0.015978h-5.49c-0.21986 0-0.41824 0.082975-0.56171 0.21741-0.13937 0.13058-0.22041 0.31234-0.2253 0.51132l-0.0067094 0.36074c0.0049-0.19899 0.092639-0.38123 0.23201-0.51181 0.14347-0.13443 0.34185-0.21741 0.56171-0.21741h5.49c0.03568-0.00513 0.06806-0.01048 0.10077-0.015978 0.75911-0.24646 1.2883-0.74229 1.2883-0.74229h8.5998c0.18216 3.471e-4 0.34718 0.075914 0.46663 0.19901 0.1197 0.12338 0.19378 0.29401 0.19378 0.48227v-0.36025c0-0.18827-0.07408-0.35889-0.19378-0.48227-0.11945-0.1231-0.28447-0.19866-0.46663-0.19901h-8.0112z" fill="url(#linearGradient11110)" opacity=".3"/>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 5.8 KiB |
|
Before Width: | Height: | Size: 12 KiB |
@@ -1 +0,0 @@
|
|||||||
<?xml version="1.0" encoding="UTF-8"?><svg width="24" height="24" viewBox="0 0 48 48" fill="none" xmlns="http://www.w3.org/2000/svg"><rect width="48" height="48" fill="white" fill-opacity="0.01"/><path d="M24 44C35.0457 44 44 35.0457 44 24C44 12.9543 35.0457 4 24 4C12.9543 4 4 12.9543 4 24C4 35.0457 12.9543 44 24 44Z" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M24 44C31.732 44 38 37.732 38 30C38 22.268 31.732 16 24 16C16.268 16 10 22.268 10 30C10 37.732 16.268 44 24 44Z" stroke="#333" stroke-width="4" stroke-linejoin="round"/><path d="M24 44C28.4183 44 32 40.4183 32 36C32 31.5817 28.4183 28 24 28C19.5817 28 16 31.5817 16 36C16 40.4183 19.5817 44 24 44Z" fill="none" stroke="#333" stroke-width="4" stroke-linejoin="round"/></svg>
|
|
||||||
|
Before Width: | Height: | Size: 758 B |
|
Before Width: | Height: | Size: 26 KiB |
|
Before Width: | Height: | Size: 11 KiB |
|
Before Width: | Height: | Size: 15 KiB |
|
Before Width: | Height: | Size: 9.7 KiB |
|
Before Width: | Height: | Size: 9.1 KiB |
|
Before Width: | Height: | Size: 693 B |
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 6.0 KiB |
@@ -1,25 +0,0 @@
|
|||||||
<?xml version="1.0" standalone="no"?>
|
|
||||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 20010904//EN"
|
|
||||||
"http://www.w3.org/TR/2001/REC-SVG-20010904/DTD/svg10.dtd">
|
|
||||||
<svg version="1.0" xmlns="http://www.w3.org/2000/svg"
|
|
||||||
width="200.000000pt" height="200.000000pt" viewBox="0 0 200.000000 200.000000"
|
|
||||||
preserveAspectRatio="xMidYMid meet">
|
|
||||||
<metadata>
|
|
||||||
Created by potrace 1.14, written by Peter Selinger 2001-2017
|
|
||||||
</metadata>
|
|
||||||
<g transform="translate(0.000000,200.000000) scale(0.100000,-0.100000)"
|
|
||||||
fill="#000000" stroke="none">
|
|
||||||
<path d="M875 1894 c-11 -2 -51 -11 -88 -20 -341 -78 -610 -364 -673 -714 -82
|
|
||||||
-459 197 -902 647 -1030 94 -27 277 -37 378 -21 303 47 575 261 690 540 55
|
|
||||||
133 66 192 65 361 -1 136 -4 165 -27 235 -36 116 -62 170 -123 261 -123 186
|
|
||||||
-347 336 -566 379 -42 8 -276 15 -303 9z m250 -168 c11 -2 42 -9 70 -16 131
|
|
||||||
-30 288 -135 387 -260 160 -201 198 -506 93 -745 l-22 -50 2 80 c3 180 -64
|
|
||||||
351 -184 476 -209 216 -544 260 -807 105 -201 -117 -326 -347 -319 -587 l2
|
|
||||||
-74 -19 44 c-63 140 -80 332 -44 476 24 94 87 219 147 292 109 133 290 238
|
|
||||||
448 259 25 3 47 7 49 9 5 4 173 -3 197 -9z m8 -501 c33 -8 85 -31 116 -50 227
|
|
||||||
-137 305 -418 183 -651 l-21 -39 -1 35 c-9 251 -245 439 -490 389 -186 -38
|
|
||||||
-323 -200 -330 -389 l-1 -35 -23 45 c-101 194 -61 429 99 578 130 122 292 162
|
|
||||||
468 117z m-27 -499 c182 -85 183 -345 1 -438 -53 -27 -161 -26 -215 1 -146 75
|
|
||||||
-180 267 -69 390 63 69 190 90 283 47z"/>
|
|
||||||
</g>
|
|
||||||
</svg>
|
|
||||||
|
Before Width: | Height: | Size: 1.3 KiB |
|
Before Width: | Height: | Size: 8.6 KiB |
@@ -1,34 +0,0 @@
|
|||||||
<!DOCTYPE html>
|
|
||||||
<html lang="">
|
|
||||||
|
|
||||||
<head>
|
|
||||||
<meta charset="utf-8">
|
|
||||||
<meta http-equiv="X-UA-Compatible" content="IE=edge">
|
|
||||||
<meta name="viewport" content="width=device-width,initial-scale=1">
|
|
||||||
<meta name="robots" content="noindex">
|
|
||||||
<script>
|
|
||||||
if (document.URL.indexOf("ui") === -1) {
|
|
||||||
window.location.replace("ui")
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
<link rel="apple-touch-icon" sizes="180x180" href="/ui/img/icon/apple-touch-icon.png">
|
|
||||||
<link rel="manifest" href="/ui/site.webmanifest">
|
|
||||||
<meta name="msapplication-TileColor" content="#da532c">
|
|
||||||
<meta name="theme-color" content="#ffffff">
|
|
||||||
<link rel="icon" href="/ui/favicon.svg" type="image/svg+xml">
|
|
||||||
|
|
||||||
<title>
|
|
||||||
CasaOS
|
|
||||||
</title>
|
|
||||||
<link href="/ui/css/13.a16d5119.css" rel="prefetch"><link href="/ui/css/14.cf8c898a.css" rel="prefetch"><link href="/ui/css/4.f17f9b01.css" rel="prefetch"><link href="/ui/css/5.e8438f80.css" rel="prefetch"><link href="/ui/css/6.d72d6157.css" rel="prefetch"><link href="/ui/css/7.805596b0.css" rel="prefetch"><link href="/ui/css/8.92188e4d.css" rel="prefetch"><link href="/ui/css/9.dccf29b4.css" rel="prefetch"><link href="/ui/js/0.js" rel="prefetch"><link href="/ui/js/1.js" rel="prefetch"><link href="/ui/js/10.js" rel="prefetch"><link href="/ui/js/11.js" rel="prefetch"><link href="/ui/js/12.js" rel="prefetch"><link href="/ui/js/13.js" rel="prefetch"><link href="/ui/js/14.js" rel="prefetch"><link href="/ui/js/15.js" rel="prefetch"><link href="/ui/js/2.js" rel="prefetch"><link href="/ui/js/3.js" rel="prefetch"><link href="/ui/js/4.js" rel="prefetch"><link href="/ui/js/5.js" rel="prefetch"><link href="/ui/js/6.js" rel="prefetch"><link href="/ui/js/7.js" rel="prefetch"><link href="/ui/js/8.js" rel="prefetch"><link href="/ui/js/9.js" rel="prefetch"><link href="/ui/css/app.c78d232d.css" rel="preload" as="style"><link href="/ui/css/vendors~app.c42f9a2b.css" rel="preload" as="style"><link href="/ui/js/app.js" rel="preload" as="script"><link href="/ui/js/vendors~app.js" rel="preload" as="script"><link href="/ui/css/vendors~app.c42f9a2b.css" rel="stylesheet"><link href="/ui/css/app.c78d232d.css" rel="stylesheet"></head>
|
|
||||||
|
|
||||||
<body>
|
|
||||||
<noscript>
|
|
||||||
<strong>We're sorry but CasaOS doesn't work properly without JavaScript enabled.
|
|
||||||
Please enable it to continue.</strong>
|
|
||||||
</noscript>
|
|
||||||
<div id="app"></div>
|
|
||||||
<!-- built files will be auto injected -->
|
|
||||||
<script type="text/javascript" src="/ui/js/vendors~app.js"></script><script type="text/javascript" src="/ui/js/app.js"></script></body>
|
|
||||||
|
|
||||||
</html>
|
|
||||||
37
web/js/0.js
21
web/js/1.js
21
web/js/10.js
21
web/js/11.js
21
web/js/12.js
13
web/js/13.js
@@ -1,5 +0,0 @@
|
|||||||
(window["webpackJsonp"]=window["webpackJsonp"]||[]).push([[14],{"./node_modules/vue-plyr/dist/vue-plyr.css":
|
|
||||||
/*!*************************************************!*\
|
|
||||||
!*** ./node_modules/vue-plyr/dist/vue-plyr.css ***!
|
|
||||||
\*************************************************/
|
|
||||||
/*! no static exports found */function(module,exports,__webpack_require__){eval("// extracted by mini-css-extract-plugin\n if(false) { var cssReload; }\n \n\n//# sourceURL=webpack:///./node_modules/vue-plyr/dist/vue-plyr.css?")}}]);
|
|
||||||