mirror of
https://github.com/IceWhaleTech/CasaOS.git
synced 2025-12-23 13:04:42 +00:00
Compare commits
26 Commits
v0.4.2
...
v0.4.3-alp
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
8c7c8dc1ec | ||
|
|
60a141fe25 | ||
|
|
02e712f649 | ||
|
|
7022cf5d29 | ||
|
|
6cf46ce50c | ||
|
|
202c1de570 | ||
|
|
858ab5b124 | ||
|
|
e319975a60 | ||
|
|
5c2c3b5e98 | ||
|
|
a0dc58264a | ||
|
|
717b47ca2c | ||
|
|
f530f69ba5 | ||
|
|
87b190a84b | ||
|
|
10191a1be3 | ||
|
|
59f2ccbeb3 | ||
|
|
076b7198b2 | ||
|
|
eb483a4c5d | ||
|
|
60e81bc781 | ||
|
|
dc8ee89c85 | ||
|
|
c995750312 | ||
|
|
de6ed093a2 | ||
|
|
449e1515d9 | ||
|
|
e6ddb0d849 | ||
|
|
c19e32c6e9 | ||
|
|
94755e221a | ||
|
|
86a3692dad |
53
.github/ISSUE_TEMPLATE/app_request.yml
vendored
53
.github/ISSUE_TEMPLATE/app_request.yml
vendored
@@ -1,53 +0,0 @@
|
|||||||
name: "App Request"
|
|
||||||
description: "Request to add an app to the app store."
|
|
||||||
title: "[App Request] AppName"
|
|
||||||
labels: ["App Request"]
|
|
||||||
body:
|
|
||||||
- type: markdown
|
|
||||||
attributes:
|
|
||||||
value: |
|
|
||||||
### ❤ Thanks for taking the time to fill out this app request!
|
|
||||||
> Before proceeding, please make sure that this app is not in App Store and no one has [requested](https://github.com/IceWhaleTech/CasaOS/labels/App%20Request) the same app before.
|
|
||||||
> If you have already requested the app, please ask your friends to help add a 👍 to this issue. Then be patient and wait for the developers to work on it.
|
|
||||||
> If you have any questions, please ask them on [Discord](https://discord.gg/knqAbbBbeX) or [Github Discussions](https://github.com/IceWhaleTech/CasaOS/discussions).
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: app-info
|
|
||||||
attributes:
|
|
||||||
label: "App Information"
|
|
||||||
description: "The formal information of this app, as detailed as possible."
|
|
||||||
value: |
|
|
||||||
- Name: <!-- eg. Nextcloud -->
|
|
||||||
- Short Description: <!-- eg. Personal cloud and file sharing solution -->
|
|
||||||
- Official Website: <!-- If available. eg. https://nextcloud.com -->
|
|
||||||
- GitHub Repository: <!-- If available. eg. https://github.com/nextcloud/server -->
|
|
||||||
- Docker Image: <!-- If available. eg. nextcloud/server:latest, ghcr.io/nextcloud/server:latest -->
|
|
||||||
validations:
|
|
||||||
required: true
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: why
|
|
||||||
attributes:
|
|
||||||
label: "Why do you want this app?"
|
|
||||||
description: "Detailed notes can help developers and others understand the importance of this app."
|
|
||||||
placeholder: |
|
|
||||||
As a [what role], it helps me solve [what problem], and especially [what function] is great!
|
|
||||||
or
|
|
||||||
It solves [what problem] and especially [what feature] works well, which is hard to do with other app.
|
|
||||||
or
|
|
||||||
This is the app that [some device/service] must use and will not work without it.
|
|
||||||
or
|
|
||||||
others
|
|
||||||
|
|
||||||
- type: textarea
|
|
||||||
id: additional-info
|
|
||||||
attributes:
|
|
||||||
label: "Additional information?"
|
|
||||||
description: "Anything else you want to share with the developers and others?"
|
|
||||||
placeholder: |
|
|
||||||
Example:
|
|
||||||
- Noteworthy matters.
|
|
||||||
- Recommended Docker image.
|
|
||||||
- Validated Docker deployment instructions.
|
|
||||||
- Notable Docker setup details.
|
|
||||||
- Recommended config files, user data, accessible directory settings.
|
|
||||||
5
.github/ISSUE_TEMPLATE/config.yml
vendored
5
.github/ISSUE_TEMPLATE/config.yml
vendored
@@ -1,5 +1,8 @@
|
|||||||
blank_issues_enabled: false
|
blank_issues_enabled: false
|
||||||
contact_links:
|
contact_links:
|
||||||
|
- name: App Request
|
||||||
|
url: https://github.com/IceWhaleTech/CasaOS-AppStore/issues/new?assignees=&labels=App+Request&template=app_request.yml&title=%5BApp+Request%5D+AppName
|
||||||
|
about: Request to add an app to the app store.
|
||||||
- name: Feature/Enhancement Ideas
|
- name: Feature/Enhancement Ideas
|
||||||
url: https://github.com/IceWhaleTech/CasaOS/discussions/164
|
url: https://github.com/IceWhaleTech/CasaOS/discussions/164
|
||||||
about: Have an idea for a new feature/enhancement?
|
about: Have an idea for a new feature/enhancement?
|
||||||
@@ -8,4 +11,4 @@ contact_links:
|
|||||||
about: Ask questions, propose ideas, or discuss anything related to CasaOS
|
about: Ask questions, propose ideas, or discuss anything related to CasaOS
|
||||||
- name: Discord
|
- name: Discord
|
||||||
url: https://discord.gg/knqAbbBbeX
|
url: https://discord.gg/knqAbbBbeX
|
||||||
about: Get help or share great ideas on Discord!
|
about: Get help or share great ideas on Discord!
|
||||||
|
|||||||
4
.github/workflows/casa.yml
vendored
4
.github/workflows/casa.yml
vendored
@@ -40,7 +40,7 @@ jobs:
|
|||||||
# env:
|
# env:
|
||||||
# GITHUB_TOKEN: ${{ github.token }}
|
# GITHUB_TOKEN: ${{ github.token }}
|
||||||
|
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
submodules: true
|
submodules: true
|
||||||
@@ -73,7 +73,7 @@ jobs:
|
|||||||
|
|
||||||
|
|
||||||
- name: Use Node.js
|
- name: Use Node.js
|
||||||
uses: actions/setup-node@v2
|
uses: actions/setup-node@v3
|
||||||
with:
|
with:
|
||||||
node-version: '14'
|
node-version: '14'
|
||||||
|
|
||||||
|
|||||||
8
.github/workflows/codecov.yml
vendored
8
.github/workflows/codecov.yml
vendored
@@ -13,10 +13,14 @@ jobs:
|
|||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
- name: Checkout
|
- name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
|
- name: Set up Go
|
||||||
|
uses: actions/setup-go@v4
|
||||||
|
with:
|
||||||
|
go-version: "1.20"
|
||||||
- name: Run coverage
|
- name: Run coverage
|
||||||
run: go test -race -failfast -coverprofile=coverage.txt -covermode=atomic -v ./...
|
run: go test -race -failfast -coverprofile=coverage.txt -covermode=atomic -v ./...
|
||||||
- name: Upload coverage to Codecov
|
- name: Upload coverage to Codecov
|
||||||
uses: codecov/codecov-action@v3
|
uses: codecov/codecov-action@v3
|
||||||
|
|||||||
2
.github/workflows/demo.yml
vendored
2
.github/workflows/demo.yml
vendored
@@ -22,7 +22,7 @@ jobs:
|
|||||||
# Steps represent a sequence of tasks that will be executed as part of the job
|
# Steps represent a sequence of tasks that will be executed as part of the job
|
||||||
steps:
|
steps:
|
||||||
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
# Checks-out your repository under $GITHUB_WORKSPACE, so your job can access it
|
||||||
- uses: actions/checkout@v2
|
- uses: actions/checkout@v3
|
||||||
|
|
||||||
- name: Configure AWS credentials from Test account
|
- name: Configure AWS credentials from Test account
|
||||||
uses: aws-actions/configure-aws-credentials@v1
|
uses: aws-actions/configure-aws-credentials@v1
|
||||||
|
|||||||
8
.github/workflows/push_test_server.yml
vendored
8
.github/workflows/push_test_server.yml
vendored
@@ -11,7 +11,7 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
-
|
-
|
||||||
name: Checkout
|
name: Checkout
|
||||||
uses: actions/checkout@v2
|
uses: actions/checkout@v3
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
- name: isntall git
|
- name: isntall git
|
||||||
@@ -35,12 +35,12 @@ jobs:
|
|||||||
run: echo ${{env.VERSION}}
|
run: echo ${{env.VERSION}}
|
||||||
|
|
||||||
- name: Set up Go
|
- name: Set up Go
|
||||||
uses: actions/setup-go@v2
|
uses: actions/setup-go@v4
|
||||||
with:
|
with:
|
||||||
go-version: 1.19
|
go-version: 'stable'
|
||||||
|
|
||||||
- name: Run GoReleaser
|
- name: Run GoReleaser
|
||||||
uses: goreleaser/goreleaser-action@v2
|
uses: goreleaser/goreleaser-action@v4
|
||||||
with:
|
with:
|
||||||
# either 'goreleaser' (default) or 'goreleaser-pro'
|
# either 'goreleaser' (default) or 'goreleaser-pro'
|
||||||
distribution: goreleaser
|
distribution: goreleaser
|
||||||
|
|||||||
30
.github/workflows/release.yml
vendored
30
.github/workflows/release.yml
vendored
@@ -12,34 +12,29 @@ jobs:
|
|||||||
goreleaser:
|
goreleaser:
|
||||||
runs-on: ubuntu-22.04
|
runs-on: ubuntu-22.04
|
||||||
steps:
|
steps:
|
||||||
-
|
- name: Install dependencies for cross-compiling
|
||||||
name: Install dependencies for cross-compiling
|
|
||||||
run: |
|
run: |
|
||||||
sudo apt update
|
sudo apt update
|
||||||
sudo apt-get --no-install-recommends --yes install \
|
sudo apt-get --no-install-recommends --yes install \
|
||||||
upx libc6-dev-amd64-cross \
|
upx libc6-dev-amd64-cross \
|
||||||
gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
|
gcc-aarch64-linux-gnu libc6-dev-arm64-cross \
|
||||||
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross
|
gcc-arm-linux-gnueabihf libc6-dev-armhf-cross
|
||||||
-
|
- name: Checkout
|
||||||
name: Checkout
|
uses: actions/checkout@v3
|
||||||
uses: actions/checkout@v2
|
|
||||||
with:
|
with:
|
||||||
fetch-depth: 0
|
fetch-depth: 0
|
||||||
-
|
- name: Fetch all tags
|
||||||
name: Fetch all tags
|
|
||||||
run: git fetch --force --tags
|
run: git fetch --force --tags
|
||||||
|
|
||||||
- name: Get version
|
- name: Get version
|
||||||
id: get_version
|
id: get_version
|
||||||
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
|
run: echo ::set-output name=VERSION::${GITHUB_REF/refs\/tags\//}
|
||||||
-
|
- name: Set up Go
|
||||||
name: Set up Go
|
uses: actions/setup-go@v4
|
||||||
uses: actions/setup-go@v2
|
|
||||||
with:
|
with:
|
||||||
go-version: 1.19
|
go-version: "1.20"
|
||||||
-
|
- name: Run GoReleaser
|
||||||
name: Run GoReleaser
|
uses: goreleaser/goreleaser-action@v4
|
||||||
uses: goreleaser/goreleaser-action@v2
|
|
||||||
with:
|
with:
|
||||||
# either 'goreleaser' (default) or 'goreleaser-pro'
|
# either 'goreleaser' (default) or 'goreleaser-pro'
|
||||||
distribution: goreleaser
|
distribution: goreleaser
|
||||||
@@ -49,7 +44,7 @@ jobs:
|
|||||||
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
||||||
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
|
# Your GoReleaser Pro key, if you are using the 'goreleaser-pro' distribution
|
||||||
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
# GORELEASER_KEY: ${{ secrets.GORELEASER_KEY }}
|
||||||
|
|
||||||
- name: Upload to oss
|
- name: Upload to oss
|
||||||
id: upload_to_oss
|
id: upload_to_oss
|
||||||
uses: tvrcgo/upload-to-oss@master
|
uses: tvrcgo/upload-to-oss@master
|
||||||
@@ -66,6 +61,3 @@ jobs:
|
|||||||
dist/linux-arm-7-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm-7-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
dist/linux-arm-7-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm-7-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
dist/linux-arm64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
dist/linux-arm64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-arm64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
dist/linux-amd64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-amd64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
dist/linux-amd64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz:/IceWhaleTech/CasaOS/releases/download/${{ steps.get_version.outputs.VERSION }}/linux-amd64-casaos-migration-tool-${{ steps.get_version.outputs.VERSION }}.tar.gz
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
20
CHANGELOG.md
20
CHANGELOG.md
@@ -16,6 +16,26 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||||||
|
|
||||||
### Security
|
### Security
|
||||||
|
|
||||||
|
## [0.4.3]
|
||||||
|
|
||||||
|
### Added
|
||||||
|
|
||||||
|
- [Disk] Now usb also supports merging to
|
||||||
|
|
||||||
|
|
||||||
|
### Changed
|
||||||
|
|
||||||
|
- [File] Solve the installation dependency problem, make the installation more smoothly
|
||||||
|
- [File] Change the default permissions of the sharing folder
|
||||||
|
|
||||||
|
### Fixed
|
||||||
|
|
||||||
|
- [System] Fixed not see wlan iface ([#909](https://github.com/IceWhaleTech/CasaOS/issues/909))
|
||||||
|
- [System] Terminal font issue fix ([#929](https://github.com/IceWhaleTech/CasaOS/issues/929))
|
||||||
|
- [File] Fixed the problem of not being able to launch after mounting
|
||||||
|
|
||||||
|
### Removed
|
||||||
|
|
||||||
|
|
||||||
## [0.4.2]
|
## [0.4.2]
|
||||||
|
|
||||||
|
|||||||
9
SECURITY.md
Normal file
9
SECURITY.md
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
# Security Policy
|
||||||
|
|
||||||
|
## Supported Versions
|
||||||
|
|
||||||
|
CasaOS is currently under active development. Support is limited before CasaOS reaches v1.0.
|
||||||
|
|
||||||
|
## Reporting a Vulnerability
|
||||||
|
|
||||||
|
If you see any vulnerabiility, email us at wiki@casaos.io
|
||||||
@@ -1,3 +1,3 @@
|
|||||||
LEGACY_WITHOUT_VERSION ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
LEGACY_WITHOUT_VERSION ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
v0.3.5 ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
v0.3.5 ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
v0.3.5.1 ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
v0.3.5.1 ${DOWNLOAD_DOMAIN}IceWhaleTech/CasaOS/releases/download/v0.3.6/linux-${ARCH}-casaos-migration-tool-v0.3.6.tar.gz
|
||||||
|
|||||||
@@ -25,7 +25,7 @@ GetNetCard() {
|
|||||||
fi
|
fi
|
||||||
else
|
else
|
||||||
if [ -d "/sys/devices/virtual/net" ] && [ -d "/sys/class/net" ]; then
|
if [ -d "/sys/devices/virtual/net" ] && [ -d "/sys/class/net" ]; then
|
||||||
ls /sys/class/net/ | grep -v "$(ls /sys/devices/virtual/net/)"
|
ls /sys/class/net/ | grep -v "$(ls /sys/devices/virtual/net/)" -w
|
||||||
fi
|
fi
|
||||||
fi
|
fi
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,46 +1,13 @@
|
|||||||
/*
|
|
||||||
* @Author: LinkLeong link@icewhale.org
|
|
||||||
* @Date: 2022-08-24 17:36:00
|
|
||||||
* @LastEditors: LinkLeong
|
|
||||||
* @LastEditTime: 2022-09-05 11:24:27
|
|
||||||
* @FilePath: /CasaOS/cmd/migration-tool/migration-034-035.go
|
|
||||||
* @Description:
|
|
||||||
* @Website: https://www.casaos.io
|
|
||||||
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
|
||||||
*/
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
interfaces "github.com/IceWhaleTech/CasaOS-Common"
|
interfaces "github.com/IceWhaleTech/CasaOS-Common"
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/version"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type migrationTool struct{}
|
type migrationTool struct{}
|
||||||
|
|
||||||
func (u *migrationTool) IsMigrationNeeded() (bool, error) {
|
func (u *migrationTool) IsMigrationNeeded() (bool, error) {
|
||||||
majorVersion, minorVersion, patchVersion, err := version.DetectLegacyVersion()
|
return false, nil
|
||||||
if err != nil {
|
|
||||||
if err == version.ErrLegacyVersionNotFound {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
return false, err
|
|
||||||
}
|
|
||||||
|
|
||||||
if majorVersion > 0 {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if minorVersion > 3 {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
if minorVersion == 3 && patchVersion > 5 {
|
|
||||||
return false, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
_logger.Info("Migration is needed for a CasaOS version 0.3.5 and older...")
|
|
||||||
return true, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (u *migrationTool) PreMigrate() error {
|
func (u *migrationTool) PreMigrate() error {
|
||||||
|
|||||||
@@ -14,7 +14,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type Dropbox struct {
|
type Dropbox struct {
|
||||||
model.Storage
|
model.StorageA
|
||||||
Addition
|
Addition
|
||||||
AccessToken string
|
AccessToken string
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -17,7 +17,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type GoogleDrive struct {
|
type GoogleDrive struct {
|
||||||
model.Storage
|
model.StorageA
|
||||||
Addition
|
Addition
|
||||||
AccessToken string
|
AccessToken string
|
||||||
}
|
}
|
||||||
|
|||||||
121
go.mod
121
go.mod
@@ -1,130 +1,133 @@
|
|||||||
module github.com/IceWhaleTech/CasaOS
|
module github.com/IceWhaleTech/CasaOS
|
||||||
|
|
||||||
go 1.19
|
go 1.20
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
|
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d
|
||||||
github.com/IceWhaleTech/CasaOS-Common v0.4.2-alpha3
|
github.com/IceWhaleTech/CasaOS-Common v0.4.2-alpha3
|
||||||
github.com/Xhofe/go-cache v0.0.0-20220723083548-714439c8af9a
|
|
||||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf
|
||||||
github.com/deckarep/golang-set/v2 v2.1.0
|
github.com/deckarep/golang-set/v2 v2.3.0
|
||||||
github.com/deepmap/oapi-codegen v1.12.4
|
github.com/deepmap/oapi-codegen v1.12.4
|
||||||
github.com/disintegration/imaging v1.6.2
|
github.com/disintegration/imaging v1.6.2
|
||||||
github.com/dsoprea/go-exif/v3 v3.0.0-20221012082141-d21ac8e2de85
|
github.com/dsoprea/go-exif/v3 v3.0.0-20221012082141-d21ac8e2de85
|
||||||
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd
|
github.com/getkin/kin-openapi v0.115.0
|
||||||
github.com/getkin/kin-openapi v0.113.0
|
|
||||||
github.com/gin-contrib/gzip v0.0.6
|
github.com/gin-contrib/gzip v0.0.6
|
||||||
github.com/gin-gonic/gin v1.8.2
|
github.com/gin-gonic/gin v1.9.0
|
||||||
github.com/glebarez/sqlite v1.6.0
|
github.com/glebarez/sqlite v1.7.0
|
||||||
github.com/go-ini/ini v1.67.0
|
github.com/go-ini/ini v1.67.0
|
||||||
github.com/go-resty/resty/v2 v2.7.0
|
github.com/go-resty/resty/v2 v2.7.0
|
||||||
github.com/golang/mock v1.6.0
|
github.com/golang/mock v1.6.0
|
||||||
github.com/gomodule/redigo v1.8.9
|
github.com/gomodule/redigo v1.8.9
|
||||||
github.com/google/go-github/v36 v36.0.0
|
github.com/google/go-github/v36 v36.0.0
|
||||||
github.com/googollee/go-socket.io v1.6.2
|
github.com/googollee/go-socket.io v1.7.0
|
||||||
github.com/gorilla/websocket v1.5.0
|
github.com/gorilla/websocket v1.5.0
|
||||||
github.com/h2non/filetype v1.1.3
|
github.com/h2non/filetype v1.1.3
|
||||||
github.com/hirochachacha/go-smb2 v1.1.0
|
github.com/hirochachacha/go-smb2 v1.1.0
|
||||||
github.com/json-iterator/go v1.1.12
|
github.com/json-iterator/go v1.1.12
|
||||||
github.com/labstack/echo/v4 v4.10.0
|
github.com/labstack/echo/v4 v4.10.2
|
||||||
github.com/maruel/natural v1.1.0
|
github.com/maruel/natural v1.1.0
|
||||||
github.com/mholt/archiver/v3 v3.5.1
|
github.com/mholt/archiver/v3 v3.5.1
|
||||||
|
github.com/mileusna/useragent v1.2.1
|
||||||
github.com/moby/sys/mount v0.3.3
|
github.com/moby/sys/mount v0.3.3
|
||||||
github.com/moby/sys/mountinfo v0.6.2
|
github.com/moby/sys/mountinfo v0.6.2
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible
|
github.com/patrickmn/go-cache v2.1.0+incompatible
|
||||||
github.com/pkg/errors v0.9.1
|
github.com/pkg/errors v0.9.1
|
||||||
github.com/robfig/cron v1.2.0
|
github.com/robfig/cron/v3 v3.0.1
|
||||||
github.com/satori/go.uuid v1.2.0
|
github.com/satori/go.uuid v1.2.0
|
||||||
github.com/shirou/gopsutil/v3 v3.22.11
|
github.com/shirou/gopsutil/v3 v3.23.2
|
||||||
github.com/sirupsen/logrus v1.9.0
|
github.com/sirupsen/logrus v1.9.0
|
||||||
github.com/stretchr/testify v1.8.1
|
|
||||||
github.com/tidwall/gjson v1.14.4
|
github.com/tidwall/gjson v1.14.4
|
||||||
|
go.uber.org/goleak v1.2.1
|
||||||
go.uber.org/zap v1.24.0
|
go.uber.org/zap v1.24.0
|
||||||
golang.org/x/crypto v0.5.0
|
golang.org/x/crypto v0.7.0
|
||||||
golang.org/x/oauth2 v0.3.0
|
golang.org/x/oauth2 v0.6.0
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c
|
golang.org/x/sync v0.1.0
|
||||||
gorm.io/gorm v1.24.3
|
gorm.io/gorm v1.24.6
|
||||||
gotest.tools v2.2.0+incompatible
|
gotest.tools v2.2.0+incompatible
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
github.com/andybalholm/brotli v1.0.1 // indirect
|
github.com/andybalholm/brotli v1.0.5 // indirect
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
|
||||||
github.com/benbjohnson/clock v1.3.0 // indirect
|
github.com/benbjohnson/clock v1.3.0 // indirect
|
||||||
github.com/coreos/go-systemd/v22 v22.3.2 // indirect
|
github.com/bytedance/sonic v1.8.5 // indirect
|
||||||
github.com/davecgh/go-spew v1.1.1 // indirect
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 // indirect
|
||||||
|
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||||
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
github.com/dsnet/compress v0.0.2-0.20210315054119-f66993602bf5 // indirect
|
||||||
|
github.com/dsoprea/go-logging v0.0.0-20200710184922-b02d349568dd // indirect
|
||||||
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
|
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 // indirect
|
||||||
|
github.com/dustin/go-humanize v1.0.1 // indirect
|
||||||
github.com/geoffgarside/ber v1.1.0 // indirect
|
github.com/geoffgarside/ber v1.1.0 // indirect
|
||||||
github.com/gin-contrib/sse v0.1.0 // indirect
|
github.com/gin-contrib/sse v0.1.0 // indirect
|
||||||
github.com/glebarez/go-sqlite v1.20.0 // indirect
|
github.com/glebarez/go-sqlite v1.21.0 // indirect
|
||||||
github.com/go-errors/errors v1.4.2 // indirect
|
github.com/go-errors/errors v1.4.2 // indirect
|
||||||
github.com/go-ole/go-ole v1.2.6 // indirect
|
github.com/go-ole/go-ole v1.2.6 // indirect
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 // indirect
|
github.com/go-openapi/jsonpointer v0.19.6 // indirect
|
||||||
github.com/go-openapi/swag v0.21.1 // indirect
|
github.com/go-openapi/swag v0.22.3 // indirect
|
||||||
github.com/go-playground/locales v0.14.0 // indirect
|
github.com/go-playground/locales v0.14.1 // indirect
|
||||||
github.com/go-playground/universal-translator v0.18.0 // indirect
|
github.com/go-playground/universal-translator v0.18.1 // indirect
|
||||||
github.com/go-playground/validator/v10 v10.11.1 // indirect
|
github.com/go-playground/validator/v10 v10.11.2 // indirect
|
||||||
github.com/goccy/go-json v0.9.11 // indirect
|
github.com/goccy/go-json v0.10.1 // indirect
|
||||||
github.com/godbus/dbus/v5 v5.0.4 // indirect
|
github.com/godbus/dbus/v5 v5.1.0 // indirect
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible // indirect
|
github.com/gofrs/uuid v4.4.0+incompatible // indirect
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
github.com/golang-jwt/jwt v3.2.2+incompatible // indirect
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.2 // indirect
|
github.com/golang-jwt/jwt/v4 v4.5.0 // indirect
|
||||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
|
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 // indirect
|
||||||
github.com/golang/protobuf v1.5.2 // indirect
|
github.com/golang/protobuf v1.5.3 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/google/go-cmp v0.5.9 // indirect
|
github.com/google/go-cmp v0.5.9 // indirect
|
||||||
github.com/google/go-querystring v1.0.0 // indirect
|
github.com/google/go-querystring v1.1.0 // indirect
|
||||||
github.com/google/uuid v1.3.0 // indirect
|
github.com/google/uuid v1.3.0 // indirect
|
||||||
github.com/gorilla/mux v1.8.0 // indirect
|
github.com/gorilla/mux v1.8.0 // indirect
|
||||||
github.com/invopop/yaml v0.1.0 // indirect
|
github.com/invopop/yaml v0.2.0 // indirect
|
||||||
github.com/jinzhu/inflection v1.0.0 // indirect
|
github.com/jinzhu/inflection v1.0.0 // indirect
|
||||||
github.com/jinzhu/now v1.1.5 // indirect
|
github.com/jinzhu/now v1.1.5 // indirect
|
||||||
github.com/josharian/intern v1.0.0 // indirect
|
github.com/josharian/intern v1.0.0 // indirect
|
||||||
github.com/klauspost/compress v1.15.13 // indirect
|
github.com/klauspost/compress v1.16.3 // indirect
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.4 // indirect
|
||||||
github.com/klauspost/pgzip v1.2.5 // indirect
|
github.com/klauspost/pgzip v1.2.5 // indirect
|
||||||
|
github.com/kr/pretty v0.3.1 // indirect
|
||||||
github.com/labstack/gommon v0.4.0 // indirect
|
github.com/labstack/gommon v0.4.0 // indirect
|
||||||
github.com/leodido/go-urn v1.2.1 // indirect
|
github.com/leodido/go-urn v1.2.2 // indirect
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 // indirect
|
github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de // indirect
|
||||||
github.com/mailru/easyjson v0.7.7 // indirect
|
github.com/mailru/easyjson v0.7.7 // indirect
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.16 // indirect
|
github.com/mattn/go-isatty v0.0.17 // indirect
|
||||||
github.com/mattn/go-sqlite3 v1.14.15 // indirect
|
|
||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
|
||||||
github.com/modern-go/reflect2 v1.0.2 // indirect
|
github.com/modern-go/reflect2 v1.0.2 // indirect
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
|
||||||
github.com/nwaples/rardecode v1.1.0 // indirect
|
github.com/nwaples/rardecode v1.1.3 // indirect
|
||||||
github.com/pelletier/go-toml/v2 v2.0.6 // indirect
|
github.com/pelletier/go-toml/v2 v2.0.7 // indirect
|
||||||
github.com/perimeterx/marshmallow v1.1.4 // indirect
|
github.com/perimeterx/marshmallow v1.1.4 // indirect
|
||||||
github.com/pierrec/lz4/v4 v4.1.2 // indirect
|
github.com/pierrec/lz4/v4 v4.1.17 // indirect
|
||||||
github.com/pmezard/go-difflib v1.0.0 // indirect
|
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b // indirect
|
||||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c // indirect
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec // indirect
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 // indirect
|
|
||||||
github.com/tidwall/match v1.1.1 // indirect
|
github.com/tidwall/match v1.1.1 // indirect
|
||||||
github.com/tidwall/pretty v1.2.0 // indirect
|
github.com/tidwall/pretty v1.2.1 // indirect
|
||||||
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
github.com/tklauser/go-sysconf v0.3.11 // indirect
|
||||||
github.com/tklauser/numcpus v0.6.0 // indirect
|
github.com/tklauser/numcpus v0.6.0 // indirect
|
||||||
github.com/ugorji/go/codec v1.2.7 // indirect
|
github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
|
||||||
github.com/ulikunitz/xz v0.5.9 // indirect
|
github.com/ugorji/go/codec v1.2.11 // indirect
|
||||||
|
github.com/ulikunitz/xz v0.5.11 // indirect
|
||||||
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
github.com/valyala/bytebufferpool v1.0.0 // indirect
|
||||||
github.com/valyala/fasttemplate v1.2.2 // indirect
|
github.com/valyala/fasttemplate v1.2.2 // indirect
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 // indirect
|
||||||
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
github.com/yusufpapurcu/wmi v1.2.2 // indirect
|
||||||
go.uber.org/atomic v1.7.0 // indirect
|
go.uber.org/atomic v1.10.0 // indirect
|
||||||
go.uber.org/multierr v1.6.0 // indirect
|
go.uber.org/multierr v1.10.0 // indirect
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 // indirect
|
golang.org/x/arch v0.3.0 // indirect
|
||||||
golang.org/x/net v0.5.0 // indirect
|
golang.org/x/image v0.6.0 // indirect
|
||||||
golang.org/x/sys v0.4.0 // indirect
|
golang.org/x/net v0.8.0 // indirect
|
||||||
golang.org/x/text v0.6.0 // indirect
|
golang.org/x/sys v0.6.0 // indirect
|
||||||
golang.org/x/time v0.2.0 // indirect
|
golang.org/x/text v0.8.0 // indirect
|
||||||
|
golang.org/x/time v0.3.0 // indirect
|
||||||
google.golang.org/appengine v1.6.7 // indirect
|
google.golang.org/appengine v1.6.7 // indirect
|
||||||
google.golang.org/protobuf v1.28.1 // indirect
|
google.golang.org/protobuf v1.30.0 // indirect
|
||||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 // indirect
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 // indirect
|
|
||||||
gopkg.in/yaml.v2 v2.4.0 // indirect
|
gopkg.in/yaml.v2 v2.4.0 // indirect
|
||||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||||
modernc.org/libc v1.21.5 // indirect
|
modernc.org/libc v1.22.3 // indirect
|
||||||
modernc.org/mathutil v1.5.0 // indirect
|
modernc.org/mathutil v1.5.0 // indirect
|
||||||
modernc.org/memory v1.4.0 // indirect
|
modernc.org/memory v1.5.0 // indirect
|
||||||
modernc.org/sqlite v1.20.0 // indirect
|
modernc.org/sqlite v1.21.0 // indirect
|
||||||
)
|
)
|
||||||
|
|||||||
291
go.sum
291
go.sum
@@ -1,31 +1,32 @@
|
|||||||
github.com/BurntSushi/toml v1.2.0 h1:Rt8g24XnyGTyglgET/PRUNlrUeu9F5L+7FilkXfZgs0=
|
|
||||||
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d h1:62lEBImTxZ83pgzywgDNIrPPuQ+j4ep9QjqrWBn1hrU=
|
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d h1:62lEBImTxZ83pgzywgDNIrPPuQ+j4ep9QjqrWBn1hrU=
|
||||||
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ=
|
github.com/Curtis-Milo/nat-type-identifier-go v0.0.0-20220215191915-18d42168c63d/go.mod h1:lW9x+yEjqKdPbE3+cf2fGPJXCw/hChX3Omi9QHTLFsQ=
|
||||||
github.com/IceWhaleTech/CasaOS-Common v0.4.2-alpha3 h1:WJUYo+hJpLmza7mQngoJVeUJOfnrZevNrX5wzTuOJo0=
|
github.com/IceWhaleTech/CasaOS-Common v0.4.2-alpha3 h1:WJUYo+hJpLmza7mQngoJVeUJOfnrZevNrX5wzTuOJo0=
|
||||||
github.com/IceWhaleTech/CasaOS-Common v0.4.2-alpha3/go.mod h1:xcemiRsXcs1zrmQxYMyExDjZ7UHYwkJqYE71IDIV0xA=
|
github.com/IceWhaleTech/CasaOS-Common v0.4.2-alpha3/go.mod h1:xcemiRsXcs1zrmQxYMyExDjZ7UHYwkJqYE71IDIV0xA=
|
||||||
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
|
||||||
github.com/Xhofe/go-cache v0.0.0-20220723083548-714439c8af9a h1:RenIAa2q4H8UcS/cqmwdT1WCWIAH5aumP8m8RpbqVsE=
|
|
||||||
github.com/Xhofe/go-cache v0.0.0-20220723083548-714439c8af9a/go.mod h1:sSBbaOg90XwWKtpT56kVujF0bIeVITnPlssLclogS04=
|
|
||||||
github.com/andybalholm/brotli v1.0.1 h1:KqhlKozYbRtJvsPrrEeXcO+N2l6NYT5A2QAFmSULpEc=
|
|
||||||
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
github.com/andybalholm/brotli v1.0.1/go.mod h1:loMXtMfwqflxFJPmdbJO0a3KNoPuLBgiu3qAvBg8x/Y=
|
||||||
|
github.com/andybalholm/brotli v1.0.5 h1:8uQZIdzKmjc/iuPu7O2ioW48L81FgatrcpfFmiq/cCs=
|
||||||
|
github.com/andybalholm/brotli v1.0.5/go.mod h1:fO7iG3H7G2nSZ7m0zPUDn85XEX2GTukHGRSepvi9Eig=
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
|
||||||
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
|
||||||
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
github.com/benbjohnson/clock v1.3.0 h1:ip6w0uFQkncKQ979AypyG0ER7mqUSBdKLOgAle/AT8A=
|
||||||
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
github.com/benbjohnson/clock v1.3.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
|
||||||
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
|
github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
|
||||||
github.com/chzyer/logex v1.2.0/go.mod h1:9+9sk7u7pGNWYMkh0hdiL++6OeibzJccyQU4p4MedaY=
|
github.com/bytedance/sonic v1.5.0/go.mod h1:ED5hyg4y6t3/9Ku1R6dU/4KyJ48DZ4jPhfY1O2AihPM=
|
||||||
github.com/chzyer/readline v1.5.0/go.mod h1:x22KAscuvRqlLoK9CsoYsmxoXZMMFVyOl86cAH8qUic=
|
github.com/bytedance/sonic v1.8.5 h1:kjX0/vo5acEQ/sinD/18SkA/lDDUk23F0RcaHvI7omc=
|
||||||
github.com/chzyer/test v0.0.0-20210722231415-061457976a23/go.mod h1:Q3SI9o4m/ZMnBNeIyt5eFwwo7qiLfzFZmjNmxjkiQlU=
|
github.com/bytedance/sonic v1.8.5/go.mod h1:i736AoUSYt75HyZLoJW9ERYxcy6eaN6h4BZXU064P/U=
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20211019084208-fb5309c8db06/go.mod h1:DH46F32mSOjUmXrMHnKwZdA8wcEefY7UVqBKYGjpdQY=
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311 h1:qSGYFH7+jGhDF8vLC+iwCD4WpbV1EBDSzWkJODFLams=
|
||||||
|
github.com/chenzhuoyu/base64x v0.0.0-20221115062448-fe3a3abad311/go.mod h1:b583jCggY9gE99b6G5LEC39OIiVsWj+R97kbl5odCEk=
|
||||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf h1:iW4rZ826su+pqaw19uhpSCzhj44qo35pNgKFGqzDKkU=
|
||||||
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
github.com/coreos/go-systemd v0.0.0-20191104093116-d3cd4ed1dbcf/go.mod h1:F5haX7vjVVG0kc13fIWeqUViNPyEJxv/OmvnBo0Yme4=
|
||||||
github.com/coreos/go-systemd/v22 v22.3.2 h1:D9/bQk5vlXQFZ6Kwuu6zaiXJ9oTPe68++AzAJc1DzSI=
|
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||||
github.com/coreos/go-systemd/v22 v22.3.2/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
github.com/creack/pty v1.1.9/go.mod h1:oKZEueFk5CKHvIhNR5MUki03XCEU+Q6VDXinZuGJ33E=
|
||||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
github.com/davecgh/go-spew v1.1.1 h1:vj9j/u1bqnvCEfJOwUhtlOARqs3+rkHYY13jYWTU97c=
|
||||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||||
github.com/deckarep/golang-set/v2 v2.1.0 h1:g47V4Or+DUdzbs8FxCCmgb6VYd+ptPAngjM6dtGktsI=
|
github.com/deckarep/golang-set/v2 v2.3.0 h1:qs18EKUfHm2X9fA50Mr/M5hccg2tNnVqsiBImnyDs0g=
|
||||||
github.com/deckarep/golang-set/v2 v2.1.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
|
github.com/deckarep/golang-set/v2 v2.3.0/go.mod h1:VAky9rY/yGXJOLEDv3OMci+7wtDpOF4IN+y82NBOac4=
|
||||||
github.com/deepmap/oapi-codegen v1.12.4 h1:pPmn6qI9MuOtCz82WY2Xaw46EQjgvxednXXrP7g5Q2s=
|
github.com/deepmap/oapi-codegen v1.12.4 h1:pPmn6qI9MuOtCz82WY2Xaw46EQjgvxednXXrP7g5Q2s=
|
||||||
github.com/deepmap/oapi-codegen v1.12.4/go.mod h1:3lgHGMu6myQ2vqbbTXH2H1o4eXFTGnFiDaOaKKl5yas=
|
github.com/deepmap/oapi-codegen v1.12.4/go.mod h1:3lgHGMu6myQ2vqbbTXH2H1o4eXFTGnFiDaOaKKl5yas=
|
||||||
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
github.com/disintegration/imaging v1.6.2 h1:w1LecBlG2Lnp8B3jk5zSuNqd7b4DXhcjwek1ei82L+c=
|
||||||
@@ -50,22 +51,23 @@ github.com/dsoprea/go-utility/v2 v2.0.0-20221003142440-7a1927d49d9d/go.mod h1:LV
|
|||||||
github.com/dsoprea/go-utility/v2 v2.0.0-20221003160719-7bc88537c05e/go.mod h1:VZ7cB0pTjm1ADBWhJUOHESu4ZYy9JN+ZPqjfiW09EPU=
|
github.com/dsoprea/go-utility/v2 v2.0.0-20221003160719-7bc88537c05e/go.mod h1:VZ7cB0pTjm1ADBWhJUOHESu4ZYy9JN+ZPqjfiW09EPU=
|
||||||
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 h1:DilThiXje0z+3UQ5YjYiSRRzVdtamFpvBQXKwMglWqw=
|
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349 h1:DilThiXje0z+3UQ5YjYiSRRzVdtamFpvBQXKwMglWqw=
|
||||||
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8=
|
github.com/dsoprea/go-utility/v2 v2.0.0-20221003172846-a3e1774ef349/go.mod h1:4GC5sXji84i/p+irqghpPFZBF8tRN/Q7+700G0/DLe8=
|
||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
|
github.com/dustin/go-humanize v1.0.1 h1:GzkhY7T5VNhEkwH0PVJgjz+fX1rhBrR7pRT3mDkpeCY=
|
||||||
|
github.com/dustin/go-humanize v1.0.1/go.mod h1:Mu1zIs6XwVuF/gI1OepvI0qD18qycQx+mFykh5fBlto=
|
||||||
github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w=
|
github.com/geoffgarside/ber v1.1.0 h1:qTmFG4jJbwiSzSXoNJeHcOprVzZ8Ulde2Rrrifu5U9w=
|
||||||
github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc=
|
github.com/geoffgarside/ber v1.1.0/go.mod h1:jVPKeCbj6MvQZhwLYsGwaGI52oUorHoHKNecGT85ZCc=
|
||||||
github.com/getkin/kin-openapi v0.113.0 h1:t9aNS/q5Agr7a55Jp1AuZ3sR2WzHESv3Dd2ys4UphsM=
|
github.com/getkin/kin-openapi v0.115.0 h1:c8WHRLVY3G8m9jQTy0/DnIuljgRwTCB5twZytQS4JyU=
|
||||||
github.com/getkin/kin-openapi v0.113.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc=
|
github.com/getkin/kin-openapi v0.115.0/go.mod h1:l5e9PaFUo9fyLJCPGQeXI2ML8c3P8BHOEV2VaAVf/pc=
|
||||||
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
|
github.com/gin-contrib/gzip v0.0.6 h1:NjcunTcGAj5CO1gn4N8jHOSIeRFHIbn51z6K+xaN4d4=
|
||||||
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
|
github.com/gin-contrib/gzip v0.0.6/go.mod h1:QOJlmV2xmayAjkNS2Y8NQsMneuRShOU/kjovCXNuzzk=
|
||||||
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
github.com/gin-contrib/sse v0.1.0 h1:Y/yl/+YNO8GZSjAhjMsSuLt29uWRFHdHYUb5lYOV9qE=
|
||||||
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
github.com/gin-contrib/sse v0.1.0/go.mod h1:RHrZQHXnP2xjPF+u1gW/2HnVO7nvIa9PG3Gm+fLHvGI=
|
||||||
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
|
github.com/gin-gonic/gin v1.8.1/go.mod h1:ji8BvRH1azfM+SYow9zQ6SZMvR8qOMZHmsCuWR9tTTk=
|
||||||
github.com/gin-gonic/gin v1.8.2 h1:UzKToD9/PoFj/V4rvlKqTRKnQYyz8Sc1MJlv4JHPtvY=
|
github.com/gin-gonic/gin v1.9.0 h1:OjyFBKICoexlu99ctXNR2gg+c5pKrKMuyjgARg9qeY8=
|
||||||
github.com/gin-gonic/gin v1.8.2/go.mod h1:qw5AYuDrzRTnhvusDsrov+fDIxp9Dleuu12h8nfB398=
|
github.com/gin-gonic/gin v1.9.0/go.mod h1:W1Me9+hsUSyj3CePGrd1/QrKJMSJ1Tu/0hFEH89961k=
|
||||||
github.com/glebarez/go-sqlite v1.20.0 h1:6D9uRXq3Kd+W7At+hOU2eIAeahv6qcYfO8jzmvb4Dr8=
|
github.com/glebarez/go-sqlite v1.21.0 h1:b8MHPtBagkSD2gntImZPsG3o3QEXgMDxguW/GLUonHQ=
|
||||||
github.com/glebarez/go-sqlite v1.20.0/go.mod h1:uTnJoqtwMQjlULmljLT73Cg7HB+2X6evsBHODyyq1ak=
|
github.com/glebarez/go-sqlite v1.21.0/go.mod h1:GodsA6yGSa3eKbvpr7dS+JaqazzVfMcjIXvx6KHhW/c=
|
||||||
github.com/glebarez/sqlite v1.6.0 h1:ZpvDLv4zBi2cuuQPitRiVz/5Uh6sXa5d8eBu0xNTpAo=
|
github.com/glebarez/sqlite v1.7.0 h1:A7Xj/KN2Lvie4Z4rrgQHY8MsbebX3NyWsL3n2i82MVI=
|
||||||
github.com/glebarez/sqlite v1.6.0/go.mod h1:6D6zPU/HTrFlYmVDKqBJlmQvma90P6r7sRRdkUUZOYk=
|
github.com/glebarez/sqlite v1.7.0/go.mod h1:PkeevrRlF/1BhQBCnzcMWzgrIk7IOop+qS2jUYLfHhk=
|
||||||
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
github.com/go-errors/errors v1.0.1/go.mod h1:f4zRHt4oKfwPJE5k8C9vpYG+aDHdBFUsgrm6/TyX73Q=
|
||||||
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
github.com/go-errors/errors v1.0.2/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
||||||
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
github.com/go-errors/errors v1.1.1/go.mod h1:psDX2osz5VnTOnFWbDeWwS7yejl+uV3FEWEp4lssFEs=
|
||||||
@@ -75,35 +77,40 @@ github.com/go-ini/ini v1.67.0 h1:z6ZrTEZqSWOTyH2FlglNbNgARyHG8oLW9gMELqKr06A=
|
|||||||
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
github.com/go-ini/ini v1.67.0/go.mod h1:ByCAeIL28uOIIG0E3PJtZPDL8WnHpFKFOtgjp+3Ies8=
|
||||||
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
github.com/go-ole/go-ole v1.2.6 h1:/Fpf6oFPoeFik9ty7siob0G6Ke8QvQEuVcuChpwXzpY=
|
||||||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||||
github.com/go-openapi/jsonpointer v0.19.5 h1:gZr+CIYByUqjcgeLXnQu2gHYQC9o73G2XUeOFYEICuY=
|
|
||||||
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
github.com/go-openapi/jsonpointer v0.19.5/go.mod h1:Pl9vOtqEWErmShwVjC8pYs9cog34VGT37dQOVbmoatg=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.6 h1:eCs3fxoIi3Wh6vtgmLTOjdhSpiqphQ+DaPn38N2ZdrE=
|
||||||
|
github.com/go-openapi/jsonpointer v0.19.6/go.mod h1:osyAmYz/mB/C3I+WsTTSgw1ONzaLJoLCyoi6/zppojs=
|
||||||
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
github.com/go-openapi/swag v0.19.5/go.mod h1:POnQmlKehdgb5mhVOsnJFsivZCEZ/vjK9gh66Z9tfKk=
|
||||||
github.com/go-openapi/swag v0.21.1 h1:wm0rhTb5z7qpJRHBdPOMuY4QjVUMbF6/kwoYeRAOrKU=
|
github.com/go-openapi/swag v0.22.3 h1:yMBqmnQ0gyZvEb/+KzuWZOXgllrXT4SADYbvDaXHv/g=
|
||||||
github.com/go-openapi/swag v0.21.1/go.mod h1:QYRuS/SOXUCsnplDa677K7+DxSOj6IPNl/eQntq43wQ=
|
github.com/go-openapi/swag v0.22.3/go.mod h1:UzaqsxGiab7freDnrUUra0MwWfN/q7tE4j+VcZ0yl14=
|
||||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
|
|
||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
|
||||||
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
|
github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
|
||||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
|
||||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
|
github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
|
||||||
|
github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
|
||||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
|
||||||
|
github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
|
||||||
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
github.com/go-playground/validator/v10 v10.10.0/go.mod h1:74x4gJWsvQexRdW8Pn3dXSGrTK4nAUsbPlLADvpJkos=
|
||||||
github.com/go-playground/validator/v10 v10.11.1 h1:prmOlTVv+YjZjmRmNSF3VmspqJIxJWXmqUsHwfTRRkQ=
|
github.com/go-playground/validator/v10 v10.11.2 h1:q3SHpufmypg+erIExEKUmsgmhDTyhcJ38oeKGACXohU=
|
||||||
github.com/go-playground/validator/v10 v10.11.1/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
|
github.com/go-playground/validator/v10 v10.11.2/go.mod h1:NieE624vt4SCTJtD87arVLvdmjPAeV8BQlHtMnw9D7s=
|
||||||
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
github.com/go-resty/resty/v2 v2.7.0 h1:me+K9p3uhSmXtrBZ4k9jcEAfJmuC8IivWHwaLZwPrFY=
|
||||||
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
github.com/go-resty/resty/v2 v2.7.0/go.mod h1:9PWDzw47qPphMRFfhsyk0NnSgvluHcljSMVIq3w7q0I=
|
||||||
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
github.com/go-test/deep v1.0.8 h1:TDsG77qcSprGbC6vTN8OuXp5g+J+b5Pcguhf7Zt61VM=
|
||||||
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
github.com/go-test/deep v1.0.8/go.mod h1:5C2ZWiW0ErCdrYzpqxLbTX7MG14M9iiw8DgHncVwcsE=
|
||||||
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.9.7/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/goccy/go-json v0.9.11 h1:/pAaQDLHEoCq/5FFmSKBswWmK6H0e8g4159Kc/X/nqk=
|
github.com/goccy/go-json v0.10.1 h1:lEs5Ob+oOG/Ze199njvzHbhn6p9T+h64F5hRj69iTTo=
|
||||||
github.com/goccy/go-json v0.9.11/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
github.com/goccy/go-json v0.10.1/go.mod h1:6MelG93GURQebXPDq3khkgXZkazVtN9CRI+MGFi0w8I=
|
||||||
github.com/godbus/dbus/v5 v5.0.4 h1:9349emZab16e7zQvpmsbtjc18ykshndd8y2PG3sgJbA=
|
|
||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible h1:1SD/1F5pU8p29ybwgQSwpQk+mwdRrXCYuPhW6m+TnJw=
|
github.com/godbus/dbus/v5 v5.1.0 h1:4KLkAxT3aOY8Li4FRJe/KvhoNFFxo0m6fNuFUO8QJUk=
|
||||||
|
github.com/godbus/dbus/v5 v5.1.0/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||||
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
github.com/gofrs/uuid v4.0.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
|
github.com/gofrs/uuid v4.4.0+incompatible h1:3qXRTX8/NbyulANqlc0lchS1gqAVxRgsuW1YrTJupqA=
|
||||||
|
github.com/gofrs/uuid v4.4.0+incompatible/go.mod h1:b2aQJv3Z4Fp6yNu3cdSllBxTCLRxnplIgP/c0N/04lM=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
github.com/golang-jwt/jwt v3.2.2+incompatible h1:IfV12K8xAKAnZqdXVzCZ+TOjboZ2keLg81eXfW3O+oY=
|
||||||
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
github.com/golang-jwt/jwt v3.2.2+incompatible/go.mod h1:8pz2t5EyA70fFQQSrl6XZXzqecmYZeUEB8OUGHkxJ+I=
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.2 h1:rcc4lwaZgFMCZ5jxF9ABolDcIHdBytAFgqFPbSJQAYs=
|
github.com/golang-jwt/jwt/v4 v4.5.0 h1:7cYmW1XlMY7h7ii7UhUyChSgS5wUJEnm9uZVTGqOWzg=
|
||||||
github.com/golang-jwt/jwt/v4 v4.4.2/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
github.com/golang-jwt/jwt/v4 v4.5.0/go.mod h1:m21LjoU+eqJr34lmDMbreY2eSTRJ1cv77w39/MY0Ch0=
|
||||||
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
github.com/golang/geo v0.0.0-20190916061304-5b978397cfec/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||||
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
github.com/golang/geo v0.0.0-20200319012246-673a6f80352d/go.mod h1:QZ0nwyI2jOfgRAoBvP+ab5aRr7c9x7lhGEJrKvBwjWI=
|
||||||
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
|
github.com/golang/geo v0.0.0-20210211234256-740aa86cb551 h1:gtexQ/VGyN+VVFRXSFiguSNcXmS6rkKT+X7FdIrTtfo=
|
||||||
@@ -113,29 +120,30 @@ github.com/golang/mock v1.6.0/go.mod h1:p6yTPP+5HYm5mzsMV8JkE6ZKdX+/wYM6Hr+Licev
|
|||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
github.com/golang/protobuf v1.3.2/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
|
||||||
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
|
||||||
github.com/golang/protobuf v1.5.2 h1:ROPKBNFfQgOUMifHyP+KYbvpjbdoFNs+aK7DXlji0Tw=
|
github.com/golang/protobuf v1.5.3 h1:KhyjKVUg7Usr/dYsdSqoFveMYd5ko72D+zANwlG1mmg=
|
||||||
github.com/golang/protobuf v1.5.2/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
github.com/golang/protobuf v1.5.3/go.mod h1:XVQd3VNwM+JqD3oG2Ue2ip4fOMUkwXdXDdiuN0vRsmY=
|
||||||
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.2/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
|
||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
|
||||||
github.com/gomodule/redigo v1.8.4/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
github.com/gomodule/redigo v1.8.4/go.mod h1:P9dn9mFrCBvWhGE1wpxx6fgq7BAeLBk+UUUzlpkBYO0=
|
||||||
github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=
|
github.com/gomodule/redigo v1.8.9 h1:Sl3u+2BI/kk+VEatbj0scLdrFhjPmbxOc1myhDP41ws=
|
||||||
github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
|
github.com/gomodule/redigo v1.8.9/go.mod h1:7ArFNvsTjH8GMMzB4uy1snslv2BwmginuMs06a1uzZE=
|
||||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
github.com/google/go-cmp v0.5.6/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||||
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
github.com/google/go-cmp v0.5.9 h1:O2Tfq5qg4qc4AmwVlvv0oLiVAGB7enBSJ2x2DqQFi38=
|
||||||
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
github.com/google/go-cmp v0.5.9/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||||
github.com/google/go-github/v36 v36.0.0 h1:ndCzM616/oijwufI7nBRa+5eZHLldT+4yIB68ib5ogs=
|
github.com/google/go-github/v36 v36.0.0 h1:ndCzM616/oijwufI7nBRa+5eZHLldT+4yIB68ib5ogs=
|
||||||
github.com/google/go-github/v36 v36.0.0/go.mod h1:LFlKC047IOqiglRGNqNb9s/iAPTnnjtlshm+bxp+kwk=
|
github.com/google/go-github/v36 v36.0.0/go.mod h1:LFlKC047IOqiglRGNqNb9s/iAPTnnjtlshm+bxp+kwk=
|
||||||
github.com/google/go-querystring v1.0.0 h1:Xkwi/a1rcvNg1PPYe5vI8GbeBY/jrVuDX5ASuANWTrk=
|
|
||||||
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
github.com/google/go-querystring v1.0.0/go.mod h1:odCYkC5MyYFN7vkCjXpyrEuKhc/BUO6wN/zVPAxq5ck=
|
||||||
|
github.com/google/go-querystring v1.1.0 h1:AnCroh3fv4ZBgVIf1Iwtovgjaw/GiKJo8M8yD/fhyJ8=
|
||||||
|
github.com/google/go-querystring v1.1.0/go.mod h1:Kcdr2DB4koayq7X8pmAG4sNG59So17icRSOU623lUBU=
|
||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
|
||||||
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26/go.mod h1:dDKJzRmX4S37WGHujM7tX//fmj1uioxKzKxz3lo4HJo=
|
github.com/google/pprof v0.0.0-20221118152302-e6195bd50e26 h1:Xim43kblpZXfIBQsbuBVKCudVG457BR2GZFIz3uw3hQ=
|
||||||
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
github.com/google/uuid v1.3.0 h1:t6JiXgmwXMjEs8VusXIJk2BXHsn+wx8BZdTaoZ5fu7I=
|
||||||
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
github.com/google/uuid v1.3.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||||
github.com/googollee/go-socket.io v1.6.2 h1:olKLLHJtHz1IkL/OrTyNriZZvVQYEORNkJAqsOwPask=
|
github.com/googollee/go-socket.io v1.7.0 h1:ODcQSAvVIPvKozXtUGuJDV3pLwdpBLDs1Uoq/QHIlY8=
|
||||||
github.com/googollee/go-socket.io v1.6.2/go.mod h1:0vGP8/dXR9SZUMMD4+xxaGo/lohOw3YWMh2WRiWeKxg=
|
github.com/googollee/go-socket.io v1.7.0/go.mod h1:0vGP8/dXR9SZUMMD4+xxaGo/lohOw3YWMh2WRiWeKxg=
|
||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
|
||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
|
||||||
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
github.com/gorilla/websocket v1.4.2/go.mod h1:YR8l580nyteQvAITg2hZ9XVh4b55+EU/adAjf1fMHhE=
|
||||||
@@ -145,14 +153,13 @@ github.com/h2non/filetype v1.1.3 h1:FKkx9QbD7HR/zjK1Ia5XiBsq9zdLi5Kf3zGyFTAFkGg=
|
|||||||
github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
github.com/h2non/filetype v1.1.3/go.mod h1:319b3zT68BvV+WRj7cwy856M2ehB3HqNOt6sy1HndBY=
|
||||||
github.com/hirochachacha/go-smb2 v1.1.0 h1:b6hs9qKIql9eVXAiN0M2wSFY5xnhbHAQoCwRKbaRTZI=
|
github.com/hirochachacha/go-smb2 v1.1.0 h1:b6hs9qKIql9eVXAiN0M2wSFY5xnhbHAQoCwRKbaRTZI=
|
||||||
github.com/hirochachacha/go-smb2 v1.1.0/go.mod h1:8F1A4d5EZzrGu5R7PU163UcMRDJQl4FtcxjBfsY8TZE=
|
github.com/hirochachacha/go-smb2 v1.1.0/go.mod h1:8F1A4d5EZzrGu5R7PU163UcMRDJQl4FtcxjBfsY8TZE=
|
||||||
github.com/ianlancetaylor/demangle v0.0.0-20220319035150-800ac71e25c2/go.mod h1:aYm2/VgdVmcIU8iMfdMvDMsRAQjcfZSKFby6HOFvi/w=
|
|
||||||
github.com/invopop/yaml v0.1.0 h1:YW3WGUoJEXYfzWBjn00zIlrw7brGVD0fUKRYDPAPhrc=
|
|
||||||
github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
|
github.com/invopop/yaml v0.1.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
|
||||||
|
github.com/invopop/yaml v0.2.0 h1:7zky/qH+O0DwAyoobXUqvVBwgBFRxKoQ/3FjcVpjTMY=
|
||||||
|
github.com/invopop/yaml v0.2.0/go.mod h1:2XuRLgs/ouIrW3XNzuNj7J3Nvu/Dig5MXvbCEdiBN3Q=
|
||||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||||
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
github.com/jessevdk/go-flags v1.5.0/go.mod h1:Fw0T6WPc1dYxT4mKEZRfG5kJhaTDP9pj1c2EWnYs/m4=
|
||||||
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
github.com/jinzhu/inflection v1.0.0 h1:K317FqzuhWc8YvSVlFMCCUb36O/S9MCKRDI7QkRKD/E=
|
||||||
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
github.com/jinzhu/inflection v1.0.0/go.mod h1:h+uFLlag+Qp1Va5pdKtLDYj+kHp5pxUVkryuEj+Srlc=
|
||||||
github.com/jinzhu/now v1.1.4/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
|
||||||
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
github.com/jinzhu/now v1.1.5 h1:/o9tlHleP7gOFmsnYNz3RGnqzefHA47wQpKrrdTIwXQ=
|
||||||
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
github.com/jinzhu/now v1.1.5/go.mod h1:d3SSVoowX0Lcu0IBviAWJpolVfI5UJVZZ7cO71lE/z8=
|
||||||
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
github.com/josharian/intern v1.0.0 h1:vlS4z54oSdjm0bgjRigI+G1HpF+tI+9rE5LLzOg8HmY=
|
||||||
@@ -160,33 +167,37 @@ github.com/josharian/intern v1.0.0/go.mod h1:5DoeVV0s6jJacbCEi61lwdGj/aVlrQvzHFF
|
|||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
|
||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
|
||||||
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
|
github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
|
||||||
github.com/kballard/go-shellquote v0.0.0-20180428030007-95032a82bc51/go.mod h1:CzGEWj7cYgsdH8dAjBGEr58BoE7ScuLd+fwFZ44+/x8=
|
|
||||||
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
github.com/klauspost/compress v1.4.1/go.mod h1:RyIbtBH6LamlWaDj8nUwkbUhJ87Yi3uG0guNDohfE1A=
|
||||||
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
github.com/klauspost/compress v1.11.4/go.mod h1:aoV0uJVorq1K+umq18yTdKaF57EivdYsUV+/s2qKfXs=
|
||||||
github.com/klauspost/compress v1.15.13 h1:NFn1Wr8cfnenSJSA46lLq4wHCcBzKTSjnBIexDMMOV0=
|
github.com/klauspost/compress v1.16.3 h1:XuJt9zzcnaz6a16/OU53ZjWp/v7/42WcR5t2a0PcNQY=
|
||||||
github.com/klauspost/compress v1.15.13/go.mod h1:QPwzmACJjUTFsnSHH934V6woptycfrDDJnH7hvFVbGM=
|
github.com/klauspost/compress v1.16.3/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
|
||||||
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
github.com/klauspost/cpuid v1.2.0/go.mod h1:Pj4uuM528wm8OyEC2QMXAi2YiTZ96dNQPGgoMS4s3ek=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.0.9/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.4 h1:acbojRNwl3o09bUq+yDCtZFc1aiwaAAxtcn8YkZXnvk=
|
||||||
|
github.com/klauspost/cpuid/v2 v2.2.4/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
|
||||||
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
github.com/klauspost/pgzip v1.2.5 h1:qnWYvvKqedOF2ulHpMG72XQol4ILEJ8k2wwRl/Km8oE=
|
||||||
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
github.com/klauspost/pgzip v1.2.5/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
|
||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
|
||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
|
||||||
github.com/kr/pretty v0.3.0 h1:WgNl7dwNpEZ6jJ9k1snq4pZsg7DOEN8hP9Xw0Tsjwk0=
|
|
||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
|
||||||
|
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||||
|
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
|
||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
|
||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||||
github.com/labstack/echo/v4 v4.10.0 h1:5CiyngihEO4HXsz3vVsJn7f8xAlWwRr3aY6Ih280ZKA=
|
github.com/labstack/echo/v4 v4.10.2 h1:n1jAhnq/elIFTHr1EYpiYtyKgx4RW9ccVgkqByZaN2M=
|
||||||
github.com/labstack/echo/v4 v4.10.0/go.mod h1:S/T/5fy/GigaXnHTkh0ZGe4LpkkQysvRjFMSUTkDRNQ=
|
github.com/labstack/echo/v4 v4.10.2/go.mod h1:OEyqf2//K1DFdE57vw2DRgWY0M7s65IVQO2FzvI4J5k=
|
||||||
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
github.com/labstack/gommon v0.4.0 h1:y7cvthEAEbU0yHOf4axH8ZG2NH8knB9iNSoTO8dyIk8=
|
||||||
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
github.com/labstack/gommon v0.4.0/go.mod h1:uW6kP17uPlLJsD3ijUYn3/M5bAxtlZhMI6m3MFxTMTM=
|
||||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
|
|
||||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0 h1:6E+4a0GO5zZEnZ81pIr0yLvtUWk2if982qA3F3QD6H4=
|
github.com/leodido/go-urn v1.2.2 h1:7z68G0FCGvDk646jz1AelTYNYWrTNm0bEcFAo147wt4=
|
||||||
|
github.com/leodido/go-urn v1.2.2/go.mod h1:kUaIbLZWttglzwNuG0pgsh5vuV6u2YcGBYz1hIPjtOQ=
|
||||||
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
github.com/lufia/plan9stats v0.0.0-20211012122336-39d0f177ccd0/go.mod h1:zJYVVT2jmtg6P3p1VtQj7WsuWi/y4VnjVBn7F8KPB3I=
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de h1:V53FWzU6KAZVi1tPp5UIsMoUWJ2/PNwYIDXnu7QuBCE=
|
||||||
|
github.com/lufia/plan9stats v0.0.0-20230110061619-bbe2e5e100de/go.mod h1:JKx41uQRwqlTZabZc+kILPrO/3jlKnQ2Z8b7YiVw5cE=
|
||||||
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190614124828-94de47d64c63/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
github.com/mailru/easyjson v0.0.0-20190626092158-b2ccc519800e/go.mod h1:C1wdFJiN94OJF2b5HbByQZoLdCWB1Yqtg26g4irojpc=
|
||||||
github.com/mailru/easyjson v0.7.6/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
|
||||||
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
github.com/mailru/easyjson v0.7.7 h1:UGYAvKxe3sBsEDzO8ZeWOSlIQfWFlxbzLZe7hwFURr0=
|
||||||
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
github.com/mailru/easyjson v0.7.7/go.mod h1:xzfreul335JAWq5oZzymOObrkdz5UnU4kGfJJLY9Nlc=
|
||||||
github.com/maruel/natural v1.1.0 h1:2z1NgP/Vae+gYrtC0VuvrTJ6U35OuyUqDdfluLqMWuQ=
|
github.com/maruel/natural v1.1.0 h1:2z1NgP/Vae+gYrtC0VuvrTJ6U35OuyUqDdfluLqMWuQ=
|
||||||
@@ -195,12 +206,13 @@ github.com/mattn/go-colorable v0.1.11/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb
|
|||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
|
||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
|
||||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||||
github.com/mattn/go-isatty v0.0.16 h1:bq3VjFmv/sOjHtdEhmkEV4x1AJtvUvOJ2PFAZ5+peKQ=
|
|
||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mattn/go-sqlite3 v1.14.15 h1:vfoHhTN1af61xCRSWzFIWzx2YskyMTwHLrExkBOjvxI=
|
github.com/mattn/go-isatty v0.0.17 h1:BTarxUcIeDqL27Mc+vyvdWYSL28zpIhv3RoTdsLMPng=
|
||||||
github.com/mattn/go-sqlite3 v1.14.15/go.mod h1:2eHXhiwb8IkHr+BDWZGa96P6+rkvnG63S2DGjv9HUNg=
|
github.com/mattn/go-isatty v0.0.17/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||||
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
|
github.com/mholt/archiver/v3 v3.5.1 h1:rDjOBX9JSF5BvoJGvjqK479aL70qh9DIpZCl+k7Clwo=
|
||||||
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
github.com/mholt/archiver/v3 v3.5.1/go.mod h1:e3dqJ7H78uzsRSEACH1joayhuSyhnonssnDhppzS1L4=
|
||||||
|
github.com/mileusna/useragent v1.2.1 h1:p3RJWhi3LfuI6BHdddojREyK3p6qX67vIfOVMnUIVr0=
|
||||||
|
github.com/mileusna/useragent v1.2.1/go.mod h1:3d8TOmwL/5I8pJjyVDteHtgDGcefrFUX4ccGOMKNYYc=
|
||||||
github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs=
|
github.com/moby/sys/mount v0.3.3 h1:fX1SVkXFJ47XWDoeFW4Sq7PdQJnV2QIDZAqjNqgEjUs=
|
||||||
github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0=
|
github.com/moby/sys/mount v0.3.3/go.mod h1:PBaEorSNTLG5t/+4EgukEQVlAvVEc6ZjTySwKdqp5K0=
|
||||||
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
github.com/moby/sys/mountinfo v0.6.2 h1:BzJjoreD5BMFNmD9Rus6gdd1pLuecOFPt8wC+Vygl78=
|
||||||
@@ -212,36 +224,41 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
|
|||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
|
||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
|
||||||
github.com/nwaples/rardecode v1.1.0 h1:vSxaY8vQhOcVr4mm5e8XllHWTiM4JF507A0Katqw7MQ=
|
|
||||||
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
github.com/nwaples/rardecode v1.1.0/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||||
|
github.com/nwaples/rardecode v1.1.3 h1:cWCaZwfM5H7nAD6PyEdcVnczzV8i/JtotnyW/dD9lEc=
|
||||||
|
github.com/nwaples/rardecode v1.1.3/go.mod h1:5DzqNKiOdpKKBH87u8VlvAnPZMXcGRhxWkRpHbbfGS0=
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
github.com/patrickmn/go-cache v2.1.0+incompatible h1:HRMgzkcYKYpi3C8ajMPV8OFXaaRUnok+kx1WdO15EQc=
|
||||||
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
github.com/patrickmn/go-cache v2.1.0+incompatible/go.mod h1:3Qf8kWWT7OJRJbdiICTKqZju1ZixQ/KpMGzzAfe6+WQ=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
github.com/pelletier/go-toml/v2 v2.0.1/go.mod h1:r9LEWfGN8R5k0VXJ+0BkIe7MYkRdwZOjgMj2KwnJFUo=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.6 h1:nrzqCb7j9cDFj2coyLNLaZuJTLjWjlaz6nvTvIwycIU=
|
github.com/pelletier/go-toml/v2 v2.0.7 h1:muncTPStnKRos5dpVKULv2FVd4bMOhNePj9CjgDb8Us=
|
||||||
github.com/pelletier/go-toml/v2 v2.0.6/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
github.com/pelletier/go-toml/v2 v2.0.7/go.mod h1:eumQOmlWiOPt5WriQQqoM5y18pDHwha2N+QD+EUNTek=
|
||||||
github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw=
|
github.com/perimeterx/marshmallow v1.1.4 h1:pZLDH9RjlLGGorbXhcaQLhfuV0pFMNfPO55FuFkxqLw=
|
||||||
github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
|
github.com/perimeterx/marshmallow v1.1.4/go.mod h1:dsXbUu8CRzfYP5a87xpp0xq9S3u0Vchtcl8we9tYaXw=
|
||||||
github.com/pierrec/lz4/v4 v4.1.2 h1:qvY3YFXRQE/XB8MlLzJH7mSzBs74eA2gg52YTk6jUPM=
|
|
||||||
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
github.com/pierrec/lz4/v4 v4.1.2/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.17 h1:kV4Ip+/hUBC+8T6+2EgburRtkE9ef4nbY3f4dFhGjMc=
|
||||||
|
github.com/pierrec/lz4/v4 v4.1.17/go.mod h1:gZWDp/Ze/IJXGXf23ltt2EXimqmTUXEy0GFuRQyBid4=
|
||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
|
||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
|
||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||||
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
github.com/pmezard/go-difflib v1.0.0 h1:4DBwDE0NGyQoBHbLQYPwSUPoCMWR5BEzIk/f1lZbAQM=
|
||||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c h1:ncq/mPwQF4JjgDlrVEn3C11VoGHZN7m8qihwgMEtzYw=
|
|
||||||
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
github.com/power-devops/perfstat v0.0.0-20210106213030-5aafc221ea8c/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0 h1:OdAsTTz6OkFY5QxjkYwrChwuRruF69c169dPK26NUlk=
|
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b h1:0LFwY6Q3gMACTjAbMZBjXAqTOzOwFaj2Ld6cjeQ7Rig=
|
||||||
|
github.com/power-devops/perfstat v0.0.0-20221212215047-62379fc7944b/go.mod h1:OmDBASR4679mdNQnz2pUhc2G8CO2JrUAVFDRBDP/hJE=
|
||||||
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
github.com/remyoudompheng/bigfft v0.0.0-20200410134404-eec4a21b6bb0/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
github.com/robfig/cron v1.2.0 h1:ZjScXvvxeQ63Dbyxy76Fj3AT3Ut0aKsyd2/tl3DTMuQ=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec h1:W09IVJc94icq4NjY3clb7Lk8O1qJ8BdBEF8z0ibU0rE=
|
||||||
github.com/robfig/cron v1.2.0/go.mod h1:JGuDeoQd7Z6yL4zQhZ3OPEVHB7fL6Ka6skscFHfmt2k=
|
github.com/remyoudompheng/bigfft v0.0.0-20230129092748-24d4a6f8daec/go.mod h1:qqbHyh8v60DhA7CoWK5oRCqLrMHRGoxYCSS9EjAz6Eo=
|
||||||
|
github.com/robfig/cron/v3 v3.0.1 h1:WdRxkvbJztn8LMz/QEvLN5sBU+xKpSqwwUO1Pjr4qDs=
|
||||||
|
github.com/robfig/cron/v3 v3.0.1/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
|
||||||
github.com/rogpeppe/go-internal v1.8.0 h1:FCbCCtXNOY3UtUuHUYaghJg4y7Fd14rXifAYUAtL9R8=
|
|
||||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
|
||||||
|
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
|
||||||
|
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
|
||||||
|
github.com/rwtodd/Go.Sed v0.0.0-20210816025313-55464686f9ef/go.mod h1:8AEUvGVi2uQ5b24BIhcr0GCcpd/RNAFWaN2CJFrWIIQ=
|
||||||
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
github.com/satori/go.uuid v1.2.0 h1:0uYX9dsZ2yD7q2RtLRtPSdGDWzjeM3TbMJP9utgA0ww=
|
||||||
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
github.com/satori/go.uuid v1.2.0/go.mod h1:dA0hQrYB0VpLJoorglMZABFdXlWrHn1NEOzdhQKdks0=
|
||||||
github.com/shirou/gopsutil/v3 v3.22.11 h1:kxsPKS+Eeo+VnEQ2XCaGJepeP6KY53QoRTETx3+1ndM=
|
github.com/shirou/gopsutil/v3 v3.23.2 h1:PAWSuiAszn7IhPMBtXsbSCafej7PqUOvY6YywlQUExU=
|
||||||
github.com/shirou/gopsutil/v3 v3.22.11/go.mod h1:xl0EeL4vXJ+hQMAGN8B9VFpxukEMA0XdevQOe5MZ1oY=
|
github.com/shirou/gopsutil/v3 v3.23.2/go.mod h1:gv0aQw33GLo3pG8SiWKiQrbDzbRY1K80RyZJ7V4Th1M=
|
||||||
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
github.com/sirupsen/logrus v1.9.0 h1:trlNQbNUG3OdDrDil03MCb1H2o9nJ1x4/5LYw7byDE0=
|
||||||
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
github.com/sirupsen/logrus v1.9.0/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
|
||||||
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
|
||||||
@@ -254,24 +271,30 @@ github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/
|
|||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
|
||||||
github.com/stretchr/testify v1.8.1 h1:w7B6lhMri9wdJUVmEZPGGhZzrYTPvgJArz7wNPgYKsk=
|
|
||||||
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
github.com/stretchr/testify v1.8.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
|
github.com/stretchr/testify v1.8.2 h1:+h33VjcLVPDHtOdpUCuF+7gSuG3yGIftsP1YvFihtJ8=
|
||||||
|
github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||||
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM=
|
||||||
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk=
|
||||||
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA=
|
||||||
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM=
|
||||||
github.com/tidwall/pretty v1.2.0 h1:RWIZEg2iJ8/g6fDDYzMpobmaoGh5OLl4AXtGUGPcqCs=
|
|
||||||
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
|
github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4=
|
||||||
|
github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU=
|
||||||
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
|
github.com/tklauser/go-sysconf v0.3.11 h1:89WgdJhk5SNwJfu+GKyYveZ4IaJ7xAkecBo+KdJV0CM=
|
||||||
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
|
github.com/tklauser/go-sysconf v0.3.11/go.mod h1:GqXfhXY3kiPa0nAXPDIQIWzJbMCB7AmcWpGR8lSZfqI=
|
||||||
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
|
github.com/tklauser/numcpus v0.6.0 h1:kebhY2Qt+3U6RNK7UqpYNA+tJ23IBEGKkB7JQBfDYms=
|
||||||
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
|
github.com/tklauser/numcpus v0.6.0/go.mod h1:FEZLMke0lhOUG6w2JadTzp0a+Nl8PF/GFkQ5UVIcaL4=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1 h1:SU5vSMR7hnwNxj24w34ZyCi/FmDZTkS4MhqMhdFk5YI=
|
||||||
|
github.com/twitchyliquid64/golang-asm v0.15.1/go.mod h1:a1lVb/DtPvCB8fslRZhAngC2+aY1QWCk3Cedj/Gdt08=
|
||||||
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
github.com/ugorji/go v1.2.7/go.mod h1:nF9osbDWLy6bDVv/Rtoh6QgnvNDpmCalQV5urGCCS6M=
|
||||||
github.com/ugorji/go/codec v1.2.7 h1:YPXUKf7fYbp/y8xloBqZOw2qaVggbfwMlI8WM3wZUJ0=
|
|
||||||
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
github.com/ugorji/go/codec v1.2.7/go.mod h1:WGN1fab3R1fzQlVQTkfxVtIBhWDRqOviHU95kRgeqEY=
|
||||||
|
github.com/ugorji/go/codec v1.2.11 h1:BMaWp1Bb6fHwEtbplGBGJ498wD+LKlNSl25MjdZY4dU=
|
||||||
|
github.com/ugorji/go/codec v1.2.11/go.mod h1:UNopzCgEMSXjBc6AOMqYvWC1ktqTAfzJZUZgYf6w6lg=
|
||||||
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.8/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/ulikunitz/xz v0.5.9 h1:RsKRIA2MO8x56wkkcd3LbtcE/uMszhb6DpRf+3uwa3I=
|
|
||||||
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
github.com/ulikunitz/xz v0.5.9/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
|
github.com/ulikunitz/xz v0.5.11 h1:kpFauv27b6ynzBNT/Xy+1k+fK4WswhN/6PN5WhFAGw8=
|
||||||
|
github.com/ulikunitz/xz v0.5.11/go.mod h1:nbz6k7qbPmH4IRqmfOplQw/tblSgqTqBwxkY0oWt/14=
|
||||||
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
github.com/valyala/bytebufferpool v1.0.0 h1:GqA5TC/0021Y/b9FG4Oi9Mr3q7XYx6KllzawFIhcdPw=
|
||||||
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
github.com/valyala/bytebufferpool v1.0.0/go.mod h1:6bBcMArwyJ5K/AmCkWv1jt77kVWyCJ6HpOuEn7z0Csc=
|
||||||
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.1/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
@@ -279,29 +302,34 @@ github.com/valyala/fasttemplate v1.2.2 h1:lxLXG0uE3Qnshl9QyaK6XJxMXlQZELvChBOCmQ
|
|||||||
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
github.com/valyala/fasttemplate v1.2.2/go.mod h1:KHLXt3tVN2HBp8eijSv/kGJopbvo7S+qRAEEKiv+SiQ=
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8 h1:nIPpBwaJSVYIxUFsDv3M8ofmx9yWTog9BfvIu0q41lo=
|
||||||
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
github.com/xi2/xz v0.0.0-20171230120015-48954b6210f8/go.mod h1:HUYIGzjTL3rfEspMxjDjgmT5uz5wzYJKVo23qUhYTos=
|
||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
|
|
||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
|
||||||
|
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||||
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
github.com/yusufpapurcu/wmi v1.2.2 h1:KBNDSne4vP5mbSWnJbO+51IMOXJB67QiYCSBrubbPRg=
|
||||||
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
github.com/yusufpapurcu/wmi v1.2.2/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||||
go.uber.org/atomic v1.7.0 h1:ADUqmZGgLDDfbSL9ZmPxKTybcoEYHgpYfELNoN+7hsw=
|
go.uber.org/atomic v1.10.0 h1:9qC72Qh0+3MqyJbAn8YU5xVq1frD8bn3JtD2oXtafVQ=
|
||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
|
go.uber.org/atomic v1.10.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
|
||||||
go.uber.org/goleak v1.1.11 h1:wy28qYRKZgnJTxGxvye5/wgWr1EKjmUDGYox5mGlRlI=
|
go.uber.org/goleak v1.2.1 h1:NBol2c7O1ZokfZ0LEU9K6Whx/KnwvepVetCUhtKja4A=
|
||||||
go.uber.org/multierr v1.6.0 h1:y6IPFStTAIT5Ytl7/XYmHvzXQ7S3g/IeZW9hyZ5thw4=
|
go.uber.org/goleak v1.2.1/go.mod h1:qlT2yGI9QafXHhZZLxlSuNsMw3FFLxBr+tBRlmO1xH4=
|
||||||
go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9iU=
|
go.uber.org/multierr v1.10.0 h1:S0h4aNzvfcFsC3dRF1jLoaov7oRaKqRGC/pUEJ2yvPQ=
|
||||||
|
go.uber.org/multierr v1.10.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||||
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
go.uber.org/zap v1.24.0 h1:FiJd5l1UOLj0wCgbSE0rwwXHzEdAZS6hiiSnxJN/D60=
|
||||||
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
go.uber.org/zap v1.24.0/go.mod h1:2kMP+WWQ8aoFoedH3T2sq6iJ2yDWpHbP0f6MQbS9Gkg=
|
||||||
|
golang.org/x/arch v0.0.0-20210923205945-b76863e36670/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
|
golang.org/x/arch v0.3.0 h1:02VY4/ZcO/gBOH6PUaoiptASxtXU10jazRCP865E97k=
|
||||||
|
golang.org/x/arch v0.3.0/go.mod h1:5om86z9Hs0C8fWVUuoMHwpExlXzs5Tkyp9hOrfG7pp8=
|
||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
|
||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
|
||||||
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
golang.org/x/crypto v0.0.0-20200728195943-123391ffb6de/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||||
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
golang.org/x/crypto v0.0.0-20210711020723-a769d52b0f97/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
|
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||||
golang.org/x/crypto v0.5.0 h1:U/0M97KRkSFvyD/3FSmdP5W5swImpNgle/EHFhOsQPE=
|
golang.org/x/crypto v0.7.0 h1:AvwMYaRytfdeVt3u6mLaxYtErKYjxA2OXjJ1HHq6t3A=
|
||||||
golang.org/x/crypto v0.5.0/go.mod h1:NK/OQwhpMQP3MwtdjgLlYHnH9ebylxKWv3e0fK+mkQU=
|
golang.org/x/crypto v0.7.0/go.mod h1:pYwdfH91IfpZVANVyUOhSIPZaFoJGxTFbZhFTx+dXZU=
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8 h1:hVwzHzIUGRjiF7EcUjqNxk3NCfkPxbDKRdnNE1Rpg0U=
|
|
||||||
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
golang.org/x/image v0.0.0-20191009234506-e7c1f5e7dbb8/go.mod h1:FeLwcggjj3mMvU+oOTbSwawSJRM1uh48EjtB4UJZlP0=
|
||||||
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/image v0.6.0 h1:bR8b5okrPI3g/gyZakLZHeWxAR8Dn5CyxXv1hLH5g/4=
|
||||||
|
golang.org/x/image v0.6.0/go.mod h1:MXLdDR43H7cDJq5GEGXEVeeNhPgi+YYEQ2pC1byI1x0=
|
||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
|
||||||
|
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
|
||||||
|
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
|
||||||
@@ -310,26 +338,26 @@ golang.org/x/net v0.0.0-20191209160850-c0dbc17a3553/go.mod h1:z5CRVTTTmAJ677TzLL
|
|||||||
golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
golang.org/x/net v0.0.0-20200320220750-118fecf932d8/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||||
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200501053045-e0ff5e5a1de5/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
golang.org/x/net v0.0.0-20200513185701-a91f0712d120/go.mod h1:qpuaurCH72eLCgpAm/N6yyVIVM9cpaDIP3A8BGJEC5A=
|
||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
|
|
||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
|
||||||
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20211029224645-99673261e6eb/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||||
golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
|
||||||
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
golang.org/x/net v0.0.0-20221002022538-bcab6841153b/go.mod h1:YDH+HFinaLZZlnHAfSS6ZXJJ9M9t4Dl22yv3iI2vPwk=
|
||||||
golang.org/x/net v0.5.0 h1:GyT4nK/YDHSqa1c4753ouYCDajOYKTja9Xb/OHtgvSw=
|
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||||
golang.org/x/net v0.5.0/go.mod h1:DivGGAXEgPSlEBzxGzZI+ZLohi+xUj054jfeKui00ws=
|
golang.org/x/net v0.8.0 h1:Zrh2ngAOFYneWTAIAPethzeaQLuHwhuBkuV6ZiRnUaQ=
|
||||||
|
golang.org/x/net v0.8.0/go.mod h1:QVkue5JL9kW//ek3r6jTKnTFis1tRmNAW2P1shuFdJc=
|
||||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||||
golang.org/x/oauth2 v0.3.0 h1:6l90koy8/LaBLmLu8jpHeHexzMwEita0zFfYlggy2F8=
|
golang.org/x/oauth2 v0.6.0 h1:Lh8GPgSKBfWSwFvtuWOfeI3aAAnbXTSutYxJiOJFgIw=
|
||||||
golang.org/x/oauth2 v0.3.0/go.mod h1:rQrIauxkUhJ6CuwEXwymO2/eh4xz2ZWF1nBkcxS+tGk=
|
golang.org/x/oauth2 v0.6.0/go.mod h1:ycmewcwgD4Rpr3eZJLSB4Kyyljb3qDh40vJ8STE5HKw=
|
||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c h1:5KslGYwFpkhGh+Q16bwMP3cOontH8FOep7tGV86Y7SQ=
|
|
||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
|
golang.org/x/sync v0.1.0 h1:wsuoTGHzEhffawBOhz5CYhcrV4IdKZbEyZjBMuTp12o=
|
||||||
|
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20200323222414-85ca7c5b95cd/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
|
||||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20201204225414-ed752295db88/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
golang.org/x/sys v0.0.0-20210320140829-1e4c9ba3b0c4/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||||
@@ -341,31 +369,36 @@ golang.org/x/sys v0.0.0-20210630005230-0f9fa26af87c/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20210927094055-39ccf1dd6fa6/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20211103235746-7861aae1554b/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220310020820-b874c991c1a5/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|
||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
|
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220728004956-3c1f35247d10/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.0.0-20220928140112-f11e5e49a4ec/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.2.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0 h1:Zr2JFtRQNX3BCZ8YtxRE9hNJYC8J6I1MVbMg6owUp18=
|
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/sys v0.4.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
golang.org/x/sys v0.6.0 h1:MVltZSvRTcU2ljQOhs94SXPftV6DCNnZViHeQps87pQ=
|
||||||
|
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||||
golang.org/x/term v0.4.0 h1:O7UWfv5+A2qiuulQk30kVinPoMtoIPeVaKLEgLpVkvg=
|
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||||
|
golang.org/x/term v0.6.0 h1:clScbb1cHjoCkyRbWwBEUZ5H/tIFu5TAXIqaZD0Gcjw=
|
||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
|
||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||||
golang.org/x/text v0.6.0 h1:3XmdazWV+ubf7QgHSTWeykHOci5oeekaGJBLkrkaw4k=
|
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||||
golang.org/x/text v0.6.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
golang.org/x/text v0.8.0 h1:57P1ETyNKtuIjB4SRd15iJxuhj8Gc416Y78H3qgMh68=
|
||||||
golang.org/x/time v0.2.0 h1:52I/1L54xyEQAYdtcSuxtiT84KGYTBGXwayxmIpNJhE=
|
golang.org/x/text v0.8.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||||
golang.org/x/time v0.2.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
golang.org/x/time v0.3.0 h1:rg5rLMjNzMS1RkNLzCG38eapWhnYLFYXDXj2gOlr8j4=
|
||||||
|
golang.org/x/time v0.3.0/go.mod h1:tRJNPiyCQ0inRvYxbN9jk5I+vvW/OXSQhTDSoE431IQ=
|
||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
|
||||||
golang.org/x/tools v0.0.0-20201124115921-2c860bdd6e78/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
|
|
||||||
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
|
||||||
|
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||||
|
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||||
@@ -376,18 +409,15 @@ google.golang.org/appengine v1.6.7/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCID
|
|||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
||||||
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
google.golang.org/protobuf v1.26.0/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.28.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
google.golang.org/protobuf v1.28.1 h1:d0NfwRgPtno5B1Wa6L2DAG+KivqkdutMf1UhdNx175w=
|
google.golang.org/protobuf v1.30.0 h1:kPPoIgf3TsEvrm0PFe15JQ+570QVxYzEvvHqChK+cng=
|
||||||
google.golang.org/protobuf v1.28.1/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
google.golang.org/protobuf v1.30.0/go.mod h1:HV8QOd/L58Z+nl8r43ehVNZIU/HEI6OcFqwMG9pJV4I=
|
||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
|
||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
|
||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0 h1:1Lc07Kr7qY4U2YPouBjpCLxpiyxIVoxqXgkXLknAOE8=
|
|
||||||
gopkg.in/natefinch/lumberjack.v2 v2.0.0/go.mod h1:l0ndWWf7gzL7RNwBG7wST/UCcT4T24xpD6X8LsfU/+k=
|
|
||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
gopkg.in/yaml.v2 v2.2.7/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||||
@@ -395,45 +425,20 @@ gopkg.in/yaml.v2 v2.3.0/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
|||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
|
||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0-20200615113413-eeeca48fe776/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
|
||||||
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0-20210107192922-496545a6307b/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.0/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
gopkg.in/yaml.v3 v3.0.1 h1:fxVm/GzAzEWqLHuvctI91KS9hhNmmWOoWu0XTYJS7CA=
|
||||||
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
gopkg.in/yaml.v3 v3.0.1/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
|
||||||
gorm.io/gorm v1.24.2/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
|
gorm.io/gorm v1.24.6 h1:wy98aq9oFEetsc4CAbKD2SoBCdMzsbSIvSUUFJuHi5s=
|
||||||
gorm.io/gorm v1.24.3 h1:WL2ifUmzR/SLp85CSURAfybcHnGZ+yLSGSxgYXlFBHg=
|
gorm.io/gorm v1.24.6/go.mod h1:L4uxeKpfBml98NYqVqwAdmV1a2nBtAec/cf3fpucW/k=
|
||||||
gorm.io/gorm v1.24.3/go.mod h1:DVrVomtaYTbqs7gB/x2uVvqnXzv0nqjB396B8cG4dBA=
|
|
||||||
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
gotest.tools v2.2.0+incompatible h1:VsBPFP1AI068pPrMxtb/S8Zkgf9xEmTLJjfM+P5UIEo=
|
||||||
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
gotest.tools v2.2.0+incompatible/go.mod h1:DsYFclhRJ6vuDpmuTbkuFWG+y2sxOXAzmJt81HFBacw=
|
||||||
gotest.tools/v3 v3.3.0 h1:MfDY1b1/0xN1CyMlQDac0ziEy9zJQd9CXBRRDHw2jJo=
|
modernc.org/libc v1.22.3 h1:D/g6O5ftAfavceqlLOFwaZuA5KYafKwmr30A6iSqoyY=
|
||||||
lukechampine.com/uint128 v1.1.1/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
modernc.org/libc v1.22.3/go.mod h1:MQrloYP209xa2zHome2a8HLiLm6k0UT8CoHpV74tOFw=
|
||||||
lukechampine.com/uint128 v1.2.0/go.mod h1:c4eWIwlEGaxC/+H1VguhU4PHXNWDCDMUlWdIWl2j1gk=
|
|
||||||
modernc.org/cc/v3 v3.37.0/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20=
|
|
||||||
modernc.org/cc/v3 v3.38.1/go.mod h1:vtL+3mdHx/wcj3iEGz84rQa8vEqR6XM84v5Lcvfph20=
|
|
||||||
modernc.org/cc/v3 v3.40.0/go.mod h1:/bTg4dnWkSXowUO6ssQKnOV0yMVxDYNIsIrzqTFDGH0=
|
|
||||||
modernc.org/ccgo/v3 v3.0.0-20220904174949-82d86e1b6d56/go.mod h1:YSXjPL62P2AMSxBphRHPn7IkzhVHqkvOnRKAKh+W6ZI=
|
|
||||||
modernc.org/ccgo/v3 v3.0.0-20220910160915-348f15de615a/go.mod h1:8p47QxPkdugex9J4n9P2tLZ9bK01yngIVp00g4nomW0=
|
|
||||||
modernc.org/ccgo/v3 v3.16.13-0.20221017192402-261537637ce8/go.mod h1:fUB3Vn0nVPReA+7IG7yZDfjv1TMWjhQP8gCxrFAtL5g=
|
|
||||||
modernc.org/ccgo/v3 v3.16.13/go.mod h1:2Quk+5YgpImhPjv2Qsob1DnZ/4som1lJTodubIcoUkY=
|
|
||||||
modernc.org/ccorpus v1.11.6/go.mod h1:2gEUTrWqdpH2pXsmTM1ZkjeSrUWDpjMu2T6m29L/ErQ=
|
|
||||||
modernc.org/httpfs v1.0.6/go.mod h1:7dosgurJGp0sPaRanU53W4xZYKh14wfzX420oZADeHM=
|
|
||||||
modernc.org/libc v1.17.4/go.mod h1:WNg2ZH56rDEwdropAJeZPQkXmDwh+JCA1s/htl6r2fA=
|
|
||||||
modernc.org/libc v1.18.0/go.mod h1:vj6zehR5bfc98ipowQOM2nIDUZnVew/wNC/2tOGS+q0=
|
|
||||||
modernc.org/libc v1.19.0/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0=
|
|
||||||
modernc.org/libc v1.20.3/go.mod h1:ZRfIaEkgrYgZDl6pa4W39HgN5G/yDW+NRmNKZBDFrk0=
|
|
||||||
modernc.org/libc v1.21.4/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI=
|
|
||||||
modernc.org/libc v1.21.5 h1:xBkU9fnHV+hvZuPSRszN0AXDG4M7nwPLwTWwkYcvLCI=
|
|
||||||
modernc.org/libc v1.21.5/go.mod h1:przBsL5RDOZajTVslkugzLBj1evTue36jEomFQOoYuI=
|
|
||||||
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
modernc.org/mathutil v1.5.0 h1:rV0Ko/6SfM+8G+yKiyI830l3Wuz1zRutdslNoQ0kfiQ=
|
||||||
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
modernc.org/mathutil v1.5.0/go.mod h1:mZW8CKdRPY1v87qxC/wUdX5O1qDzXMP5TH3wjfpga6E=
|
||||||
modernc.org/memory v1.3.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
modernc.org/memory v1.5.0 h1:N+/8c5rE6EqugZwHii4IFsaJ7MUhoWX07J5tC/iI5Ds=
|
||||||
modernc.org/memory v1.4.0 h1:crykUfNSnMAXaOJnnxcSzbUGMqkLWjklJKkBK2nwZwk=
|
modernc.org/memory v1.5.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
||||||
modernc.org/memory v1.4.0/go.mod h1:PkUhL0Mugw21sHPeskwZW4D6VscE/GQJOnIpCnW6pSU=
|
modernc.org/sqlite v1.21.0 h1:4aP4MdUf15i3R3M2mx6Q90WHKz3nZLoz96zlB6tNdow=
|
||||||
modernc.org/opt v0.1.1/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
modernc.org/sqlite v1.21.0/go.mod h1:XwQ0wZPIh1iKb5mkvCJ3szzbhk+tykC8ZWqTRTgYRwI=
|
||||||
modernc.org/opt v0.1.3/go.mod h1:WdSiB5evDcignE70guQKxYUl14mgWtbClRi5wmkkTX0=
|
rsc.io/pdf v0.1.1/go.mod h1:n8OzWcQ6Sp37PL01nO98y4iUCRdTGarVfzxY20ICaU4=
|
||||||
modernc.org/sqlite v1.20.0 h1:80zmD3BGkm8BZ5fUi/4lwJQHiO3GXgIUvZRXpoIfROY=
|
|
||||||
modernc.org/sqlite v1.20.0/go.mod h1:EsYz8rfOvLCiYTy5ZFsOYzoCcRMu98YYkwAcCw5YIYw=
|
|
||||||
modernc.org/strutil v1.1.3/go.mod h1:MEHNA7PdEnEwLvspRMtWTNnp2nnyvMfkimT1NKNAGbw=
|
|
||||||
modernc.org/tcl v1.15.0/go.mod h1:xRoGotBZ6dU+Zo2tca+2EqVEeMmOUBzHnhIwq4YrVnE=
|
|
||||||
modernc.org/token v1.0.1/go.mod h1:UGzOrNV1mAFSEB63lOFHIpNRUVMvYTc6yu1SMY/XTDM=
|
|
||||||
modernc.org/z v1.7.0/go.mod h1:hVdgNMh8ggTuRG1rGU8x+xGRFfiQUIAw0ZqlPy8+HyQ=
|
|
||||||
|
|||||||
@@ -17,8 +17,8 @@ type Driver interface {
|
|||||||
type Meta interface {
|
type Meta interface {
|
||||||
Config() Config
|
Config() Config
|
||||||
// GetStorage just get raw storage, no need to implement, because model.Storage have implemented
|
// GetStorage just get raw storage, no need to implement, because model.Storage have implemented
|
||||||
GetStorage() *model.Storage
|
GetStorage() *model.StorageA
|
||||||
SetStorage(model.Storage)
|
SetStorage(model.StorageA)
|
||||||
// GetAddition Additional is used for unmarshal of JSON, so need return pointer
|
// GetAddition Additional is used for unmarshal of JSON, so need return pointer
|
||||||
GetAddition() Additional
|
GetAddition() Additional
|
||||||
// Init If already initialized, drop first
|
// Init If already initialized, drop first
|
||||||
|
|||||||
@@ -1,545 +0,0 @@
|
|||||||
package op
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"os"
|
|
||||||
stdpath "path"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/generic_sync"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/singleflight"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils"
|
|
||||||
"github.com/Xhofe/go-cache"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
pkgerr "github.com/pkg/errors"
|
|
||||||
log "github.com/sirupsen/logrus"
|
|
||||||
)
|
|
||||||
|
|
||||||
// In order to facilitate adding some other things before and after file op
|
|
||||||
|
|
||||||
var listCache = cache.NewMemCache(cache.WithShards[[]model.Obj](64))
|
|
||||||
var listG singleflight.Group[[]model.Obj]
|
|
||||||
|
|
||||||
func updateCacheObj(storage driver.Driver, path string, oldObj model.Obj, newObj model.Obj) {
|
|
||||||
key := Key(storage, path)
|
|
||||||
objs, ok := listCache.Get(key)
|
|
||||||
if ok {
|
|
||||||
for i, obj := range objs {
|
|
||||||
if obj.GetName() == oldObj.GetName() {
|
|
||||||
objs[i] = newObj
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
listCache.Set(key, objs, cache.WithEx[[]model.Obj](time.Minute*time.Duration(storage.GetStorage().CacheExpiration)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func delCacheObj(storage driver.Driver, path string, obj model.Obj) {
|
|
||||||
key := Key(storage, path)
|
|
||||||
objs, ok := listCache.Get(key)
|
|
||||||
if ok {
|
|
||||||
for i, oldObj := range objs {
|
|
||||||
if oldObj.GetName() == obj.GetName() {
|
|
||||||
objs = append(objs[:i], objs[i+1:]...)
|
|
||||||
break
|
|
||||||
}
|
|
||||||
}
|
|
||||||
listCache.Set(key, objs, cache.WithEx[[]model.Obj](time.Minute*time.Duration(storage.GetStorage().CacheExpiration)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var addSortDebounceMap generic_sync.MapOf[string, func(func())]
|
|
||||||
|
|
||||||
func addCacheObj(storage driver.Driver, path string, newObj model.Obj) {
|
|
||||||
key := Key(storage, path)
|
|
||||||
objs, ok := listCache.Get(key)
|
|
||||||
if ok {
|
|
||||||
for i, obj := range objs {
|
|
||||||
if obj.GetName() == newObj.GetName() {
|
|
||||||
objs[i] = newObj
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// Simple separation of files and folders
|
|
||||||
if len(objs) > 0 && objs[len(objs)-1].IsDir() == newObj.IsDir() {
|
|
||||||
objs = append(objs, newObj)
|
|
||||||
} else {
|
|
||||||
objs = append([]model.Obj{newObj}, objs...)
|
|
||||||
}
|
|
||||||
|
|
||||||
if storage.Config().LocalSort {
|
|
||||||
debounce, _ := addSortDebounceMap.LoadOrStore(key, utils.NewDebounce(time.Minute))
|
|
||||||
log.Debug("addCacheObj: wait start sort")
|
|
||||||
debounce(func() {
|
|
||||||
log.Debug("addCacheObj: start sort")
|
|
||||||
model.SortFiles(objs, storage.GetStorage().OrderBy, storage.GetStorage().OrderDirection)
|
|
||||||
addSortDebounceMap.Delete(key)
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
listCache.Set(key, objs, cache.WithEx[[]model.Obj](time.Minute*time.Duration(storage.GetStorage().CacheExpiration)))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ClearCache(storage driver.Driver, path string) {
|
|
||||||
listCache.Del(Key(storage, path))
|
|
||||||
}
|
|
||||||
|
|
||||||
func Key(storage driver.Driver, path string) string {
|
|
||||||
return stdpath.Join(storage.GetStorage().MountPath, utils.FixAndCleanPath(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
// List files in storage, not contains virtual file
|
|
||||||
func List(ctx context.Context, storage driver.Driver, path string, args model.ListArgs, refresh ...bool) ([]model.Obj, error) {
|
|
||||||
if storage.Config().CheckStatus && storage.GetStorage().Status != WORK {
|
|
||||||
return nil, errors.Errorf("storage not init: %s", storage.GetStorage().Status)
|
|
||||||
}
|
|
||||||
path = utils.FixAndCleanPath(path)
|
|
||||||
log.Debugf("op.List %s", path)
|
|
||||||
key := Key(storage, path)
|
|
||||||
if !utils.IsBool(refresh...) {
|
|
||||||
if files, ok := listCache.Get(key); ok {
|
|
||||||
log.Debugf("use cache when list %s", path)
|
|
||||||
return files, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dir, err := GetUnwrap(ctx, storage, path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.WithMessage(err, "failed get dir")
|
|
||||||
}
|
|
||||||
log.Debugf("list dir: %+v", dir)
|
|
||||||
if !dir.IsDir() {
|
|
||||||
return nil, errors.WithStack(errors.New("not a folder"))
|
|
||||||
}
|
|
||||||
objs, err, _ := listG.Do(key, func() ([]model.Obj, error) {
|
|
||||||
files, err := storage.List(ctx, dir, args)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to list objs")
|
|
||||||
}
|
|
||||||
// set path
|
|
||||||
for _, f := range files {
|
|
||||||
if s, ok := f.(model.SetPath); ok && f.GetPath() == "" && dir.GetPath() != "" {
|
|
||||||
s.SetPath(stdpath.Join(dir.GetPath(), f.GetName()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// warp obj name
|
|
||||||
model.WrapObjsName(files)
|
|
||||||
// call hooks
|
|
||||||
go func(reqPath string, files []model.Obj) {
|
|
||||||
for _, hook := range ObjsUpdateHooks {
|
|
||||||
hook(args.ReqPath, files)
|
|
||||||
}
|
|
||||||
}(args.ReqPath, files)
|
|
||||||
|
|
||||||
// sort objs
|
|
||||||
if storage.Config().LocalSort {
|
|
||||||
model.SortFiles(files, storage.GetStorage().OrderBy, storage.GetStorage().OrderDirection)
|
|
||||||
}
|
|
||||||
model.ExtractFolder(files, storage.GetStorage().ExtractFolder)
|
|
||||||
|
|
||||||
if !storage.Config().NoCache {
|
|
||||||
if len(files) > 0 {
|
|
||||||
log.Debugf("set cache: %s => %+v", key, files)
|
|
||||||
listCache.Set(key, files, cache.WithEx[[]model.Obj](time.Minute*time.Duration(storage.GetStorage().CacheExpiration)))
|
|
||||||
} else {
|
|
||||||
log.Debugf("del cache: %s", key)
|
|
||||||
listCache.Del(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return files, nil
|
|
||||||
})
|
|
||||||
return objs, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get object from list of files
|
|
||||||
func Get(ctx context.Context, storage driver.Driver, path string) (model.Obj, error) {
|
|
||||||
path = utils.FixAndCleanPath(path)
|
|
||||||
log.Debugf("op.Get %s", path)
|
|
||||||
|
|
||||||
// is root folder
|
|
||||||
if utils.PathEqual(path, "/") {
|
|
||||||
var rootObj model.Obj
|
|
||||||
switch r := storage.GetAddition().(type) {
|
|
||||||
case driver.IRootId:
|
|
||||||
rootObj = &model.Object{
|
|
||||||
ID: r.GetRootId(),
|
|
||||||
Name: RootName,
|
|
||||||
Size: 0,
|
|
||||||
Modified: storage.GetStorage().Modified,
|
|
||||||
IsFolder: true,
|
|
||||||
Path: path,
|
|
||||||
}
|
|
||||||
case driver.IRootPath:
|
|
||||||
rootObj = &model.Object{
|
|
||||||
Path: r.GetRootPath(),
|
|
||||||
Name: RootName,
|
|
||||||
Size: 0,
|
|
||||||
Modified: storage.GetStorage().Modified,
|
|
||||||
IsFolder: true,
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if storage, ok := storage.(driver.Getter); ok {
|
|
||||||
obj, err := storage.GetRoot(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.WithMessage(err, "failed get root obj")
|
|
||||||
}
|
|
||||||
rootObj = obj
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if rootObj == nil {
|
|
||||||
return nil, errors.Errorf("please implement IRootPath or IRootId or Getter method")
|
|
||||||
}
|
|
||||||
return &model.ObjWrapName{
|
|
||||||
Name: RootName,
|
|
||||||
Obj: rootObj,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// not root folder
|
|
||||||
dir, name := stdpath.Split(path)
|
|
||||||
files, err := List(ctx, storage, dir, model.ListArgs{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.WithMessage(err, "failed get parent list")
|
|
||||||
}
|
|
||||||
for _, f := range files {
|
|
||||||
// TODO maybe copy obj here
|
|
||||||
if f.GetName() == name {
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
log.Debugf("cant find obj with name: %s", name)
|
|
||||||
return nil, errors.WithStack(errors.New("object not found"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetUnwrap(ctx context.Context, storage driver.Driver, path string) (model.Obj, error) {
|
|
||||||
obj, err := Get(ctx, storage, path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return model.UnwrapObjs(obj), err
|
|
||||||
}
|
|
||||||
|
|
||||||
var linkCache = cache.NewMemCache(cache.WithShards[*model.Link](16))
|
|
||||||
var linkG singleflight.Group[*model.Link]
|
|
||||||
|
|
||||||
// Link get link, if is an url. should have an expiry time
|
|
||||||
func Link(ctx context.Context, storage driver.Driver, path string, args model.LinkArgs) (*model.Link, model.Obj, error) {
|
|
||||||
if storage.Config().CheckStatus && storage.GetStorage().Status != WORK {
|
|
||||||
return nil, nil, errors.Errorf("storage not init: %s", storage.GetStorage().Status)
|
|
||||||
}
|
|
||||||
file, err := GetUnwrap(ctx, storage, path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, errors.WithMessage(err, "failed to get file")
|
|
||||||
}
|
|
||||||
if file.IsDir() {
|
|
||||||
return nil, nil, errors.WithStack(errors.New("not a file"))
|
|
||||||
}
|
|
||||||
key := Key(storage, path) + ":" + args.IP
|
|
||||||
if link, ok := linkCache.Get(key); ok {
|
|
||||||
return link, file, nil
|
|
||||||
}
|
|
||||||
fn := func() (*model.Link, error) {
|
|
||||||
link, err := storage.Link(ctx, file, args)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed get link")
|
|
||||||
}
|
|
||||||
if link.Expiration != nil {
|
|
||||||
linkCache.Set(key, link, cache.WithEx[*model.Link](*link.Expiration))
|
|
||||||
}
|
|
||||||
return link, nil
|
|
||||||
}
|
|
||||||
link, err, _ := linkG.Do(key, fn)
|
|
||||||
return link, file, err
|
|
||||||
}
|
|
||||||
|
|
||||||
// Other api
|
|
||||||
func Other(ctx context.Context, storage driver.Driver, args model.FsOtherArgs) (interface{}, error) {
|
|
||||||
obj, err := GetUnwrap(ctx, storage, args.Path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.WithMessagef(err, "failed to get obj")
|
|
||||||
}
|
|
||||||
if o, ok := storage.(driver.Other); ok {
|
|
||||||
return o.Other(ctx, model.OtherArgs{
|
|
||||||
Obj: obj,
|
|
||||||
Method: args.Method,
|
|
||||||
Data: args.Data,
|
|
||||||
})
|
|
||||||
} else {
|
|
||||||
return nil, errors.New("not implement")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
var mkdirG singleflight.Group[interface{}]
|
|
||||||
|
|
||||||
func MakeDir(ctx context.Context, storage driver.Driver, path string, lazyCache ...bool) error {
|
|
||||||
if storage.Config().CheckStatus && storage.GetStorage().Status != WORK {
|
|
||||||
return errors.Errorf("storage not init: %s", storage.GetStorage().Status)
|
|
||||||
}
|
|
||||||
path = utils.FixAndCleanPath(path)
|
|
||||||
key := Key(storage, path)
|
|
||||||
_, err, _ := mkdirG.Do(key, func() (interface{}, error) {
|
|
||||||
// check if dir exists
|
|
||||||
f, err := GetUnwrap(ctx, storage, path)
|
|
||||||
if err != nil {
|
|
||||||
if errors.Is(pkgerr.Cause(err), errors.New("object not found")) {
|
|
||||||
parentPath, dirName := stdpath.Split(path)
|
|
||||||
err = MakeDir(ctx, storage, parentPath)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.WithMessagef(err, "failed to make parent dir [%s]", parentPath)
|
|
||||||
}
|
|
||||||
parentDir, err := GetUnwrap(ctx, storage, parentPath)
|
|
||||||
// this should not happen
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.WithMessagef(err, "failed to get parent dir [%s]", parentPath)
|
|
||||||
}
|
|
||||||
|
|
||||||
switch s := storage.(type) {
|
|
||||||
case driver.MkdirResult:
|
|
||||||
var newObj model.Obj
|
|
||||||
newObj, err = s.MakeDir(ctx, parentDir, dirName)
|
|
||||||
if err == nil {
|
|
||||||
if newObj != nil {
|
|
||||||
addCacheObj(storage, parentPath, model.WrapObjName(newObj))
|
|
||||||
} else if !utils.IsBool(lazyCache...) {
|
|
||||||
ClearCache(storage, parentPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case driver.Mkdir:
|
|
||||||
err = s.MakeDir(ctx, parentDir, dirName)
|
|
||||||
if err == nil && !utils.IsBool(lazyCache...) {
|
|
||||||
ClearCache(storage, parentPath)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return nil, errors.New("not implement")
|
|
||||||
}
|
|
||||||
return nil, errors.WithStack(err)
|
|
||||||
}
|
|
||||||
return nil, errors.WithMessage(err, "failed to check if dir exists")
|
|
||||||
}
|
|
||||||
// dir exists
|
|
||||||
if f.IsDir() {
|
|
||||||
return nil, nil
|
|
||||||
}
|
|
||||||
// dir to make is a file
|
|
||||||
return nil, errors.New("file exists")
|
|
||||||
})
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func Move(ctx context.Context, storage driver.Driver, srcPath, dstDirPath string, lazyCache ...bool) error {
|
|
||||||
if storage.Config().CheckStatus && storage.GetStorage().Status != WORK {
|
|
||||||
return errors.Errorf("storage not init: %s", storage.GetStorage().Status)
|
|
||||||
}
|
|
||||||
srcPath = utils.FixAndCleanPath(srcPath)
|
|
||||||
dstDirPath = utils.FixAndCleanPath(dstDirPath)
|
|
||||||
srcRawObj, err := Get(ctx, storage, srcPath)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithMessage(err, "failed to get src object")
|
|
||||||
}
|
|
||||||
srcObj := model.UnwrapObjs(srcRawObj)
|
|
||||||
dstDir, err := GetUnwrap(ctx, storage, dstDirPath)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithMessage(err, "failed to get dst dir")
|
|
||||||
}
|
|
||||||
srcDirPath := stdpath.Dir(srcPath)
|
|
||||||
|
|
||||||
switch s := storage.(type) {
|
|
||||||
case driver.MoveResult:
|
|
||||||
var newObj model.Obj
|
|
||||||
newObj, err = s.Move(ctx, srcObj, dstDir)
|
|
||||||
if err == nil {
|
|
||||||
delCacheObj(storage, srcDirPath, srcRawObj)
|
|
||||||
if newObj != nil {
|
|
||||||
addCacheObj(storage, dstDirPath, model.WrapObjName(newObj))
|
|
||||||
} else if !utils.IsBool(lazyCache...) {
|
|
||||||
ClearCache(storage, dstDirPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case driver.Move:
|
|
||||||
err = s.Move(ctx, srcObj, dstDir)
|
|
||||||
if err == nil {
|
|
||||||
delCacheObj(storage, srcDirPath, srcRawObj)
|
|
||||||
if !utils.IsBool(lazyCache...) {
|
|
||||||
ClearCache(storage, dstDirPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return errors.New("not implement")
|
|
||||||
}
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Rename(ctx context.Context, storage driver.Driver, srcPath, dstName string, lazyCache ...bool) error {
|
|
||||||
if storage.Config().CheckStatus && storage.GetStorage().Status != WORK {
|
|
||||||
return errors.Errorf("storage not init: %s", storage.GetStorage().Status)
|
|
||||||
}
|
|
||||||
srcPath = utils.FixAndCleanPath(srcPath)
|
|
||||||
srcRawObj, err := Get(ctx, storage, srcPath)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithMessage(err, "failed to get src object")
|
|
||||||
}
|
|
||||||
srcObj := model.UnwrapObjs(srcRawObj)
|
|
||||||
srcDirPath := stdpath.Dir(srcPath)
|
|
||||||
|
|
||||||
switch s := storage.(type) {
|
|
||||||
case driver.RenameResult:
|
|
||||||
var newObj model.Obj
|
|
||||||
newObj, err = s.Rename(ctx, srcObj, dstName)
|
|
||||||
if err == nil {
|
|
||||||
if newObj != nil {
|
|
||||||
updateCacheObj(storage, srcDirPath, srcRawObj, model.WrapObjName(newObj))
|
|
||||||
} else if !utils.IsBool(lazyCache...) {
|
|
||||||
ClearCache(storage, srcDirPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case driver.Rename:
|
|
||||||
err = s.Rename(ctx, srcObj, dstName)
|
|
||||||
if err == nil && !utils.IsBool(lazyCache...) {
|
|
||||||
ClearCache(storage, srcDirPath)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return errors.New("not implement")
|
|
||||||
}
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
// Copy Just copy file[s] in a storage
|
|
||||||
func Copy(ctx context.Context, storage driver.Driver, srcPath, dstDirPath string, lazyCache ...bool) error {
|
|
||||||
if storage.Config().CheckStatus && storage.GetStorage().Status != WORK {
|
|
||||||
return errors.Errorf("storage not init: %s", storage.GetStorage().Status)
|
|
||||||
}
|
|
||||||
srcPath = utils.FixAndCleanPath(srcPath)
|
|
||||||
dstDirPath = utils.FixAndCleanPath(dstDirPath)
|
|
||||||
srcObj, err := GetUnwrap(ctx, storage, srcPath)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithMessage(err, "failed to get src object")
|
|
||||||
}
|
|
||||||
dstDir, err := GetUnwrap(ctx, storage, dstDirPath)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithMessage(err, "failed to get dst dir")
|
|
||||||
}
|
|
||||||
|
|
||||||
switch s := storage.(type) {
|
|
||||||
case driver.CopyResult:
|
|
||||||
var newObj model.Obj
|
|
||||||
newObj, err = s.Copy(ctx, srcObj, dstDir)
|
|
||||||
if err == nil {
|
|
||||||
if newObj != nil {
|
|
||||||
addCacheObj(storage, dstDirPath, model.WrapObjName(newObj))
|
|
||||||
} else if !utils.IsBool(lazyCache...) {
|
|
||||||
ClearCache(storage, dstDirPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case driver.Copy:
|
|
||||||
err = s.Copy(ctx, srcObj, dstDir)
|
|
||||||
if err == nil && !utils.IsBool(lazyCache...) {
|
|
||||||
ClearCache(storage, dstDirPath)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return errors.New("not implement")
|
|
||||||
}
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Remove(ctx context.Context, storage driver.Driver, path string) error {
|
|
||||||
if storage.Config().CheckStatus && storage.GetStorage().Status != WORK {
|
|
||||||
return errors.Errorf("storage not init: %s", storage.GetStorage().Status)
|
|
||||||
}
|
|
||||||
path = utils.FixAndCleanPath(path)
|
|
||||||
rawObj, err := Get(ctx, storage, path)
|
|
||||||
if err != nil {
|
|
||||||
// if object not found, it's ok
|
|
||||||
if errors.Is(pkgerr.Cause(err), errors.New("object not found")) {
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
return errors.WithMessage(err, "failed to get object")
|
|
||||||
}
|
|
||||||
dirPath := stdpath.Dir(path)
|
|
||||||
|
|
||||||
switch s := storage.(type) {
|
|
||||||
case driver.Remove:
|
|
||||||
err = s.Remove(ctx, model.UnwrapObjs(rawObj))
|
|
||||||
if err == nil {
|
|
||||||
delCacheObj(storage, dirPath, rawObj)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return errors.New("not implement")
|
|
||||||
}
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Put(ctx context.Context, storage driver.Driver, dstDirPath string, file *model.FileStream, up driver.UpdateProgress, lazyCache ...bool) error {
|
|
||||||
if storage.Config().CheckStatus && storage.GetStorage().Status != WORK {
|
|
||||||
return errors.Errorf("storage not init: %s", storage.GetStorage().Status)
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
if f, ok := file.GetReadCloser().(*os.File); ok {
|
|
||||||
err := os.RemoveAll(f.Name())
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed to remove file [%s]", f.Name())
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
defer func() {
|
|
||||||
if err := file.Close(); err != nil {
|
|
||||||
log.Errorf("failed to close file streamer, %v", err)
|
|
||||||
}
|
|
||||||
}()
|
|
||||||
// if file exist and size = 0, delete it
|
|
||||||
dstDirPath = utils.FixAndCleanPath(dstDirPath)
|
|
||||||
dstPath := stdpath.Join(dstDirPath, file.GetName())
|
|
||||||
fi, err := GetUnwrap(ctx, storage, dstPath)
|
|
||||||
if err == nil {
|
|
||||||
if fi.GetSize() == 0 {
|
|
||||||
err = Remove(ctx, storage, dstPath)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithMessagef(err, "failed remove file that exist and have size 0")
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
file.Old = fi
|
|
||||||
}
|
|
||||||
}
|
|
||||||
err = MakeDir(ctx, storage, dstDirPath)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithMessagef(err, "failed to make dir [%s]", dstDirPath)
|
|
||||||
}
|
|
||||||
parentDir, err := GetUnwrap(ctx, storage, dstDirPath)
|
|
||||||
// this should not happen
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithMessagef(err, "failed to get dir [%s]", dstDirPath)
|
|
||||||
}
|
|
||||||
// if up is nil, set a default to prevent panic
|
|
||||||
if up == nil {
|
|
||||||
up = func(p int) {}
|
|
||||||
}
|
|
||||||
|
|
||||||
switch s := storage.(type) {
|
|
||||||
case driver.PutResult:
|
|
||||||
var newObj model.Obj
|
|
||||||
newObj, err = s.Put(ctx, parentDir, file, up)
|
|
||||||
if err == nil {
|
|
||||||
if newObj != nil {
|
|
||||||
addCacheObj(storage, dstDirPath, model.WrapObjName(newObj))
|
|
||||||
} else if !utils.IsBool(lazyCache...) {
|
|
||||||
ClearCache(storage, dstDirPath)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
case driver.Put:
|
|
||||||
err = s.Put(ctx, parentDir, file, up)
|
|
||||||
if err == nil && !utils.IsBool(lazyCache...) {
|
|
||||||
ClearCache(storage, dstDirPath)
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
return errors.New("not implement")
|
|
||||||
}
|
|
||||||
log.Debugf("put file [%s] done", file.GetName())
|
|
||||||
//if err == nil {
|
|
||||||
// //clear cache
|
|
||||||
// key := stdpath.Join(storage.GetStorage().MountPath, dstDirPath)
|
|
||||||
// listCache.Del(key)
|
|
||||||
//}
|
|
||||||
return errors.WithStack(err)
|
|
||||||
}
|
|
||||||
26
main.go
26
main.go
@@ -30,8 +30,7 @@ import (
|
|||||||
"github.com/coreos/go-systemd/daemon"
|
"github.com/coreos/go-systemd/daemon"
|
||||||
"go.uber.org/zap"
|
"go.uber.org/zap"
|
||||||
|
|
||||||
_ "github.com/IceWhaleTech/CasaOS/drivers"
|
"github.com/robfig/cron/v3"
|
||||||
"github.com/robfig/cron"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -79,8 +78,12 @@ func init() {
|
|||||||
service.Cache = cache.Init()
|
service.Cache = cache.Init()
|
||||||
|
|
||||||
service.GetCPUThermalZone()
|
service.GetCPUThermalZone()
|
||||||
service.MyService.Storages().InitStorages()
|
|
||||||
route.InitFunction()
|
route.InitFunction()
|
||||||
|
|
||||||
|
///
|
||||||
|
// service.MountLists = make(map[string]*mountlib.MountPoint)
|
||||||
|
// configfile.Install()
|
||||||
}
|
}
|
||||||
|
|
||||||
// @title casaOS API
|
// @title casaOS API
|
||||||
@@ -115,18 +118,13 @@ func main() {
|
|||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|
||||||
cron2 := cron.New()
|
crontab := cron.New(cron.WithSeconds())
|
||||||
// every day execution
|
if _, err := crontab.AddFunc("@every 5s", route.SendAllHardwareStatusBySocket); err != nil {
|
||||||
|
logger.Error("add crontab error", zap.Error(err))
|
||||||
err := cron2.AddFunc("0/5 * * * * *", func() {
|
|
||||||
route.SendAllHardwareStatusBySocket()
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
fmt.Println(err)
|
|
||||||
}
|
}
|
||||||
cron2.Start()
|
|
||||||
|
|
||||||
defer cron2.Stop()
|
crontab.Start()
|
||||||
|
defer crontab.Stop()
|
||||||
|
|
||||||
listener, err := net.Listen("tcp", net.JoinHostPort(LOCALHOST, "0"))
|
listener, err := net.Listen("tcp", net.JoinHostPort(LOCALHOST, "0"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -225,7 +223,7 @@ func main() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("CasaOS main service is listening...", zap.Any("address", listener.Addr().String()))
|
logger.Info("CasaOS main service is listening...", zap.Any("address", listener.Addr().String()))
|
||||||
|
// defer service.MyService.Storage().UnmountAllStorage()
|
||||||
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)
|
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 {
|
if err != nil {
|
||||||
panic(err)
|
panic(err)
|
||||||
|
|||||||
@@ -2,7 +2,7 @@ package model
|
|||||||
|
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type Storage struct {
|
type StorageA struct {
|
||||||
ID uint `json:"id" gorm:"primaryKey"` // unique key
|
ID uint `json:"id" gorm:"primaryKey"` // unique key
|
||||||
MountPath string `json:"mount_path" gorm:"unique" binding:"required"` // must be standardized
|
MountPath string `json:"mount_path" gorm:"unique" binding:"required"` // must be standardized
|
||||||
Order int `json:"order"` // use to sort
|
Order int `json:"order"` // use to sort
|
||||||
@@ -29,15 +29,15 @@ type Proxy struct {
|
|||||||
DownProxyUrl string `json:"down_proxy_url"`
|
DownProxyUrl string `json:"down_proxy_url"`
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) GetStorage() *Storage {
|
func (s *StorageA) GetStorage() *StorageA {
|
||||||
return s
|
return s
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) SetStorage(storage Storage) {
|
func (s *StorageA) SetStorage(storage StorageA) {
|
||||||
*s = storage
|
*s = storage
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Storage) SetStatus(status string) {
|
func (s *StorageA) SetStatus(status string) {
|
||||||
s.Status = status
|
s.Status = status
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -11,14 +11,12 @@
|
|||||||
package sqlite
|
package sqlite
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"fmt"
|
||||||
"time"
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
"github.com/glebarez/sqlite"
|
"github.com/glebarez/sqlite"
|
||||||
"go.uber.org/zap"
|
|
||||||
"gorm.io/gorm"
|
"gorm.io/gorm"
|
||||||
)
|
)
|
||||||
|
|
||||||
@@ -33,23 +31,24 @@ func GetDb(dbPath string) *gorm.DB {
|
|||||||
// db, err := gorm.Open(mysql2.Open(dsn), &gorm.Config{})
|
// db, err := gorm.Open(mysql2.Open(dsn), &gorm.Config{})
|
||||||
file.IsNotExistMkDir(dbPath)
|
file.IsNotExistMkDir(dbPath)
|
||||||
db, err := gorm.Open(sqlite.Open(dbPath+"/casaOS.db"), &gorm.Config{})
|
db, err := gorm.Open(sqlite.Open(dbPath+"/casaOS.db"), &gorm.Config{})
|
||||||
|
if err != nil {
|
||||||
|
panic("sqlite connect error")
|
||||||
|
}
|
||||||
|
|
||||||
c, _ := db.DB()
|
c, _ := db.DB()
|
||||||
c.SetMaxIdleConns(10)
|
c.SetMaxIdleConns(10)
|
||||||
c.SetMaxOpenConns(1)
|
c.SetMaxOpenConns(1)
|
||||||
c.SetConnMaxIdleTime(time.Second * 1000)
|
c.SetConnMaxIdleTime(time.Second * 1000)
|
||||||
if err != nil {
|
|
||||||
logger.Error("sqlite connect error", zap.Any("db connect error", err))
|
|
||||||
panic("sqlite connect error")
|
|
||||||
}
|
|
||||||
gdb = db
|
gdb = db
|
||||||
|
|
||||||
err = db.AutoMigrate(&model2.AppNotify{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{}, model.Storage{})
|
err = db.AutoMigrate(&model2.AppNotify{}, model2.SharesDBModel{}, model2.ConnectionsDBModel{}, model2.PeerDriveDBModel{})
|
||||||
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
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")
|
||||||
db.Exec("DROP TABLE IF EXISTS o_person_down_record")
|
db.Exec("DROP TABLE IF EXISTS o_person_down_record")
|
||||||
if err != nil {
|
|
||||||
logger.Error("check or create db error", zap.Any("error", err))
|
|
||||||
}
|
|
||||||
return db
|
return db
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -14,14 +14,18 @@ func OnlyExec(cmdStr string) {
|
|||||||
cmd := exec.Command("/bin/bash", "-c", cmdStr)
|
cmd := exec.Command("/bin/bash", "-c", cmdStr)
|
||||||
stdout, err := cmd.StdoutPipe()
|
stdout, err := cmd.StdoutPipe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer stdout.Close()
|
defer stdout.Close()
|
||||||
if err := cmd.Start(); err != nil {
|
if err := cmd.Start(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
cmd.Wait()
|
|
||||||
return
|
if err := cmd.Wait(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ExecResultStrArray(cmdStr string) []string {
|
func ExecResultStrArray(cmdStr string) []string {
|
||||||
@@ -49,7 +53,11 @@ func ExecResultStrArray(cmdStr string) []string {
|
|||||||
}
|
}
|
||||||
networklist = append(networklist, string(output))
|
networklist = append(networklist, string(output))
|
||||||
}
|
}
|
||||||
cmd.Wait()
|
|
||||||
|
if err := cmd.Wait(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
return networklist
|
return networklist
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -68,11 +76,15 @@ func ExecResultStr(cmdStr string) string {
|
|||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
str, err := ioutil.ReadAll(stdout)
|
str, err := ioutil.ReadAll(stdout)
|
||||||
cmd.Wait()
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
return ""
|
return ""
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if err := cmd.Wait(); err != nil {
|
||||||
|
fmt.Println(err)
|
||||||
|
}
|
||||||
|
|
||||||
return string(str)
|
return string(str)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,23 @@
|
|||||||
package command
|
package command_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"os"
|
"os"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/command"
|
||||||
|
"go.uber.org/goleak"
|
||||||
"gotest.tools/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestExecuteScripts(t *testing.T) {
|
func TestExecuteScripts(t *testing.T) {
|
||||||
|
goleak.VerifyNone(t)
|
||||||
|
|
||||||
// make a temp directory
|
// make a temp directory
|
||||||
tmpDir, err := os.MkdirTemp("", "casaos-test-*")
|
tmpDir, err := os.MkdirTemp("", "casaos-test-*")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
defer os.RemoveAll(tmpDir)
|
defer os.RemoveAll(tmpDir)
|
||||||
|
|
||||||
ExecuteScripts(tmpDir)
|
command.ExecuteScripts(tmpDir)
|
||||||
|
|
||||||
// create a sample script under tmpDir
|
// create a sample script under tmpDir
|
||||||
script := tmpDir + "/test.sh"
|
script := tmpDir + "/test.sh"
|
||||||
@@ -25,5 +29,5 @@ func TestExecuteScripts(t *testing.T) {
|
|||||||
_, err = f.WriteString("#!/bin/bash\necho 123")
|
_, err = f.WriteString("#!/bin/bash\necho 123")
|
||||||
assert.NilError(t, err)
|
assert.NilError(t, err)
|
||||||
|
|
||||||
ExecuteScripts(tmpDir)
|
command.ExecuteScripts(tmpDir)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,6 +2,7 @@ package file
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"bufio"
|
"bufio"
|
||||||
|
"bytes"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
@@ -596,3 +597,146 @@ func NameAccumulation(name string, dir string) string {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func ParseFileHeader(h []byte, boundary []byte) (map[string]string, bool) {
|
||||||
|
arr := bytes.Split(h, boundary)
|
||||||
|
//var out_header FileHeader
|
||||||
|
//out_header.ContentLength = -1
|
||||||
|
const (
|
||||||
|
CONTENT_DISPOSITION = "Content-Disposition: "
|
||||||
|
NAME = "name=\""
|
||||||
|
FILENAME = "filename=\""
|
||||||
|
CONTENT_TYPE = "Content-Type: "
|
||||||
|
CONTENT_LENGTH = "Content-Length: "
|
||||||
|
)
|
||||||
|
result := make(map[string]string)
|
||||||
|
for _, item := range arr {
|
||||||
|
|
||||||
|
tarr := bytes.Split(item, []byte(";"))
|
||||||
|
if len(tarr) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
tbyte := tarr[1]
|
||||||
|
fmt.Println(string(tbyte))
|
||||||
|
tbyte = bytes.ReplaceAll(tbyte, []byte("\r\n--"), []byte(""))
|
||||||
|
tbyte = bytes.ReplaceAll(tbyte, []byte("name=\""), []byte(""))
|
||||||
|
tempArr := bytes.Split(tbyte, []byte("\"\r\n\r\n"))
|
||||||
|
if len(tempArr) != 2 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
bytes.HasPrefix(item, []byte("name="))
|
||||||
|
result[strings.TrimSpace(string(tempArr[0]))] = strings.TrimSpace(string(tempArr[1]))
|
||||||
|
}
|
||||||
|
// for _, item := range arr {
|
||||||
|
// if bytes.HasPrefix(item, []byte(CONTENT_DISPOSITION)) {
|
||||||
|
// l := len(CONTENT_DISPOSITION)
|
||||||
|
// arr1 := bytes.Split(item[l:], []byte("; "))
|
||||||
|
// out_header.ContentDisposition = string(arr1[0])
|
||||||
|
// if bytes.HasPrefix(arr1[1], []byte(NAME)) {
|
||||||
|
// out_header.Name = string(arr1[1][len(NAME) : len(arr1[1])-1])
|
||||||
|
// }
|
||||||
|
// l = len(arr1[2])
|
||||||
|
// if bytes.HasPrefix(arr1[2], []byte(FILENAME)) && arr1[2][l-1] == 0x22 {
|
||||||
|
// out_header.FileName = string(arr1[2][len(FILENAME) : l-1])
|
||||||
|
// }
|
||||||
|
// } else if bytes.HasPrefix(item, []byte(CONTENT_TYPE)) {
|
||||||
|
// l := len(CONTENT_TYPE)
|
||||||
|
// out_header.ContentType = string(item[l:])
|
||||||
|
// } else if bytes.HasPrefix(item, []byte(CONTENT_LENGTH)) {
|
||||||
|
// l := len(CONTENT_LENGTH)
|
||||||
|
// s := string(item[l:])
|
||||||
|
// content_length, err := strconv.ParseInt(s, 10, 64)
|
||||||
|
// if err != nil {
|
||||||
|
// log.Printf("content length error:%s", string(item))
|
||||||
|
// return out_header, false
|
||||||
|
// } else {
|
||||||
|
// out_header.ContentLength = content_length
|
||||||
|
// }
|
||||||
|
// } else {
|
||||||
|
// log.Printf("unknown:%s\n", string(item))
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
//fmt.Println(result)
|
||||||
|
// if len(out_header.FileName) == 0 {
|
||||||
|
// return out_header, false
|
||||||
|
// }
|
||||||
|
return result, true
|
||||||
|
}
|
||||||
|
|
||||||
|
func ReadToBoundary(boundary []byte, stream io.ReadCloser, target io.WriteCloser) ([]byte, bool, error) {
|
||||||
|
read_data := make([]byte, 1024*8)
|
||||||
|
read_data_len := 0
|
||||||
|
buf := make([]byte, 1024*4)
|
||||||
|
b_len := len(boundary)
|
||||||
|
reach_end := false
|
||||||
|
for !reach_end {
|
||||||
|
read_len, err := stream.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
if err != io.EOF && read_len <= 0 {
|
||||||
|
return nil, true, err
|
||||||
|
}
|
||||||
|
reach_end = true
|
||||||
|
}
|
||||||
|
|
||||||
|
copy(read_data[read_data_len:], buf[:read_len])
|
||||||
|
read_data_len += read_len
|
||||||
|
if read_data_len < b_len+4 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
loc := bytes.Index(read_data[:read_data_len], boundary)
|
||||||
|
if loc >= 0 {
|
||||||
|
|
||||||
|
target.Write(read_data[:loc-4])
|
||||||
|
return read_data[loc:read_data_len], reach_end, nil
|
||||||
|
}
|
||||||
|
target.Write(read_data[:read_data_len-b_len-4])
|
||||||
|
copy(read_data[0:], read_data[read_data_len-b_len-4:])
|
||||||
|
read_data_len = b_len + 4
|
||||||
|
}
|
||||||
|
target.Write(read_data[:read_data_len])
|
||||||
|
return nil, reach_end, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func ParseFromHead(read_data []byte, read_total int, boundary []byte, stream io.ReadCloser) (map[string]string, []byte, error) {
|
||||||
|
|
||||||
|
buf := make([]byte, 1024*8)
|
||||||
|
found_boundary := false
|
||||||
|
boundary_loc := -1
|
||||||
|
|
||||||
|
for {
|
||||||
|
read_len, err := stream.Read(buf)
|
||||||
|
if err != nil {
|
||||||
|
if err != io.EOF {
|
||||||
|
return nil, nil, err
|
||||||
|
}
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if read_total+read_len > cap(read_data) {
|
||||||
|
return nil, nil, fmt.Errorf("not found boundary")
|
||||||
|
}
|
||||||
|
copy(read_data[read_total:], buf[:read_len])
|
||||||
|
read_total += read_len
|
||||||
|
if !found_boundary {
|
||||||
|
boundary_loc = bytes.LastIndex(read_data[:read_total], boundary)
|
||||||
|
if boundary_loc == -1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
found_boundary = true
|
||||||
|
}
|
||||||
|
start_loc := boundary_loc + len(boundary)
|
||||||
|
fmt.Println(string(read_data))
|
||||||
|
file_head_loc := bytes.Index(read_data[start_loc:read_total], []byte("\r\n\r\n"))
|
||||||
|
if file_head_loc == -1 {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
file_head_loc += start_loc
|
||||||
|
ret := false
|
||||||
|
headMap, ret := ParseFileHeader(read_data, boundary)
|
||||||
|
if !ret {
|
||||||
|
return headMap, nil, fmt.Errorf("ParseFileHeader fail:%s", string(read_data[start_loc:file_head_loc]))
|
||||||
|
}
|
||||||
|
return headMap, read_data[file_head_loc+4 : read_total], nil
|
||||||
|
}
|
||||||
|
return nil, nil, fmt.Errorf("reach to sream EOF")
|
||||||
|
}
|
||||||
|
|||||||
@@ -3,9 +3,13 @@ package file
|
|||||||
import (
|
import (
|
||||||
"fmt"
|
"fmt"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"go.uber.org/goleak"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestNameAccumulation(t *testing.T) {
|
func TestNameAccumulation(t *testing.T) {
|
||||||
|
goleak.VerifyNone(t)
|
||||||
|
|
||||||
fmt.Println("aaa")
|
fmt.Println("aaa")
|
||||||
a := NameAccumulation("/mnt/test_1_1", "/")
|
a := NameAccumulation("/mnt/test_1_1", "/")
|
||||||
fmt.Println(a)
|
fmt.Println(a)
|
||||||
|
|||||||
@@ -13,12 +13,13 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
type MountList struct {
|
type MountList struct {
|
||||||
MountPoints []struct {
|
MountPoints []MountPoints `json:"mountPoints"`
|
||||||
MountPoint string `json:"MountPoint"`
|
}
|
||||||
Fs string `json:"Fs"`
|
type MountPoints struct {
|
||||||
Icon string `json:"Icon"`
|
MountPoint string `json:"MountPoint"`
|
||||||
Name string `json:"Name"`
|
Fs string `json:"Fs"`
|
||||||
} `json:"mountPoints"`
|
Icon string `json:"Icon"`
|
||||||
|
Name string `json:"Name"`
|
||||||
}
|
}
|
||||||
type MountPoint struct {
|
type MountPoint struct {
|
||||||
MountPoint string `json:"mount_point"`
|
MountPoint string `json:"mount_point"`
|
||||||
@@ -75,11 +76,13 @@ func GetMountList() (MountList, error) {
|
|||||||
}
|
}
|
||||||
return result, err
|
return result, err
|
||||||
}
|
}
|
||||||
|
|
||||||
func Mount(mountPoint string, fs string) error {
|
func Mount(mountPoint string, fs string) error {
|
||||||
res, err := NewRestyClient().R().SetFormData(map[string]string{
|
res, err := NewRestyClient().R().SetFormData(map[string]string{
|
||||||
"mountPoint": mountPoint,
|
"mountPoint": mountPoint,
|
||||||
"fs": fs,
|
"fs": fs,
|
||||||
"mountOpt": `{"AllowOther": true}`,
|
"mountOpt": `{"AllowOther": true}`,
|
||||||
|
"vfsOpt": `{"CacheMode": 3}`,
|
||||||
}).Post("/mount/mount")
|
}).Post("/mount/mount")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
@@ -102,6 +105,7 @@ func Unmount(mountPoint string) error {
|
|||||||
logger.Error("then unmount failed", zap.Any("res", res.Body()))
|
logger.Error("then unmount failed", zap.Any("res", res.Body()))
|
||||||
return fmt.Errorf("unmount failed")
|
return fmt.Errorf("unmount failed")
|
||||||
}
|
}
|
||||||
|
|
||||||
logger.Info("unmount then", zap.Any("res", res.Body()))
|
logger.Info("unmount then", zap.Any("res", res.Body()))
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -10,21 +10,22 @@ import (
|
|||||||
func IsIPv4(address string) bool {
|
func IsIPv4(address string) bool {
|
||||||
return strings.Count(address, ":") < 2
|
return strings.Count(address, ":") < 2
|
||||||
}
|
}
|
||||||
|
|
||||||
func IsIPv6(address string) bool {
|
func IsIPv6(address string) bool {
|
||||||
return strings.Count(address, ":") >= 2
|
return strings.Count(address, ":") >= 2
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取外网ip
|
// 获取外网ip
|
||||||
func GetExternalIPV4() string {
|
func GetExternalIPV4() string {
|
||||||
return httper2.Get("https://api.ipify.org", nil)
|
return httper2.Get("https://api.ipify.org", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取外网ip
|
// 获取外网ip
|
||||||
func GetExternalIPV6() string {
|
func GetExternalIPV6() string {
|
||||||
return httper2.Get("https://api6.ipify.org", nil)
|
return httper2.Get("https://api6.ipify.org", nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
//获取本地ip
|
// 获取本地ip
|
||||||
func GetLoclIp() string {
|
func GetLoclIp() string {
|
||||||
addrs, err := net.InterfaceAddrs()
|
addrs, err := net.InterfaceAddrs()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -35,11 +36,11 @@ func GetLoclIp() string {
|
|||||||
if ipnet.IP.To4() != nil {
|
if ipnet.IP.To4() != nil {
|
||||||
return ipnet.IP.String()
|
return ipnet.IP.String()
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return "127.0.0.1"
|
return "127.0.0.1"
|
||||||
}
|
}
|
||||||
|
|
||||||
func GetDeviceAllIP(port string) []string {
|
func GetDeviceAllIP(port string) []string {
|
||||||
var address []string
|
var address []string
|
||||||
addrs, err := net.InterfaceAddrs()
|
addrs, err := net.InterfaceAddrs()
|
||||||
@@ -60,7 +61,6 @@ func HasLocalIP(ip net.IP) bool {
|
|||||||
if ip.IsLoopback() {
|
if ip.IsLoopback() {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
ip.String()
|
|
||||||
|
|
||||||
ip4 := ip.To4()
|
ip4 := ip.To4()
|
||||||
if ip4 == nil {
|
if ip4 == nil {
|
||||||
|
|||||||
@@ -4,23 +4,28 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"net"
|
"net"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"go.uber.org/goleak"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestGetExternalIPV4(t *testing.T) {
|
func TestGetExternalIPV4(t *testing.T) {
|
||||||
|
goleak.VerifyNone(t)
|
||||||
|
|
||||||
ipv4 := make(chan string)
|
ipv4 := make(chan string)
|
||||||
go func() { ipv4 <- GetExternalIPV4() }()
|
go func() { ipv4 <- GetExternalIPV4() }()
|
||||||
fmt.Println(<-ipv4)
|
fmt.Println(<-ipv4)
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetExternalIPV6(t *testing.T) {
|
func TestGetExternalIPV6(t *testing.T) {
|
||||||
ipv6 := make(chan string)
|
ipv6 := make(chan string)
|
||||||
go func() { ipv6 <- GetExternalIPV6() }()
|
go func() { ipv6 <- GetExternalIPV6() }()
|
||||||
fmt.Println(<-ipv6)
|
fmt.Println(<-ipv6)
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestGetLoclIp(t *testing.T) {
|
func TestGetLoclIp(t *testing.T) {
|
||||||
fmt.Println(GetLoclIp())
|
fmt.Println(GetLoclIp())
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestHasLocalIP(t *testing.T) {
|
func TestHasLocalIP(t *testing.T) {
|
||||||
fmt.Println("dddd")
|
fmt.Println("dddd")
|
||||||
fmt.Println(HasLocalIP(net.ParseIP("192.168.2.10")))
|
fmt.Println(HasLocalIP(net.ParseIP("192.168.2.10")))
|
||||||
|
|||||||
@@ -92,10 +92,6 @@ func InitNetworkMount() {
|
|||||||
}
|
}
|
||||||
connection.Directories = strings.Join(directories, ",")
|
connection.Directories = strings.Join(directories, ",")
|
||||||
service.MyService.Connections().UpdateConnection(&connection)
|
service.MyService.Connections().UpdateConnection(&connection)
|
||||||
}
|
service.MyService.Storage().CheckAndMountAll()
|
||||||
|
|
||||||
err := service.MyService.Storage().CheckAndMountAll()
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("mount storage err", zap.Any("err", err))
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -92,22 +92,25 @@ func InitV1Router() *gin.Engine {
|
|||||||
v1FileGroup.GET("/content", v1.GetFilerContent) // file/read
|
v1FileGroup.GET("/content", v1.GetFilerContent) // file/read
|
||||||
|
|
||||||
// File uploads need to be handled separately, and will not be modified here
|
// File uploads need to be handled separately, and will not be modified here
|
||||||
|
//v1FileGroup.POST("/upload", v1.PostFileUpload)
|
||||||
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
v1FileGroup.POST("/upload", v1.PostFileUpload)
|
||||||
v1FileGroup.GET("/upload", v1.GetFileUpload)
|
v1FileGroup.GET("/upload", v1.GetFileUpload)
|
||||||
// v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
// v1FileGroup.GET("/download", v1.UserFileDownloadCommonService)
|
||||||
|
v1FileGroup.GET("/ws", v1.ConnectWebSocket)
|
||||||
|
v1FileGroup.GET("/peers", v1.GetPeers)
|
||||||
}
|
}
|
||||||
v1CloudGroup := v1Group.Group("/cloud")
|
v1CloudGroup := v1Group.Group("/cloud")
|
||||||
v1CloudGroup.Use()
|
v1CloudGroup.Use()
|
||||||
{
|
{
|
||||||
v1CloudGroup.GET("", v1.ListStorages)
|
v1CloudGroup.GET("", v1.ListStorages)
|
||||||
v1CloudGroup.DELETE("", v1.DeleteStorage)
|
v1CloudGroup.DELETE("", v1.UmountStorage)
|
||||||
}
|
}
|
||||||
v1DriverGroup := v1Group.Group("/driver")
|
v1DriverGroup := v1Group.Group("/driver")
|
||||||
v1DriverGroup.Use()
|
v1DriverGroup.Use()
|
||||||
{
|
{
|
||||||
v1DriverGroup.GET("", v1.ListDriverInfo)
|
v1DriverGroup.GET("", v1.ListDriverInfo)
|
||||||
}
|
}
|
||||||
|
|
||||||
v1FolderGroup := v1Group.Group("/folder")
|
v1FolderGroup := v1Group.Group("/folder")
|
||||||
v1FolderGroup.Use()
|
v1FolderGroup.Use()
|
||||||
{
|
{
|
||||||
@@ -115,6 +118,7 @@ func InitV1Router() *gin.Engine {
|
|||||||
v1FolderGroup.GET("", v1.DirPath) ///file/dirpath
|
v1FolderGroup.GET("", v1.DirPath) ///file/dirpath
|
||||||
v1FolderGroup.POST("", v1.MkdirAll) ///file/mkdir
|
v1FolderGroup.POST("", v1.MkdirAll) ///file/mkdir
|
||||||
v1FolderGroup.GET("/size", v1.GetSize)
|
v1FolderGroup.GET("/size", v1.GetSize)
|
||||||
|
v1FolderGroup.GET("/count", v1.GetFileCount)
|
||||||
}
|
}
|
||||||
v1BatchGroup := v1Group.Group("/batch")
|
v1BatchGroup := v1Group.Group("/batch")
|
||||||
v1BatchGroup.Use()
|
v1BatchGroup.Use()
|
||||||
@@ -156,6 +160,7 @@ func InitV1Router() *gin.Engine {
|
|||||||
// merge to system
|
// merge to system
|
||||||
v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify)
|
v1NotifyGroup.POST("/system_status", v1.PostSystemStatusNotify)
|
||||||
}
|
}
|
||||||
|
|
||||||
v1OtherGroup := v1Group.Group("/other")
|
v1OtherGroup := v1Group.Group("/other")
|
||||||
v1OtherGroup.Use()
|
v1OtherGroup.Use()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"strconv"
|
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
@@ -68,20 +67,7 @@ func ListStorages(c *gin.Context) {
|
|||||||
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})
|
||||||
}
|
}
|
||||||
|
|
||||||
func UpdateStorage(c *gin.Context) {
|
func UmountStorage(c *gin.Context) {
|
||||||
var req model.Storage
|
|
||||||
if err := c.ShouldBind(&req); err != nil {
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := service.MyService.Storages().UpdateStorage(c, req); err != nil {
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
|
||||||
} else {
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "success"})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func DeleteStorage(c *gin.Context) {
|
|
||||||
json := make(map[string]string)
|
json := make(map[string]string)
|
||||||
c.ShouldBind(&json)
|
c.ShouldBind(&json)
|
||||||
mountPoint := json["mount_point"]
|
mountPoint := json["mount_point"]
|
||||||
@@ -98,34 +84,6 @@ func DeleteStorage(c *gin.Context) {
|
|||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "success"})
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "success"})
|
||||||
}
|
}
|
||||||
|
|
||||||
func DisableStorage(c *gin.Context) {
|
|
||||||
idStr := c.Query("id")
|
|
||||||
id, err := strconv.Atoi(idStr)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := service.MyService.Storages().DisableStorage(c, uint(id)); err != nil {
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "success"})
|
|
||||||
}
|
|
||||||
|
|
||||||
func EnableStorage(c *gin.Context) {
|
|
||||||
idStr := c.Query("id")
|
|
||||||
id, err := strconv.Atoi(idStr)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
if err := service.MyService.Storages().EnableStorage(c, uint(id)); err != nil {
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: "success"})
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetStorage(c *gin.Context) {
|
func GetStorage(c *gin.Context) {
|
||||||
|
|
||||||
// idStr := c.Query("id")
|
// idStr := c.Query("id")
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/model"
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/common_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/op"
|
"github.com/IceWhaleTech/CasaOS/internal/op"
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|||||||
521
route/v1/file.go
521
route/v1/file.go
@@ -1,7 +1,7 @@
|
|||||||
package v1
|
package v1
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"errors"
|
"encoding/json"
|
||||||
"fmt"
|
"fmt"
|
||||||
"io"
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
@@ -15,18 +15,19 @@ import (
|
|||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
"sync"
|
"sync"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/conf"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
"github.com/IceWhaleTech/CasaOS/model"
|
||||||
|
"github.com/gorilla/websocket"
|
||||||
|
"github.com/robfig/cron/v3"
|
||||||
|
"github.com/tidwall/gjson"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
"github.com/IceWhaleTech/CasaOS/pkg/utils/file"
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
"github.com/IceWhaleTech/CasaOS/service"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/sign"
|
|
||||||
"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"
|
"go.uber.org/zap"
|
||||||
@@ -34,6 +35,45 @@ import (
|
|||||||
"github.com/h2non/filetype"
|
"github.com/h2non/filetype"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type ListReq struct {
|
||||||
|
model.PageReq
|
||||||
|
Path string `json:"path" form:"path"`
|
||||||
|
//Refresh bool `json:"refresh"`
|
||||||
|
}
|
||||||
|
type ObjResp struct {
|
||||||
|
Name string `json:"name"`
|
||||||
|
Size int64 `json:"size"`
|
||||||
|
IsDir bool `json:"is_dir"`
|
||||||
|
Modified time.Time `json:"modified"`
|
||||||
|
Sign string `json:"sign"`
|
||||||
|
Thumb string `json:"thumb"`
|
||||||
|
Type int `json:"type"`
|
||||||
|
Path string `json:"path"`
|
||||||
|
Date time.Time `json:"date"`
|
||||||
|
Extensions map[string]interface{} `json:"extensions"`
|
||||||
|
}
|
||||||
|
type FsListResp struct {
|
||||||
|
Content []ObjResp `json:"content"`
|
||||||
|
Total int64 `json:"total"`
|
||||||
|
Readme string `json:"readme,omitempty"`
|
||||||
|
Write bool `json:"write,omitempty"`
|
||||||
|
Provider string `json:"provider,omitempty"`
|
||||||
|
Index int `json:"index"`
|
||||||
|
Size int `json:"size"`
|
||||||
|
}
|
||||||
|
|
||||||
|
var (
|
||||||
|
// 升级成 WebSocket 协议
|
||||||
|
upgraderFile = websocket.Upgrader{
|
||||||
|
// 允许CORS跨域请求
|
||||||
|
CheckOrigin: func(r *http.Request) bool {
|
||||||
|
return true
|
||||||
|
},
|
||||||
|
}
|
||||||
|
conn *websocket.Conn
|
||||||
|
err error
|
||||||
|
)
|
||||||
|
|
||||||
// @Summary 读取文件
|
// @Summary 读取文件
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
@@ -563,6 +603,71 @@ func PostFileUpload(c *gin.Context) {
|
|||||||
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
c.JSON(http.StatusOK, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func PostFileOctet(c *gin.Context) {
|
||||||
|
|
||||||
|
content_length := c.Request.ContentLength
|
||||||
|
if content_length <= 0 || content_length > 1024*1024*1024*2*1024 {
|
||||||
|
log.Printf("content_length error\n")
|
||||||
|
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "content_length error"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
content_type_, has_key := c.Request.Header["Content-Type"]
|
||||||
|
if !has_key {
|
||||||
|
log.Printf("Content-Type error\n")
|
||||||
|
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Content-Type error"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if len(content_type_) != 1 {
|
||||||
|
log.Printf("Content-Type count error\n")
|
||||||
|
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Content-Type count error"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
content_type := content_type_[0]
|
||||||
|
const BOUNDARY string = "; boundary="
|
||||||
|
loc := strings.Index(content_type, BOUNDARY)
|
||||||
|
if loc == -1 {
|
||||||
|
log.Printf("Content-Type error, no boundary\n")
|
||||||
|
c.JSON(http.StatusBadRequest, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: "Content-Type error, no boundary"})
|
||||||
|
return
|
||||||
|
}
|
||||||
|
boundary := []byte(content_type[(loc + len(BOUNDARY)):])
|
||||||
|
log.Printf("[%s]\n\n", boundary)
|
||||||
|
read_data := make([]byte, 1024*24)
|
||||||
|
var read_total int = 0
|
||||||
|
for {
|
||||||
|
file_header, file_data, err := file.ParseFromHead(read_data, read_total, append(boundary, []byte("\r\n")...), c.Request.Body)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("%v", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
log.Printf("file :%s\n", file_header)
|
||||||
|
//
|
||||||
|
//os.OpenFile(path, os.O_WRONLY|os.O_CREATE, 0o644)
|
||||||
|
f, err := os.OpenFile(file_header["path"]+"/"+file_header["filename"], os.O_WRONLY|os.O_CREATE, 0o644)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("create file fail:%v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
f.Write(file_data)
|
||||||
|
file_data = nil
|
||||||
|
|
||||||
|
temp_data, reach_end, err := file.ReadToBoundary(boundary, c.Request.Body, f)
|
||||||
|
f.Close()
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("%v\n", err)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if reach_end {
|
||||||
|
break
|
||||||
|
} else {
|
||||||
|
copy(read_data[0:], temp_data)
|
||||||
|
read_total = len(temp_data)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
}
|
||||||
|
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
|
||||||
// @Produce application/json
|
// @Produce application/json
|
||||||
// @Accept application/json
|
// @Accept application/json
|
||||||
@@ -766,168 +871,286 @@ func GetSize(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: size})
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: size})
|
||||||
}
|
}
|
||||||
func Proxy(c *gin.Context) {
|
|
||||||
rawPath := c.Query("path")
|
func GetFileCount(c *gin.Context) {
|
||||||
filename := filepath.Base(rawPath)
|
json := make(map[string]string)
|
||||||
storage, err := service.MyService.FsService().GetStorage(rawPath)
|
c.ShouldBind(&json)
|
||||||
|
path := json["path"]
|
||||||
|
list, err := ioutil.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.JSON(500, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
if canProxy(storage, filename) {
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: len(list)})
|
||||||
downProxyUrl := storage.GetStorage().DownProxyUrl
|
}
|
||||||
if downProxyUrl != "" {
|
|
||||||
_, ok := c.GetQuery("d")
|
|
||||||
if !ok {
|
|
||||||
URL := fmt.Sprintf("%s%s?sign=%s",
|
|
||||||
strings.Split(downProxyUrl, "\n")[0],
|
|
||||||
utils.EncodePath(rawPath, true),
|
|
||||||
sign.Sign(rawPath))
|
|
||||||
c.Redirect(302, URL)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
}
|
|
||||||
link, file, err := service.MyService.FsService().Link(c, rawPath, model.LinkArgs{
|
|
||||||
Header: c.Request.Header,
|
|
||||||
Type: c.Query("type"),
|
|
||||||
})
|
|
||||||
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
|
type CenterHandler struct {
|
||||||
}
|
// 广播通道,有数据则循环每个用户广播出去
|
||||||
err = CommonProxy(c.Writer, c.Request, link, file)
|
broadcast chan []byte
|
||||||
if err != nil {
|
// 注册通道,有用户进来 则推到用户集合map中
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
register chan *Client
|
||||||
return
|
// 注销通道,有用户关闭连接 则将该用户剔出集合map中
|
||||||
}
|
unregister chan *Client
|
||||||
} else {
|
// 用户集合,每个用户本身也在跑两个协程,监听用户的读、写的状态
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: "proxy not allowed"})
|
clients map[string]*Client
|
||||||
|
}
|
||||||
|
|
||||||
|
type Client struct {
|
||||||
|
handler *CenterHandler
|
||||||
|
conn *websocket.Conn
|
||||||
|
// 每个用户自己的循环跑起来的状态监控
|
||||||
|
send chan []byte
|
||||||
|
ID string `json:"id"`
|
||||||
|
IP string `json:"ip"`
|
||||||
|
Name service.Name `json:"name"`
|
||||||
|
RtcSupported bool `json:"rtcSupported"`
|
||||||
|
TimerId int `json:"timerId"`
|
||||||
|
LastBeat time.Time `json:"lastBeat"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type PeerModel struct {
|
||||||
|
ID string `json:"id"`
|
||||||
|
Name service.Name `json:"name"`
|
||||||
|
RtcSupported bool `json:"rtcSupported"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func ConnectWebSocket(c *gin.Context) {
|
||||||
|
peerId := c.Query("peer")
|
||||||
|
writer := c.Writer
|
||||||
|
request := c.Request
|
||||||
|
key := uuid.NewV4().String()
|
||||||
|
//peerModel := service.MyService.Peer().GetPeerByUserAgent(c.Request.UserAgent())
|
||||||
|
peerModel := model2.PeerDriveDBModel{}
|
||||||
|
name := service.GetName(request)
|
||||||
|
if conn, err = upgraderFile.Upgrade(writer, request, writer.Header()); err != nil {
|
||||||
|
log.Println(err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
client := &Client{handler: &handler, conn: conn, send: make(chan []byte, 256), ID: service.GetPeerId(request, key), IP: service.GetIP(request), Name: name, RtcSupported: true, TimerId: 0, LastBeat: time.Now()}
|
||||||
|
if peerId != "" || len(peerModel.ID) > 0 {
|
||||||
|
if len(peerModel.ID) == 0 {
|
||||||
|
peerModel = service.MyService.Peer().GetPeerByID(peerId)
|
||||||
|
}
|
||||||
|
if len(peerModel.ID) > 0 {
|
||||||
|
key = peerId
|
||||||
|
client.ID = peerModel.ID
|
||||||
|
client.Name = service.GetNameByDB(peerModel)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
var list = service.MyService.Peer().GetPeers()
|
||||||
|
if len(peerModel.ID) == 0 {
|
||||||
|
peerModel.ID = key
|
||||||
|
peerModel.DisplayName = name.DisplayName
|
||||||
|
peerModel.DeviceName = name.DeviceName
|
||||||
|
peerModel.Model = name.Model
|
||||||
|
peerModel.OS = name.OS
|
||||||
|
peerModel.Browser = name.Browser
|
||||||
|
peerModel.UserAgent = c.Request.UserAgent()
|
||||||
|
peerModel.IP = client.IP
|
||||||
|
service.MyService.Peer().CreatePeer(&peerModel)
|
||||||
|
list = append(list, peerModel)
|
||||||
|
}
|
||||||
|
|
||||||
// TODO need optimize
|
cookie := http.Cookie{
|
||||||
// when should be proxy?
|
Name: "peerid",
|
||||||
// 1. config.MustProxy()
|
Value: key,
|
||||||
// 2. storage.WebProxy
|
Path: "/",
|
||||||
// 3. proxy_types
|
|
||||||
func shouldProxy(storage driver.Driver, filename string) bool {
|
|
||||||
if storage.Config().MustProxy() || storage.GetStorage().WebProxy {
|
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
if utils.SliceContains(conf.SlicesMap[conf.ProxyTypes], utils.Ext(filename)) {
|
http.SetCookie(writer, &cookie)
|
||||||
return true
|
if len(list) > 10 {
|
||||||
}
|
kickoutList := []Client{}
|
||||||
return false
|
count := len(list) - 10
|
||||||
}
|
for i := len(list) - 1; count > 0 && i > -1; i-- {
|
||||||
|
if _, ok := handler.clients[list[i].ID]; !ok {
|
||||||
// TODO need optimize
|
count--
|
||||||
// when can be proxy?
|
kickoutList = append(kickoutList, Client{ID: list[i].ID, Name: service.GetNameByDB(list[i]), IP: list[i].IP})
|
||||||
// 1. text file
|
service.MyService.Peer().DeletePeer(list[i].ID)
|
||||||
// 2. config.MustProxy()
|
|
||||||
// 3. storage.WebProxy
|
|
||||||
// 4. proxy_types
|
|
||||||
// solution: text_file + shouldProxy()
|
|
||||||
func canProxy(storage driver.Driver, filename string) bool {
|
|
||||||
if storage.Config().MustProxy() || storage.GetStorage().WebProxy || storage.GetStorage().WebdavProxy() {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if utils.SliceContains(conf.SlicesMap[conf.ProxyTypes], utils.Ext(filename)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
if utils.SliceContains(conf.SlicesMap[conf.TextTypes], utils.Ext(filename)) {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
var HttpClient = &http.Client{}
|
|
||||||
|
|
||||||
func CommonProxy(w http.ResponseWriter, r *http.Request, link *model.Link, file model.Obj) error {
|
|
||||||
// read data with native
|
|
||||||
var err error
|
|
||||||
if link.Data != nil {
|
|
||||||
defer func() {
|
|
||||||
_ = link.Data.Close()
|
|
||||||
}()
|
|
||||||
w.Header().Set("Content-Type", "application/octet-stream")
|
|
||||||
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"; filename*=UTF-8''%s`, file.GetName(), url.QueryEscape(file.GetName())))
|
|
||||||
w.Header().Set("Content-Length", strconv.FormatInt(file.GetSize(), 10))
|
|
||||||
if link.Header != nil {
|
|
||||||
// TODO clean header with blacklist or whitelist
|
|
||||||
link.Header.Del("set-cookie")
|
|
||||||
for h, val := range link.Header {
|
|
||||||
w.Header()[h] = val
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if link.Status == 0 {
|
// if len(kickoutList) > 0 {
|
||||||
w.WriteHeader(http.StatusOK)
|
// other := make(map[string]interface{})
|
||||||
} else {
|
// other["type"] = "kickout"
|
||||||
w.WriteHeader(link.Status)
|
// other["peers"] = kickoutList
|
||||||
}
|
// otherBy, err := json.Marshal(other)
|
||||||
_, err = io.Copy(w, link.Data)
|
// fmt.Println(err)
|
||||||
if err != nil {
|
// client.handler.broadcast <- otherBy
|
||||||
return err
|
// }
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
// local file
|
list = service.MyService.Peer().GetPeers()
|
||||||
if link.FilePath != nil && *link.FilePath != "" {
|
if len(list) > 10 {
|
||||||
f, err := os.Open(*link.FilePath)
|
fmt.Println("解决完后依然有溢出", list)
|
||||||
if err != nil {
|
}
|
||||||
return err
|
currentPeer := PeerModel{ID: client.ID, Name: client.Name, RtcSupported: client.RtcSupported}
|
||||||
|
pmsg := make(map[string]interface{})
|
||||||
|
pmsg["type"] = "peer-joined"
|
||||||
|
pmsg["peer"] = currentPeer
|
||||||
|
pby, err := json.Marshal(pmsg)
|
||||||
|
fmt.Println(err)
|
||||||
|
for _, v := range handler.clients {
|
||||||
|
v.send <- pby
|
||||||
|
}
|
||||||
|
//client.handler.broadcast <- pby
|
||||||
|
clients := []PeerModel{}
|
||||||
|
for _, v := range client.handler.clients {
|
||||||
|
if _, ok := handler.clients[v.ID]; ok {
|
||||||
|
clients = append(clients, PeerModel{ID: v.ID, Name: v.Name, RtcSupported: v.RtcSupported})
|
||||||
}
|
}
|
||||||
defer func() {
|
}
|
||||||
_ = f.Close()
|
|
||||||
}()
|
other := make(map[string]interface{})
|
||||||
fileStat, err := os.Stat(*link.FilePath)
|
other["type"] = "peers"
|
||||||
if err != nil {
|
other["peers"] = clients
|
||||||
return err
|
otherBy, err := json.Marshal(other)
|
||||||
|
fmt.Println(err)
|
||||||
|
client.send <- otherBy
|
||||||
|
|
||||||
|
// 推给监控中心注册到用户集合中
|
||||||
|
handler.register <- client
|
||||||
|
|
||||||
|
client.send <- []byte(`{"type":"ping"}`)
|
||||||
|
|
||||||
|
data := make(map[string]string)
|
||||||
|
data["displayName"] = client.Name.DisplayName
|
||||||
|
data["deviceName"] = client.Name.DeviceName
|
||||||
|
data["id"] = client.ID
|
||||||
|
msg := make(map[string]interface{})
|
||||||
|
msg["type"] = "display-name"
|
||||||
|
msg["message"] = data
|
||||||
|
by, _ := json.Marshal(msg)
|
||||||
|
client.send <- by
|
||||||
|
|
||||||
|
// 每个 client 都挂起 2 个新的协程,监控读、写状态
|
||||||
|
go client.writePump()
|
||||||
|
go client.readPump()
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS)})
|
||||||
|
}
|
||||||
|
|
||||||
|
var handler = CenterHandler{broadcast: make(chan []byte),
|
||||||
|
register: make(chan *Client),
|
||||||
|
unregister: make(chan *Client),
|
||||||
|
clients: make(map[string]*Client)}
|
||||||
|
|
||||||
|
func init() {
|
||||||
|
// 起个协程跑起来,监听注册、注销、消息 3 个 channel
|
||||||
|
go handler.monitoring()
|
||||||
|
|
||||||
|
crontab := cron.New(cron.WithSeconds()) //精确到秒
|
||||||
|
//定义定时器调用的任务函数
|
||||||
|
|
||||||
|
task := func() {
|
||||||
|
handler.broadcast <- []byte(`{"type":"ping"}`)
|
||||||
|
}
|
||||||
|
//定时任务
|
||||||
|
spec := "*/30 * * * * ?" //cron表达式,每五秒一次
|
||||||
|
// 添加定时任务,
|
||||||
|
crontab.AddFunc(spec, task)
|
||||||
|
// 启动定时器
|
||||||
|
crontab.Start()
|
||||||
|
}
|
||||||
|
func (c *Client) writePump() {
|
||||||
|
defer func() {
|
||||||
|
c.handler.unregister <- c
|
||||||
|
|
||||||
|
c.conn.Close()
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
// 广播推过来的新消息,马上通过websocket推给自己
|
||||||
|
message, _ := <-c.send
|
||||||
|
fmt.Println("推送消息", string(message), "1")
|
||||||
|
if err := c.conn.WriteMessage(websocket.TextMessage, message); err != nil {
|
||||||
|
return
|
||||||
}
|
}
|
||||||
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"; filename*=UTF-8''%s`, file.GetName(), url.QueryEscape(file.GetName())))
|
}
|
||||||
http.ServeContent(w, r, file.GetName(), fileStat.ModTime(), f)
|
}
|
||||||
return nil
|
|
||||||
} else {
|
// 读,监听客户端是否有推送内容过来服务端
|
||||||
req, err := http.NewRequest(link.Method, link.URL, nil)
|
func (c *Client) readPump() {
|
||||||
|
defer func() {
|
||||||
|
c.handler.unregister <- c
|
||||||
|
c.conn.Close()
|
||||||
|
}()
|
||||||
|
for {
|
||||||
|
// 循环监听是否该用户是否要发言
|
||||||
|
_, message, err := c.conn.ReadMessage()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
// 异常关闭的处理
|
||||||
|
if websocket.IsUnexpectedCloseError(err, websocket.CloseGoingAway, websocket.CloseAbnormalClosure) {
|
||||||
|
log.Printf("error: %v", err)
|
||||||
|
}
|
||||||
|
c.handler.broadcast <- []byte(`{"type":"peer-left","peerId":"` + c.ID + `"}`)
|
||||||
|
break
|
||||||
}
|
}
|
||||||
for h, val := range r.Header {
|
// 要的话,推给广播中心,广播中心再推给每个用户
|
||||||
if utils.SliceContains(conf.SlicesMap[conf.ProxyIgnoreHeaders], strings.ToLower(h)) {
|
|
||||||
|
t := gjson.GetBytes(message, "type")
|
||||||
|
if t.String() == "disconnect" {
|
||||||
|
c.handler.unregister <- c
|
||||||
|
c.conn.Close()
|
||||||
|
// clients := []Client{}
|
||||||
|
// list := service.MyService.Peer().GetPeers()
|
||||||
|
// for _, v := range list {
|
||||||
|
// if _, ok := handler.clients[v.ID]; ok {
|
||||||
|
// clients = append(clients, *handler.clients[v.ID])
|
||||||
|
// } else {
|
||||||
|
// clients = append(clients, Client{ID: v.ID, Name: service.GetNameByDB(v), IP: v.IP, Offline: true})
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// other := make(map[string]interface{})
|
||||||
|
// other["type"] = "peers"
|
||||||
|
// other["peers"] = clients
|
||||||
|
// otherBy, err := json.Marshal(other)
|
||||||
|
// fmt.Println(err)
|
||||||
|
c.handler.broadcast <- []byte(`{"type":"peer-left","peerId":"` + c.ID + `"}`)
|
||||||
|
//c.handler.broadcast <- otherBy
|
||||||
|
break
|
||||||
|
} else if t.String() == "pong" {
|
||||||
|
c.LastBeat = time.Now()
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
to := gjson.GetBytes(message, "to")
|
||||||
|
|
||||||
|
if len(to.String()) > 0 {
|
||||||
|
toC := c.handler.clients[to.String()]
|
||||||
|
if toC == nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
req.Header[h] = val
|
data := map[string]interface{}{}
|
||||||
|
json.Unmarshal(message, &data)
|
||||||
|
data["sender"] = c.ID
|
||||||
|
delete(data, "to")
|
||||||
|
message, err = json.Marshal(data)
|
||||||
|
toC.send <- message
|
||||||
|
continue
|
||||||
}
|
}
|
||||||
for h, val := range link.Header {
|
|
||||||
req.Header[h] = val
|
|
||||||
}
|
|
||||||
res, err := HttpClient.Do(req)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
defer func() {
|
|
||||||
_ = res.Body.Close()
|
|
||||||
}()
|
|
||||||
logger.Info("proxy status", zap.Any("status", res.StatusCode))
|
|
||||||
// TODO clean header with blacklist or whitelist
|
|
||||||
res.Header.Del("set-cookie")
|
|
||||||
for h, v := range res.Header {
|
|
||||||
w.Header()[h] = v
|
|
||||||
}
|
|
||||||
w.WriteHeader(res.StatusCode)
|
|
||||||
w.Header().Set("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"; filename*=UTF-8''%s`, file.GetName(), url.QueryEscape(file.GetName())))
|
|
||||||
if res.StatusCode >= 400 {
|
|
||||||
all, _ := ioutil.ReadAll(res.Body)
|
|
||||||
msg := string(all)
|
|
||||||
logger.Info("msg", zap.Any("msg", msg))
|
|
||||||
|
|
||||||
return errors.New(msg)
|
c.handler.broadcast <- message
|
||||||
}
|
|
||||||
_, err = io.Copy(w, res.Body)
|
|
||||||
if err != nil {
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
func (ch *CenterHandler) monitoring() {
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
// 注册,新用户连接过来会推进注册通道,这里接收推进来的用户指针
|
||||||
|
case client := <-ch.register:
|
||||||
|
ch.clients[client.ID] = client
|
||||||
|
// 注销,关闭连接或连接异常会将用户推出群聊
|
||||||
|
case client := <-ch.unregister:
|
||||||
|
delete(ch.clients, client.ID)
|
||||||
|
// 消息,监听到有新消息到来
|
||||||
|
case message := <-ch.broadcast:
|
||||||
|
println("消息来了,message:" + string(message))
|
||||||
|
// 推送给每个用户的通道,每个用户都有跑协程起了writePump的监听
|
||||||
|
for _, client := range ch.clients {
|
||||||
|
client.send <- message
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
func GetPeers(c *gin.Context) {
|
||||||
|
peers := service.MyService.Peer().GetPeers()
|
||||||
|
for i := 0; i < len(peers); i++ {
|
||||||
|
if _, ok := handler.clients[peers[i].ID]; ok {
|
||||||
|
peers[i].Online = true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: peers})
|
||||||
|
}
|
||||||
|
|||||||
@@ -1,97 +0,0 @@
|
|||||||
package v1
|
|
||||||
|
|
||||||
import (
|
|
||||||
"path/filepath"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils/common_err"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/service"
|
|
||||||
|
|
||||||
"github.com/gin-gonic/gin"
|
|
||||||
)
|
|
||||||
|
|
||||||
type ListReq struct {
|
|
||||||
model.PageReq
|
|
||||||
Path string `json:"path" form:"path"`
|
|
||||||
//Refresh bool `json:"refresh"`
|
|
||||||
}
|
|
||||||
type ObjResp struct {
|
|
||||||
Name string `json:"name"`
|
|
||||||
Size int64 `json:"size"`
|
|
||||||
IsDir bool `json:"is_dir"`
|
|
||||||
Modified time.Time `json:"modified"`
|
|
||||||
Sign string `json:"sign"`
|
|
||||||
Thumb string `json:"thumb"`
|
|
||||||
Type int `json:"type"`
|
|
||||||
Path string `json:"path"`
|
|
||||||
Date time.Time `json:"date"`
|
|
||||||
Extensions map[string]interface{} `json:"extensions"`
|
|
||||||
}
|
|
||||||
type FsListResp struct {
|
|
||||||
Content []ObjResp `json:"content"`
|
|
||||||
Total int64 `json:"total"`
|
|
||||||
Readme string `json:"readme,omitempty"`
|
|
||||||
Write bool `json:"write,omitempty"`
|
|
||||||
Provider string `json:"provider,omitempty"`
|
|
||||||
Index int `json:"index"`
|
|
||||||
Size int `json:"size"`
|
|
||||||
}
|
|
||||||
|
|
||||||
func FsList(c *gin.Context) {
|
|
||||||
var req ListReq
|
|
||||||
if err := c.ShouldBind(&req); err != nil {
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.CLIENT_ERROR, Message: common_err.GetMsg(common_err.CLIENT_ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
req.Validate()
|
|
||||||
objs, err := service.MyService.FsService().FList(c, req.Path, false)
|
|
||||||
if err != nil {
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
|
||||||
return
|
|
||||||
}
|
|
||||||
total, objs := pagination(objs, &req.PageReq)
|
|
||||||
provider := "unknown"
|
|
||||||
storage, err := service.MyService.FsService().GetStorage(req.Path)
|
|
||||||
if err == nil {
|
|
||||||
provider = storage.GetStorage().Driver
|
|
||||||
}
|
|
||||||
c.JSON(common_err.SUCCESS, model.Result{Success: common_err.SUCCESS, Message: common_err.GetMsg(common_err.SUCCESS), Data: FsListResp{
|
|
||||||
Content: toObjsResp(objs, req.Path, false),
|
|
||||||
Total: int64(total),
|
|
||||||
Readme: "",
|
|
||||||
Write: false,
|
|
||||||
Provider: provider,
|
|
||||||
}})
|
|
||||||
}
|
|
||||||
func pagination(objs []model.Obj, req *model.PageReq) (int, []model.Obj) {
|
|
||||||
pageIndex, pageSize := req.Index, req.Size
|
|
||||||
total := len(objs)
|
|
||||||
start := (pageIndex - 1) * pageSize
|
|
||||||
if start > total {
|
|
||||||
return total, []model.Obj{}
|
|
||||||
}
|
|
||||||
end := start + pageSize
|
|
||||||
if end > total {
|
|
||||||
end = total
|
|
||||||
}
|
|
||||||
return total, objs[start:end]
|
|
||||||
}
|
|
||||||
|
|
||||||
func toObjsResp(objs []model.Obj, parent string, encrypt bool) []ObjResp {
|
|
||||||
var resp []ObjResp
|
|
||||||
for _, obj := range objs {
|
|
||||||
thumb, _ := model.GetThumb(obj)
|
|
||||||
resp = append(resp, ObjResp{
|
|
||||||
Name: obj.GetName(),
|
|
||||||
Size: obj.GetSize(),
|
|
||||||
IsDir: obj.IsDir(),
|
|
||||||
Modified: obj.ModTime(),
|
|
||||||
Sign: "",
|
|
||||||
Path: filepath.Join(parent, obj.GetName()),
|
|
||||||
Thumb: thumb,
|
|
||||||
Type: 0,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
return resp
|
|
||||||
}
|
|
||||||
@@ -10,12 +10,16 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func GetSearchResult(c *gin.Context) {
|
func GetSearchResult(c *gin.Context) {
|
||||||
key := c.Query("key")
|
json := make(map[string]string)
|
||||||
if key == "" {
|
c.ShouldBind(&json)
|
||||||
|
url := json["url"]
|
||||||
|
|
||||||
|
if url == "" {
|
||||||
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "key is empty"})
|
c.JSON(common_err.CLIENT_ERROR, model.Result{Success: common_err.INVALID_PARAMS, Message: common_err.GetMsg(common_err.INVALID_PARAMS), Data: "key is empty"})
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
data, err := service.MyService.Other().Search(key)
|
//data, err := service.MyService.Other().Search(key)
|
||||||
|
data, err := service.MyService.Other().AgentSearch(url)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
fmt.Println(err)
|
fmt.Println(err)
|
||||||
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
c.JSON(common_err.SERVICE_ERROR, model.Result{Success: common_err.SERVICE_ERROR, Message: common_err.GetMsg(common_err.SERVICE_ERROR), Data: err.Error()})
|
||||||
|
|||||||
@@ -103,6 +103,7 @@ func GetRecoverStorage(c *gin.Context) {
|
|||||||
notify := make(map[string]interface{})
|
notify := make(map[string]interface{})
|
||||||
notify["status"] = "success"
|
notify["status"] = "success"
|
||||||
notify["message"] = "Success"
|
notify["message"] = "Success"
|
||||||
|
notify["driver"] = "GoogleDrive"
|
||||||
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
} else if t == "Dropbox" {
|
} else if t == "Dropbox" {
|
||||||
add := dropbox.Addition{}
|
add := dropbox.Addition{}
|
||||||
@@ -196,6 +197,7 @@ func GetRecoverStorage(c *gin.Context) {
|
|||||||
|
|
||||||
notify["status"] = "success"
|
notify["status"] = "success"
|
||||||
notify["message"] = "Success"
|
notify["message"] = "Success"
|
||||||
|
notify["driver"] = "Dropbox"
|
||||||
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
service.MyService.Notify().SendNotify("casaos:file:recover", notify)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -207,12 +207,15 @@ func DeleteSambaConnections(c *gin.Context) {
|
|||||||
}
|
}
|
||||||
baseHostPath := "/mnt/" + connection.Host
|
baseHostPath := "/mnt/" + connection.Host
|
||||||
for _, v := range mountPointList {
|
for _, v := range mountPointList {
|
||||||
err := service.MyService.Connections().UnmountSmaba(baseHostPath + "/" + v)
|
if service.IsMounted(baseHostPath + "/" + v) {
|
||||||
if err != nil {
|
err := service.MyService.Connections().UnmountSmaba(baseHostPath + "/" + v)
|
||||||
logger.Error("unmount smaba error", zap.Error(err), zap.Any("path", baseHostPath+"/"+v))
|
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()})
|
logger.Error("unmount smaba error", zap.Error(err), zap.Any("path", baseHostPath+"/"+v))
|
||||||
return
|
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
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
dir, _ := ioutil.ReadDir(connection.MountPoint)
|
dir, _ := ioutil.ReadDir(connection.MountPoint)
|
||||||
if len(dir) == 0 {
|
if len(dir) == 0 {
|
||||||
|
|||||||
@@ -8,16 +8,17 @@
|
|||||||
* @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 v1
|
package v1_test
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httptest"
|
"net/http/httptest"
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
v1 "github.com/IceWhaleTech/CasaOS/route/v1"
|
||||||
"github.com/gin-gonic/gin"
|
"github.com/gin-gonic/gin"
|
||||||
"github.com/golang/mock/gomock"
|
"github.com/golang/mock/gomock"
|
||||||
"github.com/stretchr/testify/assert"
|
"gotest.tools/assert"
|
||||||
)
|
)
|
||||||
|
|
||||||
func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
|
func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
|
||||||
@@ -62,7 +63,7 @@ func TestGetSambaSharesList(t *testing.T) {
|
|||||||
|
|
||||||
requestUrl := "/v1/samba/shares"
|
requestUrl := "/v1/samba/shares"
|
||||||
httpRequest, _ := http.NewRequest("GET", requestUrl, nil)
|
httpRequest, _ := http.NewRequest("GET", requestUrl, nil)
|
||||||
GetSambaSharesList(con)
|
v1.GetSambaSharesList(con)
|
||||||
ginEngine.ServeHTTP(response, httpRequest)
|
ginEngine.ServeHTTP(response, httpRequest)
|
||||||
return response
|
return response
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -178,12 +178,16 @@ func GetSystemHardwareInfo(c *gin.Context) {
|
|||||||
data := make(map[string]string, 1)
|
data := make(map[string]string, 1)
|
||||||
data["drive_model"] = service.MyService.System().GetDeviceTree()
|
data["drive_model"] = service.MyService.System().GetDeviceTree()
|
||||||
data["arch"] = runtime.GOARCH
|
data["arch"] = runtime.GOARCH
|
||||||
c.JSON(common_err.SUCCESS,
|
|
||||||
model.Result{
|
if cpu := service.MyService.System().GetCpuInfo(); len(cpu) > 0 {
|
||||||
Success: common_err.SUCCESS,
|
|
||||||
Message: common_err.GetMsg(common_err.SUCCESS),
|
c.JSON(common_err.SUCCESS,
|
||||||
Data: data,
|
model.Result{
|
||||||
})
|
Success: common_err.SUCCESS,
|
||||||
|
Message: common_err.GetMsg(common_err.SUCCESS),
|
||||||
|
Data: data,
|
||||||
|
})
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// @Summary system utilization
|
// @Summary system utilization
|
||||||
|
|||||||
@@ -1,9 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"testing"
|
|
||||||
)
|
|
||||||
|
|
||||||
func TestGetCasaOSCount(t *testing.T) {
|
|
||||||
|
|
||||||
}
|
|
||||||
154
service/fs.go
154
service/fs.go
@@ -1,154 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
log "github.com/dsoprea/go-logging"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FsService interface {
|
|
||||||
FList(ctx context.Context, path string, refresh ...bool) ([]model.Obj, error)
|
|
||||||
GetStorage(path string) (driver.Driver, error)
|
|
||||||
Link(ctx context.Context, path string, args model.LinkArgs) (*model.Link, model.Obj, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type fsService struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// the param named path of functions in this package is a mount path
|
|
||||||
// So, the purpose of this package is to convert mount path to actual path
|
|
||||||
// then pass the actual path to the op package
|
|
||||||
|
|
||||||
func (f *fsService) FList(ctx context.Context, path string, refresh ...bool) ([]model.Obj, error) {
|
|
||||||
res, err := MyService.FsListService().FsList(ctx, path, refresh...)
|
|
||||||
if err != nil {
|
|
||||||
logger.Info("failed list", zap.Any("path", path), zap.Any("err", err))
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return res, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// func (f *fsService) Get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// res, err := get(ctx, path)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Errorf("failed get %s: %+v", path, err)
|
|
||||||
// return nil, err
|
|
||||||
// }
|
|
||||||
// return res, nil
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (f *fsService) Link(ctx context.Context, path string, args model.LinkArgs) (*model.Link, model.Obj, error) {
|
|
||||||
res, file, err := MyService.FsLinkService().Link(ctx, path, args)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("failed link %s: %+v", path, err)
|
|
||||||
return nil, nil, err
|
|
||||||
}
|
|
||||||
return res, file, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// func (f *fsService) MakeDir(ctx context.Context, path string, lazyCache ...bool) error {
|
|
||||||
// err := makeDir(ctx, path, lazyCache...)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Errorf("failed make dir %s: %+v", path, err)
|
|
||||||
// }
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (f *fsService) Move(ctx context.Context, srcPath, dstDirPath string, lazyCache ...bool) error {
|
|
||||||
// err := move(ctx, srcPath, dstDirPath, lazyCache...)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Errorf("failed move %s to %s: %+v", srcPath, dstDirPath, err)
|
|
||||||
// }
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (f *fsService) Copy(ctx context.Context, srcObjPath, dstDirPath string, lazyCache ...bool) (bool, error) {
|
|
||||||
// res, err := _copy(ctx, srcObjPath, dstDirPath, lazyCache...)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Errorf("failed copy %s to %s: %+v", srcObjPath, dstDirPath, err)
|
|
||||||
// }
|
|
||||||
// return res, err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (f *fsService) Rename(ctx context.Context, srcPath, dstName string, lazyCache ...bool) error {
|
|
||||||
// err := rename(ctx, srcPath, dstName, lazyCache...)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Errorf("failed rename %s to %s: %+v", srcPath, dstName, err)
|
|
||||||
// }
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (f *fsService) Remove(ctx context.Context, path string) error {
|
|
||||||
// err := remove(ctx, path)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Errorf("failed remove %s: %+v", path, err)
|
|
||||||
// }
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func PutDirectly(ctx context.Context, dstDirPath string, file *model.FileStream, lazyCache ...bool) error {
|
|
||||||
// err := putDirectly(ctx, dstDirPath, file, lazyCache...)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Errorf("failed put %s: %+v", dstDirPath, err)
|
|
||||||
// }
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func (f *fsService) PutAsTask(dstDirPath string, file *model.FileStream) error {
|
|
||||||
// err := putAsTask(dstDirPath, file)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Errorf("failed put %s: %+v", dstDirPath, err)
|
|
||||||
// }
|
|
||||||
// return err
|
|
||||||
// }
|
|
||||||
|
|
||||||
func (f *fsService) GetStorage(path string) (driver.Driver, error) {
|
|
||||||
storageDriver, _, err := MyService.StoragePath().GetStorageAndActualPath(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return storageDriver, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// func (f *fsService) Other(ctx context.Context, args model.FsOtherArgs) (interface{}, error) {
|
|
||||||
// res, err := other(ctx, args)
|
|
||||||
// if err != nil {
|
|
||||||
// log.Errorf("failed remove %s: %+v", args.Path, err)
|
|
||||||
// }
|
|
||||||
// return res, err
|
|
||||||
// }
|
|
||||||
|
|
||||||
// func get(ctx context.Context, path string) (model.Obj, error) {
|
|
||||||
// path = utils.FixAndCleanPath(path)
|
|
||||||
// // maybe a virtual file
|
|
||||||
// if path != "/" {
|
|
||||||
// virtualFiles := op.GetStorageVirtualFilesByPath(stdpath.Dir(path))
|
|
||||||
// for _, f := range virtualFiles {
|
|
||||||
// if f.GetName() == stdpath.Base(path) {
|
|
||||||
// return f, nil
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// storage, actualPath, err := op.GetStorageAndActualPath(path)
|
|
||||||
// if err != nil {
|
|
||||||
// // if there are no storage prefix with path, maybe root folder
|
|
||||||
// if path == "/" {
|
|
||||||
// return &model.Object{
|
|
||||||
// Name: "root",
|
|
||||||
// Size: 0,
|
|
||||||
// Modified: time.Time{},
|
|
||||||
// IsFolder: true,
|
|
||||||
// }, nil
|
|
||||||
// }
|
|
||||||
// return nil, errors.WithMessage(err, "failed get storage")
|
|
||||||
// }
|
|
||||||
// return op.Get(ctx, storage, actualPath)
|
|
||||||
// }
|
|
||||||
|
|
||||||
func NewFsService() FsService {
|
|
||||||
return &fsService{}
|
|
||||||
}
|
|
||||||
@@ -1,27 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/op"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FsLinkService interface {
|
|
||||||
Link(ctx context.Context, path string, args model.LinkArgs) (*model.Link, model.Obj, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type fsLinkService struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (f *fsLinkService) Link(ctx context.Context, path string, args model.LinkArgs) (*model.Link, model.Obj, error) {
|
|
||||||
storage, actualPath, err := MyService.StoragePath().GetStorageAndActualPath(path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, nil, errors.WithMessage(err, "failed get storage")
|
|
||||||
}
|
|
||||||
return op.Link(ctx, storage, actualPath, args)
|
|
||||||
}
|
|
||||||
func NewFsLinkService() FsLinkService {
|
|
||||||
return &fsLinkService{}
|
|
||||||
}
|
|
||||||
@@ -1,198 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
stdpath "path"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/op"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/singleflight"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils"
|
|
||||||
"github.com/Xhofe/go-cache"
|
|
||||||
|
|
||||||
log "github.com/dsoprea/go-logging"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
|
||||||
|
|
||||||
type FsListService interface {
|
|
||||||
FsList(ctx context.Context, path string, refresh ...bool) ([]model.Obj, error)
|
|
||||||
Key(storage driver.Driver, path string) string
|
|
||||||
Get(ctx context.Context, storage driver.Driver, path string) (model.Obj, error)
|
|
||||||
GetUnwrap(ctx context.Context, storage driver.Driver, path string) (model.Obj, error)
|
|
||||||
List(ctx context.Context, storage driver.Driver, path string, args model.ListArgs, refresh ...bool) ([]model.Obj, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type fsListService struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
var listCache = cache.NewMemCache(cache.WithShards[[]model.Obj](64))
|
|
||||||
var listG singleflight.Group[[]model.Obj]
|
|
||||||
|
|
||||||
// List files
|
|
||||||
func (fl *fsListService) FsList(ctx context.Context, path string, refresh ...bool) ([]model.Obj, error) {
|
|
||||||
|
|
||||||
virtualFiles := MyService.Storages().GetStorageVirtualFilesByPath(path)
|
|
||||||
storage, actualPath, err := MyService.StoragePath().GetStorageAndActualPath(path)
|
|
||||||
if err != nil && len(virtualFiles) == 0 {
|
|
||||||
return nil, errors.WithMessage(err, "failed get storage")
|
|
||||||
}
|
|
||||||
|
|
||||||
var _objs []model.Obj
|
|
||||||
if storage != nil {
|
|
||||||
_objs, err = fl.List(ctx, storage, actualPath, model.ListArgs{
|
|
||||||
ReqPath: path,
|
|
||||||
}, refresh...)
|
|
||||||
if err != nil {
|
|
||||||
log.Errorf("%+v", err)
|
|
||||||
if len(virtualFiles) == 0 {
|
|
||||||
return nil, errors.WithMessage(err, "failed get objs")
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
om := model.NewObjMerge()
|
|
||||||
|
|
||||||
objs := om.Merge(virtualFiles, _objs...)
|
|
||||||
return objs, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fl *fsListService) Key(storage driver.Driver, path string) string {
|
|
||||||
return stdpath.Join(storage.GetStorage().MountPath, utils.FixAndCleanPath(path))
|
|
||||||
}
|
|
||||||
|
|
||||||
// Get object from list of files
|
|
||||||
func (fl *fsListService) Get(ctx context.Context, storage driver.Driver, path string) (model.Obj, error) {
|
|
||||||
path = utils.FixAndCleanPath(path)
|
|
||||||
logger.Info("get", zap.String("path", path))
|
|
||||||
|
|
||||||
// is root folder
|
|
||||||
if utils.PathEqual(path, "/") {
|
|
||||||
var rootObj model.Obj
|
|
||||||
switch r := storage.GetAddition().(type) {
|
|
||||||
case driver.IRootId:
|
|
||||||
rootObj = &model.Object{
|
|
||||||
ID: r.GetRootId(),
|
|
||||||
Name: op.RootName,
|
|
||||||
Size: 0,
|
|
||||||
Modified: storage.GetStorage().Modified,
|
|
||||||
IsFolder: true,
|
|
||||||
}
|
|
||||||
case driver.IRootPath:
|
|
||||||
rootObj = &model.Object{
|
|
||||||
Path: r.GetRootPath(),
|
|
||||||
Name: op.RootName,
|
|
||||||
Size: 0,
|
|
||||||
Modified: storage.GetStorage().Modified,
|
|
||||||
IsFolder: true,
|
|
||||||
}
|
|
||||||
default:
|
|
||||||
if storage, ok := storage.(driver.Getter); ok {
|
|
||||||
obj, err := storage.GetRoot(ctx)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.WithMessage(err, "failed get root obj")
|
|
||||||
}
|
|
||||||
rootObj = obj
|
|
||||||
}
|
|
||||||
}
|
|
||||||
if rootObj == nil {
|
|
||||||
return nil, errors.Errorf("please implement IRootPath or IRootId or Getter method")
|
|
||||||
}
|
|
||||||
return &model.ObjWrapName{
|
|
||||||
Name: op.RootName,
|
|
||||||
Obj: rootObj,
|
|
||||||
}, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// not root folder
|
|
||||||
dir, name := stdpath.Split(path)
|
|
||||||
files, err := fl.List(ctx, storage, dir, model.ListArgs{})
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.WithMessage(err, "failed get parent list")
|
|
||||||
}
|
|
||||||
for _, f := range files {
|
|
||||||
// TODO maybe copy obj here
|
|
||||||
if f.GetName() == name {
|
|
||||||
return f, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
logger.Info("cant find obj with name", zap.Any("name", name))
|
|
||||||
return nil, errors.WithStack(errors.New("object not found"))
|
|
||||||
}
|
|
||||||
|
|
||||||
func (fl *fsListService) GetUnwrap(ctx context.Context, storage driver.Driver, path string) (model.Obj, error) {
|
|
||||||
obj, err := fl.Get(ctx, storage, path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, err
|
|
||||||
}
|
|
||||||
return model.UnwrapObjs(obj), err
|
|
||||||
}
|
|
||||||
|
|
||||||
// List files in storage, not contains virtual file
|
|
||||||
func (fl *fsListService) List(ctx context.Context, storage driver.Driver, path string, args model.ListArgs, refresh ...bool) ([]model.Obj, error) {
|
|
||||||
if storage.Config().CheckStatus && storage.GetStorage().Status != op.WORK {
|
|
||||||
return nil, errors.Errorf("storage not init: %s", storage.GetStorage().Status)
|
|
||||||
}
|
|
||||||
path = utils.FixAndCleanPath(path)
|
|
||||||
logger.Info("op.List", zap.Any("path", path))
|
|
||||||
key := fl.Key(storage, path)
|
|
||||||
if !utils.IsBool(refresh...) {
|
|
||||||
if files, ok := listCache.Get(key); ok {
|
|
||||||
logger.Info("op.List", zap.Any("use cache", path))
|
|
||||||
return files, nil
|
|
||||||
}
|
|
||||||
}
|
|
||||||
dir, err := fl.GetUnwrap(ctx, storage, path)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.WithMessage(err, "failed get dir")
|
|
||||||
}
|
|
||||||
logger.Info("op.List", zap.Any("dir", dir))
|
|
||||||
if !dir.IsDir() {
|
|
||||||
return nil, errors.WithStack(errors.New("not a folder"))
|
|
||||||
}
|
|
||||||
objs, err, _ := listG.Do(key, func() ([]model.Obj, error) {
|
|
||||||
files, err := storage.List(ctx, dir, args)
|
|
||||||
if err != nil {
|
|
||||||
return nil, errors.Wrapf(err, "failed to list objs")
|
|
||||||
}
|
|
||||||
// set path
|
|
||||||
for _, f := range files {
|
|
||||||
if s, ok := f.(model.SetPath); ok && f.GetPath() == "" && dir.GetPath() != "" {
|
|
||||||
s.SetPath(stdpath.Join(dir.GetPath(), f.GetName()))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
// warp obj name
|
|
||||||
model.WrapObjsName(files)
|
|
||||||
// call hooks
|
|
||||||
go func(reqPath string, files []model.Obj) {
|
|
||||||
for _, hook := range op.ObjsUpdateHooks {
|
|
||||||
hook(args.ReqPath, files)
|
|
||||||
}
|
|
||||||
}(args.ReqPath, files)
|
|
||||||
|
|
||||||
// sort objs
|
|
||||||
if storage.Config().LocalSort {
|
|
||||||
model.SortFiles(files, storage.GetStorage().OrderBy, storage.GetStorage().OrderDirection)
|
|
||||||
}
|
|
||||||
model.ExtractFolder(files, storage.GetStorage().ExtractFolder)
|
|
||||||
|
|
||||||
if !storage.Config().NoCache {
|
|
||||||
if len(files) > 0 {
|
|
||||||
logger.Info("set cache", zap.Any("key", key), zap.Any("files", files))
|
|
||||||
listCache.Set(key, files, cache.WithEx[[]model.Obj](time.Minute*time.Duration(storage.GetStorage().CacheExpiration)))
|
|
||||||
} else {
|
|
||||||
logger.Info("del cache", zap.Any("key", key))
|
|
||||||
listCache.Del(key)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return files, nil
|
|
||||||
})
|
|
||||||
return objs, err
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewFsListService() FsListService {
|
|
||||||
return &fsListService{}
|
|
||||||
}
|
|
||||||
16
service/model/o_drive.go
Normal file
16
service/model/o_drive.go
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
package model
|
||||||
|
|
||||||
|
type PeerDriveDBModel struct {
|
||||||
|
ID string `gorm:"column:id;primary_key" json:"id"`
|
||||||
|
Updated int64 `gorm:"autoUpdateTime"`
|
||||||
|
Created int64 `gorm:"autoCreateTime"`
|
||||||
|
UserAgent string `json:"user_agent"`
|
||||||
|
DisplayName string `json:"display_name"`
|
||||||
|
DeviceName string `json:"device_name"`
|
||||||
|
Model string `json:"model"`
|
||||||
|
|
||||||
|
IP string `json:"ip"`
|
||||||
|
OS string `json:"os"`
|
||||||
|
Browser string `json:"browser"`
|
||||||
|
Online bool `gorm:"-" json:"online"`
|
||||||
|
}
|
||||||
@@ -15,6 +15,7 @@ import (
|
|||||||
|
|
||||||
type OtherService interface {
|
type OtherService interface {
|
||||||
Search(key string) ([]model.SearchEngine, error)
|
Search(key string) ([]model.SearchEngine, error)
|
||||||
|
AgentSearch(url string) ([]byte, error)
|
||||||
}
|
}
|
||||||
|
|
||||||
type otherService struct{}
|
type otherService struct{}
|
||||||
@@ -99,6 +100,17 @@ func (s *otherService) Search(key string) ([]model.SearchEngine, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *otherService) AgentSearch(url string) ([]byte, error) {
|
||||||
|
client := resty.New()
|
||||||
|
client.SetTimeout(3 * time.Second) // 设置全局超时时间
|
||||||
|
resp, err := client.R().Get(url)
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("Then get search result error: %v", zap.Error(err), zap.String("url", url))
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
return resp.Body(), nil
|
||||||
|
}
|
||||||
|
|
||||||
func NewOtherService() OtherService {
|
func NewOtherService() OtherService {
|
||||||
return &otherService{}
|
return &otherService{}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -2,11 +2,16 @@ package service
|
|||||||
|
|
||||||
import (
|
import (
|
||||||
"testing"
|
"testing"
|
||||||
|
|
||||||
|
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
||||||
|
"go.uber.org/goleak"
|
||||||
)
|
)
|
||||||
|
|
||||||
func TestSearch(t *testing.T) {
|
func TestSearch(t *testing.T) {
|
||||||
if d, e := NewOtherService().Search("test"); e != nil || d == nil {
|
logger.LogInitConsoleOnly()
|
||||||
|
goleak.VerifyNone(t)
|
||||||
|
|
||||||
|
if d, e := NewOtherService().Search("test"); e != nil || d == nil {
|
||||||
t.Error("then test search error", e)
|
t.Error("then test search error", e)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
59
service/peer.go
Normal file
59
service/peer.go
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
/*
|
||||||
|
* @Author: LinkLeong link@icewhale.org
|
||||||
|
* @Date: 2022-07-26 18:13:22
|
||||||
|
* @LastEditors: LinkLeong
|
||||||
|
* @LastEditTime: 2022-08-04 20:10:31
|
||||||
|
* @FilePath: /CasaOS/service/connections.go
|
||||||
|
* @Description:
|
||||||
|
* @Website: https://www.casaos.io
|
||||||
|
* Copyright (c) 2022 by icewhale, All Rights Reserved.
|
||||||
|
*/
|
||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
"gorm.io/gorm"
|
||||||
|
)
|
||||||
|
|
||||||
|
type PeerService interface {
|
||||||
|
GetPeerByUserAgent(ua string) (m model2.PeerDriveDBModel)
|
||||||
|
GetPeerByID(id string) (m model2.PeerDriveDBModel)
|
||||||
|
GetPeers() (peers []model2.PeerDriveDBModel)
|
||||||
|
CreatePeer(m *model2.PeerDriveDBModel)
|
||||||
|
DeletePeer(id string)
|
||||||
|
GetPeerByName(name string) (m model2.PeerDriveDBModel)
|
||||||
|
}
|
||||||
|
|
||||||
|
type peerStruct struct {
|
||||||
|
db *gorm.DB
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *peerStruct) GetPeerByName(name string) (m model2.PeerDriveDBModel) {
|
||||||
|
s.db.Where("display_name = ?", name).First(&m)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (s *peerStruct) GetPeerByUserAgent(ua string) (m model2.PeerDriveDBModel) {
|
||||||
|
s.db.Where("user_agent = ?", ua).First(&m)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (s *peerStruct) GetPeerByID(id string) (m model2.PeerDriveDBModel) {
|
||||||
|
s.db.Where("id = ?", id).First(&m)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (s *peerStruct) GetPeers() (peers []model2.PeerDriveDBModel) {
|
||||||
|
s.db.Order("updated desc").Find(&peers)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
func (s *peerStruct) CreatePeer(m *model2.PeerDriveDBModel) {
|
||||||
|
|
||||||
|
s.db.Create(m)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *peerStruct) DeletePeer(id string) {
|
||||||
|
s.db.Where("id= ?", id).Delete(&model.PeerDriveDBModel{})
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewPeerService(db *gorm.DB) PeerService {
|
||||||
|
return &peerStruct{db: db}
|
||||||
|
}
|
||||||
@@ -40,12 +40,8 @@ type Repository interface {
|
|||||||
Shares() SharesService
|
Shares() SharesService
|
||||||
System() SystemService
|
System() SystemService
|
||||||
Storage() StorageService
|
Storage() StorageService
|
||||||
Storages() StoragesService
|
|
||||||
StoragePath() StoragePathService
|
|
||||||
FsListService() FsListService
|
|
||||||
FsLinkService() FsLinkService
|
|
||||||
FsService() FsService
|
|
||||||
MessageBus() *message_bus.ClientWithResponses
|
MessageBus() *message_bus.ClientWithResponses
|
||||||
|
Peer() PeerService
|
||||||
Other() OtherService
|
Other() OtherService
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,70 +52,48 @@ func NewService(db *gorm.DB, RuntimePath string) Repository {
|
|||||||
}
|
}
|
||||||
|
|
||||||
return &store{
|
return &store{
|
||||||
casa: NewCasaService(),
|
casa: NewCasaService(),
|
||||||
connections: NewConnectionsService(db),
|
connections: NewConnectionsService(db),
|
||||||
gateway: gatewayManagement,
|
gateway: gatewayManagement,
|
||||||
notify: NewNotifyService(db),
|
notify: NewNotifyService(db),
|
||||||
rely: NewRelyService(db),
|
rely: NewRelyService(db),
|
||||||
system: NewSystemService(),
|
system: NewSystemService(),
|
||||||
health: NewHealthService(),
|
health: NewHealthService(),
|
||||||
shares: NewSharesService(db),
|
shares: NewSharesService(db),
|
||||||
storage: NewStorageService(),
|
storage: NewStorageService(),
|
||||||
storages: NewStoragesService(),
|
other: NewOtherService(),
|
||||||
storage_path: NewStoragePathService(),
|
|
||||||
fs_list: NewFsListService(),
|
peer: NewPeerService(db),
|
||||||
fs_link: NewFsLinkService(),
|
|
||||||
fs: NewFsService(),
|
|
||||||
other: NewOtherService(),
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
type store struct {
|
type store struct {
|
||||||
db *gorm.DB
|
peer PeerService
|
||||||
casa CasaService
|
db *gorm.DB
|
||||||
notify NotifyServer
|
casa CasaService
|
||||||
rely RelyService
|
notify NotifyServer
|
||||||
system SystemService
|
rely RelyService
|
||||||
shares SharesService
|
system SystemService
|
||||||
connections ConnectionsService
|
shares SharesService
|
||||||
gateway external.ManagementService
|
connections ConnectionsService
|
||||||
storage StorageService
|
gateway external.ManagementService
|
||||||
storages StoragesService
|
storage StorageService
|
||||||
storage_path StoragePathService
|
health HealthService
|
||||||
fs_list FsListService
|
other OtherService
|
||||||
fs_link FsLinkService
|
|
||||||
fs FsService
|
|
||||||
health HealthService
|
|
||||||
other OtherService
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *store) Other() OtherService {
|
|
||||||
return c.other
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *store) FsLinkService() FsLinkService {
|
|
||||||
return c.fs_link
|
|
||||||
}
|
|
||||||
func (c *store) FsService() FsService {
|
|
||||||
return c.fs
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *store) FsListService() FsListService {
|
|
||||||
return c.fs_list
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *store) StoragePath() StoragePathService {
|
|
||||||
return c.storage_path
|
|
||||||
}
|
|
||||||
|
|
||||||
func (c *store) Storages() StoragesService {
|
|
||||||
return c.storages
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *store) Storage() StorageService {
|
func (c *store) Storage() StorageService {
|
||||||
return c.storage
|
return c.storage
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *store) Peer() PeerService {
|
||||||
|
return c.peer
|
||||||
|
}
|
||||||
|
|
||||||
|
func (c *store) Other() OtherService {
|
||||||
|
return c.other
|
||||||
|
}
|
||||||
|
|
||||||
func (c *store) Gateway() external.ManagementService {
|
func (c *store) Gateway() external.ManagementService {
|
||||||
return c.gateway
|
return c.gateway
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -82,7 +82,7 @@ read only = No
|
|||||||
guest ok = Yes
|
guest ok = Yes
|
||||||
create mask = 0777
|
create mask = 0777
|
||||||
directory mask = 0777
|
directory mask = 0777
|
||||||
guest account = root
|
force user = root
|
||||||
|
|
||||||
`
|
`
|
||||||
}
|
}
|
||||||
|
|||||||
102
service/socket.go
Normal file
102
service/socket.go
Normal file
@@ -0,0 +1,102 @@
|
|||||||
|
package service
|
||||||
|
|
||||||
|
import (
|
||||||
|
"net/http"
|
||||||
|
"strconv"
|
||||||
|
"strings"
|
||||||
|
|
||||||
|
model2 "github.com/IceWhaleTech/CasaOS/service/model"
|
||||||
|
"github.com/mileusna/useragent"
|
||||||
|
)
|
||||||
|
|
||||||
|
type Name struct {
|
||||||
|
Model string `json:"model"`
|
||||||
|
OS string `json:"os"`
|
||||||
|
Browser string `json:"browser"`
|
||||||
|
DeviceName string `json:"deviceName"`
|
||||||
|
DisplayName string `json:"displayName"`
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetPeerId(request *http.Request, id string) string {
|
||||||
|
cookiePree, err := request.Cookie("peerid")
|
||||||
|
if err != nil {
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
if len(cookiePree.Value) > 0 {
|
||||||
|
return cookiePree.Value
|
||||||
|
}
|
||||||
|
return id
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetIP(request *http.Request) string {
|
||||||
|
ip := ""
|
||||||
|
if len(request.Header.Get("x-forwarded-for")) > 0 {
|
||||||
|
ip = strings.Split(request.Header.Get("x-forwarded-for"), ",")[0]
|
||||||
|
} else {
|
||||||
|
ip = request.RemoteAddr
|
||||||
|
}
|
||||||
|
|
||||||
|
if ip == "::1" || ip == "::ffff:127.0.0.1" {
|
||||||
|
ip = "127.0.0.1"
|
||||||
|
}
|
||||||
|
return ip
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetName(request *http.Request) Name {
|
||||||
|
us := useragent.Parse(request.Header.Get("user-agent"))
|
||||||
|
device := ""
|
||||||
|
if len(us.Device) > 0 {
|
||||||
|
device += us.Device
|
||||||
|
} else {
|
||||||
|
device += us.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
display := ""
|
||||||
|
if len(us.Device) > 0 {
|
||||||
|
display = us.Device + " " + us.Name
|
||||||
|
} else {
|
||||||
|
display = us.OS + " " + us.Name
|
||||||
|
}
|
||||||
|
|
||||||
|
model := "desktop"
|
||||||
|
if us.Mobile {
|
||||||
|
model = "mobile"
|
||||||
|
}
|
||||||
|
if us.Tablet {
|
||||||
|
model = "tablet"
|
||||||
|
}
|
||||||
|
peer := MyService.Peer().GetPeerByName(display)
|
||||||
|
if len(peer.ID) > 0 {
|
||||||
|
for i := 0; true; i++ {
|
||||||
|
peer = MyService.Peer().GetPeerByName(display + "_" + strconv.Itoa(i+1))
|
||||||
|
if len(peer.ID) == 0 {
|
||||||
|
display = display + "_" + strconv.Itoa(i+1)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return Name{
|
||||||
|
Model: model,
|
||||||
|
OS: us.OS,
|
||||||
|
Browser: us.Name,
|
||||||
|
DeviceName: device,
|
||||||
|
DisplayName: display,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetNameByDB(m model2.PeerDriveDBModel) Name {
|
||||||
|
device := ""
|
||||||
|
if len(m.DeviceName) > 0 {
|
||||||
|
device += m.DeviceName
|
||||||
|
} else {
|
||||||
|
device += m.Browser
|
||||||
|
}
|
||||||
|
return Name{
|
||||||
|
Model: m.Model,
|
||||||
|
OS: m.OS,
|
||||||
|
Browser: m.Browser,
|
||||||
|
DeviceName: device,
|
||||||
|
DisplayName: m.DisplayName,
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,73 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"fmt"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"gorm.io/gorm"
|
|
||||||
)
|
|
||||||
|
|
||||||
type StorageOldService interface {
|
|
||||||
CreateStorage(storage *model.Storage) error
|
|
||||||
UpdateStorage(storage *model.Storage) error
|
|
||||||
DeleteStorageById(id uint) error
|
|
||||||
GetStorages(pageIndex, pageSize int) ([]model.Storage, int64, error)
|
|
||||||
GetStorageById(id uint) (*model.Storage, error)
|
|
||||||
GetEnabledStorages() ([]model.Storage, error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type storageOldStruct struct {
|
|
||||||
db *gorm.DB
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateStorage just insert storage to database
|
|
||||||
func (s *storageOldStruct) CreateStorage(storage *model.Storage) error {
|
|
||||||
return errors.WithStack(s.db.Create(storage).Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateStorage just update storage in database
|
|
||||||
func (s *storageOldStruct) UpdateStorage(storage *model.Storage) error {
|
|
||||||
return errors.WithStack(s.db.Save(storage).Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// DeleteStorageById just delete storage from database by id
|
|
||||||
func (s *storageOldStruct) DeleteStorageById(id uint) error {
|
|
||||||
return errors.WithStack(s.db.Delete(&model.Storage{}, id).Error)
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStorages Get all storages from database order by index
|
|
||||||
func (s *storageOldStruct) GetStorages(pageIndex, pageSize int) ([]model.Storage, int64, error) {
|
|
||||||
storageDB := s.db.Model(&model.Storage{})
|
|
||||||
var count int64
|
|
||||||
if err := storageDB.Count(&count).Error; err != nil {
|
|
||||||
return nil, 0, errors.Wrapf(err, "failed get storages count")
|
|
||||||
}
|
|
||||||
var storages []model.Storage
|
|
||||||
if err := storageDB.Order("`order`").Offset((pageIndex - 1) * pageSize).Limit(pageSize).Find(&storages).Error; err != nil {
|
|
||||||
return nil, 0, errors.WithStack(err)
|
|
||||||
}
|
|
||||||
return storages, count, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStorageById Get Storage by id, used to update storage usually
|
|
||||||
func (s *storageOldStruct) GetStorageById(id uint) (*model.Storage, error) {
|
|
||||||
var storage model.Storage
|
|
||||||
storage.ID = id
|
|
||||||
if err := s.db.First(&storage).Error; err != nil {
|
|
||||||
return nil, errors.WithStack(err)
|
|
||||||
}
|
|
||||||
return &storage, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storageOldStruct) GetEnabledStorages() ([]model.Storage, error) {
|
|
||||||
var storages []model.Storage
|
|
||||||
if err := s.db.Where(fmt.Sprintf("%s = ?", "disabled"), false).Find(&storages).Error; err != nil {
|
|
||||||
return nil, errors.WithStack(err)
|
|
||||||
}
|
|
||||||
return storages, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func NewStorageOldService(db *gorm.DB) StorageOldService {
|
|
||||||
return &storageOldStruct{db: db}
|
|
||||||
}
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"strings"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
)
|
|
||||||
|
|
||||||
type StoragePathService interface {
|
|
||||||
GetStorageAndActualPath(rawPath string) (storage driver.Driver, actualPath string, err error)
|
|
||||||
}
|
|
||||||
|
|
||||||
type storagePathStruct struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storagePathStruct) GetStorageAndActualPath(rawPath string) (storage driver.Driver, actualPath string, err error) {
|
|
||||||
rawPath = utils.FixAndCleanPath(rawPath)
|
|
||||||
storage = MyService.Storages().GetBalancedStorage(rawPath)
|
|
||||||
if storage == nil {
|
|
||||||
err = errors.Errorf("can't find storage with rawPath: %s", rawPath)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
logger.Info("use storage", zap.Any("storage mount path", storage.GetStorage().MountPath))
|
|
||||||
mountPath := utils.GetActualMountPath(storage.GetStorage().MountPath)
|
|
||||||
actualPath = utils.FixAndCleanPath(strings.TrimPrefix(rawPath, mountPath))
|
|
||||||
return
|
|
||||||
}
|
|
||||||
func NewStoragePathService() StoragePathService {
|
|
||||||
return &storagePathStruct{}
|
|
||||||
}
|
|
||||||
@@ -1,398 +0,0 @@
|
|||||||
package service
|
|
||||||
|
|
||||||
import (
|
|
||||||
"context"
|
|
||||||
"sort"
|
|
||||||
"strings"
|
|
||||||
"time"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS-Common/utils/logger"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/utils"
|
|
||||||
jsoniter "github.com/json-iterator/go"
|
|
||||||
"go.uber.org/zap"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/pkg/generic_sync"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/model"
|
|
||||||
|
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/driver"
|
|
||||||
"github.com/IceWhaleTech/CasaOS/internal/op"
|
|
||||||
mapset "github.com/deckarep/golang-set/v2"
|
|
||||||
"github.com/pkg/errors"
|
|
||||||
)
|
|
||||||
|
|
||||||
type StoragesService interface {
|
|
||||||
HasStorage(mountPath string) bool
|
|
||||||
CreateStorage(ctx context.Context, storage model.Storage) (uint, error)
|
|
||||||
LoadStorage(ctx context.Context, storage model.Storage) error
|
|
||||||
EnableStorage(ctx context.Context, id uint) error
|
|
||||||
DisableStorage(ctx context.Context, id uint) error
|
|
||||||
UpdateStorage(ctx context.Context, storage model.Storage) error
|
|
||||||
DeleteStorageById(ctx context.Context, id uint) error
|
|
||||||
MustSaveDriverStorage(driver driver.Driver) error
|
|
||||||
GetStorageVirtualFilesByPath(prefix string) []model.Obj
|
|
||||||
initStorage(ctx context.Context, storage model.Storage, storageDriver driver.Driver, setMountPath func(d driver.Driver, ctx context.Context) string) (err error)
|
|
||||||
InitStorages()
|
|
||||||
GetBalancedStorage(path string) driver.Driver
|
|
||||||
}
|
|
||||||
|
|
||||||
type storagesStruct struct {
|
|
||||||
}
|
|
||||||
|
|
||||||
// Although the driver type is stored,
|
|
||||||
// there is a storage in each driver,
|
|
||||||
// so it should actually be a storage, just wrapped by the driver
|
|
||||||
var storagesMap generic_sync.MapOf[string, driver.Driver]
|
|
||||||
|
|
||||||
func GetAllStorages() []driver.Driver {
|
|
||||||
return storagesMap.Values()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storagesStruct) HasStorage(mountPath string) bool {
|
|
||||||
return storagesMap.Has(utils.FixAndCleanPath(mountPath))
|
|
||||||
}
|
|
||||||
|
|
||||||
func GetStorageByMountPath(mountPath string) (driver.Driver, error) {
|
|
||||||
mountPath = utils.FixAndCleanPath(mountPath)
|
|
||||||
storageDriver, ok := storagesMap.Load(mountPath)
|
|
||||||
if !ok {
|
|
||||||
return nil, errors.Errorf("no mount path for an storage is: %s", mountPath)
|
|
||||||
}
|
|
||||||
return storageDriver, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// CreateStorage Save the storage to database so storage can get an id
|
|
||||||
// then instantiate corresponding driver and save it in memory
|
|
||||||
func (s *storagesStruct) CreateStorage(ctx context.Context, storage model.Storage) (uint, error) {
|
|
||||||
storage.Modified = time.Now()
|
|
||||||
storage.MountPath = utils.FixAndCleanPath(storage.MountPath)
|
|
||||||
var err error
|
|
||||||
// check driver first
|
|
||||||
driverName := storage.Driver
|
|
||||||
driverNew, err := op.GetDriverNew(driverName)
|
|
||||||
if err != nil {
|
|
||||||
return 0, errors.WithMessage(err, "failed get driver new")
|
|
||||||
}
|
|
||||||
storageDriver := driverNew()
|
|
||||||
// // insert storage to database
|
|
||||||
// err = MyService.Storage().CreateStorage(&storage)
|
|
||||||
// if err != nil {
|
|
||||||
|
|
||||||
// return storage.ID, errors.WithMessage(err, "failed create storage in database")
|
|
||||||
// }
|
|
||||||
// already has an id
|
|
||||||
err = s.initStorage(ctx, storage, storageDriver, func(d driver.Driver, ctx context.Context) string {
|
|
||||||
u, _ := d.GetUserInfo(ctx)
|
|
||||||
if len(u) > 0 {
|
|
||||||
a := strings.Split(u, "@")
|
|
||||||
u = a[0]
|
|
||||||
}
|
|
||||||
return u
|
|
||||||
})
|
|
||||||
if err != nil {
|
|
||||||
s.DeleteStorageById(ctx, storage.ID)
|
|
||||||
return storage.ID, errors.Wrap(err, "failed init storage")
|
|
||||||
}
|
|
||||||
|
|
||||||
go op.CallStorageHooks("add", storageDriver)
|
|
||||||
|
|
||||||
logger.Error("storage created", zap.Any("storage", storageDriver))
|
|
||||||
return storage.ID, nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// LoadStorage load exist storage in db to memory
|
|
||||||
func (s *storagesStruct) LoadStorage(ctx context.Context, storage model.Storage) error {
|
|
||||||
storage.MountPath = utils.FixAndCleanPath(storage.MountPath)
|
|
||||||
// check driver first
|
|
||||||
driverName := storage.Driver
|
|
||||||
driverNew, err := op.GetDriverNew(driverName)
|
|
||||||
if err != nil {
|
|
||||||
return errors.WithMessage(err, "failed get driver new")
|
|
||||||
}
|
|
||||||
storageDriver := driverNew()
|
|
||||||
|
|
||||||
err = s.initStorage(ctx, storage, storageDriver, nil)
|
|
||||||
go op.CallStorageHooks("add", storageDriver)
|
|
||||||
logger.Info("storage created", zap.Any("storage", storageDriver))
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
// initStorage initialize the driver and store to storagesMap
|
|
||||||
func (s *storagesStruct) initStorage(ctx context.Context, storage model.Storage, storageDriver driver.Driver, setMountPath func(d driver.Driver, ctx context.Context) string) (err error) {
|
|
||||||
storageDriver.SetStorage(storage)
|
|
||||||
driverStorage := storageDriver.GetStorage()
|
|
||||||
|
|
||||||
// Unmarshal Addition
|
|
||||||
|
|
||||||
var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
|
||||||
|
|
||||||
err = json.UnmarshalFromString(driverStorage.Addition, storageDriver.GetAddition())
|
|
||||||
if err == nil {
|
|
||||||
err = storageDriver.Init(ctx)
|
|
||||||
}
|
|
||||||
if setMountPath != nil {
|
|
||||||
driverStorage.MountPath += "_" + setMountPath(storageDriver, ctx)
|
|
||||||
|
|
||||||
}
|
|
||||||
if s.HasStorage(driverStorage.MountPath) {
|
|
||||||
return errors.New("mount path already exists")
|
|
||||||
}
|
|
||||||
storageDriver.SetStorage(*driverStorage)
|
|
||||||
storagesMap.Store(driverStorage.MountPath, storageDriver)
|
|
||||||
|
|
||||||
if err != nil {
|
|
||||||
driverStorage.SetStatus(err.Error())
|
|
||||||
err = errors.Wrap(err, "failed init storage")
|
|
||||||
} else {
|
|
||||||
driverStorage.SetStatus(op.WORK)
|
|
||||||
}
|
|
||||||
|
|
||||||
err = s.MustSaveDriverStorage(storageDriver)
|
|
||||||
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storagesStruct) EnableStorage(ctx context.Context, id uint) error {
|
|
||||||
// storage, err := MyService.Storage().GetStorageById(id)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed get storage")
|
|
||||||
// }
|
|
||||||
// if !storage.Disabled {
|
|
||||||
// return errors.Errorf("this storage have enabled")
|
|
||||||
// }
|
|
||||||
// storage.Disabled = false
|
|
||||||
// err = MyService.Storage().UpdateStorage(storage)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed update storage in db")
|
|
||||||
// }
|
|
||||||
// err = s.LoadStorage(ctx, *storage)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed load storage")
|
|
||||||
// }
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storagesStruct) DisableStorage(ctx context.Context, id uint) error {
|
|
||||||
// storage, err := MyService.Storage().GetStorageById(id)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed get storage")
|
|
||||||
// }
|
|
||||||
// if storage.Disabled {
|
|
||||||
// return errors.Errorf("this storage have disabled")
|
|
||||||
// }
|
|
||||||
// storageDriver, err := GetStorageByMountPath(storage.MountPath)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed get storage driver")
|
|
||||||
// }
|
|
||||||
// // drop the storage in the driver
|
|
||||||
// if err := storageDriver.Drop(ctx); err != nil {
|
|
||||||
// return errors.Wrap(err, "failed drop storage")
|
|
||||||
// }
|
|
||||||
// // delete the storage in the memory
|
|
||||||
// storage.Disabled = true
|
|
||||||
// err = MyService.Storage().UpdateStorage(storage)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed update storage in db")
|
|
||||||
// }
|
|
||||||
// storagesMap.Delete(storage.MountPath)
|
|
||||||
// go op.CallStorageHooks("del", storageDriver)
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// UpdateStorage update storage
|
|
||||||
// get old storage first
|
|
||||||
// drop the storage then reinitialize
|
|
||||||
func (s *storagesStruct) UpdateStorage(ctx context.Context, storage model.Storage) error {
|
|
||||||
// oldStorage, err := MyService.Storage().GetStorageById(storage.ID)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed get old storage")
|
|
||||||
// }
|
|
||||||
// if oldStorage.Driver != storage.Driver {
|
|
||||||
// return errors.Errorf("driver cannot be changed")
|
|
||||||
// }
|
|
||||||
// storage.Modified = time.Now()
|
|
||||||
// storage.MountPath = utils.FixAndCleanPath(storage.MountPath)
|
|
||||||
// err = MyService.Storage().UpdateStorage(&storage)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed update storage in database")
|
|
||||||
// }
|
|
||||||
// if storage.Disabled {
|
|
||||||
// return nil
|
|
||||||
// }
|
|
||||||
// storageDriver, err := GetStorageByMountPath(oldStorage.MountPath)
|
|
||||||
// if oldStorage.MountPath != storage.MountPath {
|
|
||||||
// // mount path renamed, need to drop the storage
|
|
||||||
// storagesMap.Delete(oldStorage.MountPath)
|
|
||||||
// }
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed get storage driver")
|
|
||||||
// }
|
|
||||||
// err = storageDriver.Drop(ctx)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.Wrapf(err, "failed drop storage")
|
|
||||||
// }
|
|
||||||
|
|
||||||
// err = s.initStorage(ctx, storage, storageDriver, nil)
|
|
||||||
// go op.CallStorageHooks("update", storageDriver)
|
|
||||||
|
|
||||||
// logger.Info("storage updated", zap.Any("storage", storageDriver))
|
|
||||||
//return err
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *storagesStruct) DeleteStorageById(ctx context.Context, id uint) error {
|
|
||||||
// storage, err := MyService.Storage().GetStorageById(id)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed get storage")
|
|
||||||
// }
|
|
||||||
// if !storage.Disabled {
|
|
||||||
// storageDriver, err := GetStorageByMountPath(storage.MountPath)
|
|
||||||
// if err == nil {
|
|
||||||
// // drop the storage in the driver
|
|
||||||
// if err := storageDriver.Drop(ctx); err != nil {
|
|
||||||
// return errors.Wrapf(err, "failed drop storage")
|
|
||||||
// }
|
|
||||||
// // delete the storage in the memory
|
|
||||||
// storagesMap.Delete(storage.MountPath)
|
|
||||||
// }
|
|
||||||
|
|
||||||
// go op.CallStorageHooks("del", storageDriver)
|
|
||||||
// }
|
|
||||||
// // delete the storage in the database
|
|
||||||
// if err := MyService.Storage().DeleteStorageById(id); err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed delete storage in database")
|
|
||||||
// }
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// MustSaveDriverStorage call from specific driver
|
|
||||||
func (s *storagesStruct) MustSaveDriverStorage(driver driver.Driver) error {
|
|
||||||
err := saveDriverStorage(driver)
|
|
||||||
if err != nil {
|
|
||||||
logger.Error("failed save driver storage", zap.Any("err", err))
|
|
||||||
}
|
|
||||||
return err
|
|
||||||
}
|
|
||||||
|
|
||||||
func saveDriverStorage(driver driver.Driver) error {
|
|
||||||
// storage := driver.GetStorage()
|
|
||||||
// addition := driver.GetAddition()
|
|
||||||
|
|
||||||
// var json = jsoniter.ConfigCompatibleWithStandardLibrary
|
|
||||||
|
|
||||||
// str, err := json.MarshalToString(addition)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.Wrap(err, "error while marshal addition")
|
|
||||||
// }
|
|
||||||
// storage.Addition = str
|
|
||||||
// err = MyService.Storage().UpdateStorage(storage)
|
|
||||||
// if err != nil {
|
|
||||||
// return errors.WithMessage(err, "failed update storage in database")
|
|
||||||
// }
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
// getStoragesByPath get storage by longest match path, contains balance storage.
|
|
||||||
// for example, there is /a/b,/a/c,/a/d/e,/a/d/e.balance
|
|
||||||
// getStoragesByPath(/a/d/e/f) => /a/d/e,/a/d/e.balance
|
|
||||||
func getStoragesByPath(path string) []driver.Driver {
|
|
||||||
storages := make([]driver.Driver, 0)
|
|
||||||
curSlashCount := 0
|
|
||||||
storagesMap.Range(func(mountPath string, value driver.Driver) bool {
|
|
||||||
mountPath = utils.GetActualMountPath(mountPath)
|
|
||||||
// is this path
|
|
||||||
if utils.IsSubPath(mountPath, path) {
|
|
||||||
slashCount := strings.Count(utils.PathAddSeparatorSuffix(mountPath), "/")
|
|
||||||
// not the longest match
|
|
||||||
if slashCount > curSlashCount {
|
|
||||||
storages = storages[:0]
|
|
||||||
curSlashCount = slashCount
|
|
||||||
}
|
|
||||||
if slashCount == curSlashCount {
|
|
||||||
storages = append(storages, value)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return true
|
|
||||||
})
|
|
||||||
// make sure the order is the same for same input
|
|
||||||
sort.Slice(storages, func(i, j int) bool {
|
|
||||||
return storages[i].GetStorage().MountPath < storages[j].GetStorage().MountPath
|
|
||||||
})
|
|
||||||
return storages
|
|
||||||
}
|
|
||||||
|
|
||||||
// GetStorageVirtualFilesByPath Obtain the virtual file generated by the storage according to the path
|
|
||||||
// for example, there are: /a/b,/a/c,/a/d/e,/a/b.balance1,/av
|
|
||||||
// GetStorageVirtualFilesByPath(/a) => b,c,d
|
|
||||||
func (s *storagesStruct) GetStorageVirtualFilesByPath(prefix string) []model.Obj {
|
|
||||||
files := make([]model.Obj, 0)
|
|
||||||
storages := storagesMap.Values()
|
|
||||||
sort.Slice(storages, func(i, j int) bool {
|
|
||||||
if storages[i].GetStorage().Order == storages[j].GetStorage().Order {
|
|
||||||
return storages[i].GetStorage().MountPath < storages[j].GetStorage().MountPath
|
|
||||||
}
|
|
||||||
return storages[i].GetStorage().Order < storages[j].GetStorage().Order
|
|
||||||
})
|
|
||||||
|
|
||||||
prefix = utils.FixAndCleanPath(prefix)
|
|
||||||
set := mapset.NewSet[string]()
|
|
||||||
for _, v := range storages {
|
|
||||||
mountPath := utils.GetActualMountPath(v.GetStorage().MountPath)
|
|
||||||
// Exclude prefix itself and non prefix
|
|
||||||
if len(prefix) >= len(mountPath) || !utils.IsSubPath(prefix, mountPath) {
|
|
||||||
continue
|
|
||||||
}
|
|
||||||
name := strings.SplitN(strings.TrimPrefix(mountPath[len(prefix):], "/"), "/", 2)[0]
|
|
||||||
if set.Add(name) {
|
|
||||||
files = append(files, &model.Object{
|
|
||||||
Name: name,
|
|
||||||
Size: 0,
|
|
||||||
Modified: v.GetStorage().Modified,
|
|
||||||
IsFolder: true,
|
|
||||||
})
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return files
|
|
||||||
}
|
|
||||||
|
|
||||||
var balanceMap generic_sync.MapOf[string, int]
|
|
||||||
|
|
||||||
// GetBalancedStorage get storage by path
|
|
||||||
func (s *storagesStruct) GetBalancedStorage(path string) driver.Driver {
|
|
||||||
path = utils.FixAndCleanPath(path)
|
|
||||||
storages := getStoragesByPath(path)
|
|
||||||
storageNum := len(storages)
|
|
||||||
switch storageNum {
|
|
||||||
case 0:
|
|
||||||
return nil
|
|
||||||
case 1:
|
|
||||||
return storages[0]
|
|
||||||
default:
|
|
||||||
virtualPath := utils.GetActualMountPath(storages[0].GetStorage().MountPath)
|
|
||||||
i, _ := balanceMap.LoadOrStore(virtualPath, 0)
|
|
||||||
i = (i + 1) % storageNum
|
|
||||||
balanceMap.Store(virtualPath, i)
|
|
||||||
return storages[i]
|
|
||||||
}
|
|
||||||
}
|
|
||||||
func (s *storagesStruct) InitStorages() {
|
|
||||||
// storages, err := MyService.Storage().GetEnabledStorages()
|
|
||||||
// if err != nil {
|
|
||||||
// logger.Error("failed get enabled storages", zap.Any("err", err))
|
|
||||||
// }
|
|
||||||
// go func(storages []model.Storage) {
|
|
||||||
// for i := range storages {
|
|
||||||
// err := s.LoadStorage(context.Background(), storages[i])
|
|
||||||
// if err != nil {
|
|
||||||
// logger.Error("failed get enabled storages", zap.Any("err", err))
|
|
||||||
// } else {
|
|
||||||
// logger.Info("success load storage", zap.String("mount_path", storages[i].MountPath))
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// conf.StoragesLoaded = true
|
|
||||||
// }(storages)
|
|
||||||
|
|
||||||
}
|
|
||||||
func NewStoragesService() StoragesService {
|
|
||||||
return &storagesStruct{}
|
|
||||||
}
|
|
||||||
@@ -169,7 +169,7 @@ func (c *systemService) GetDirPath(path string) ([]model.Path, error) {
|
|||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ls, err := ioutil.ReadDir(path)
|
ls, err := os.ReadDir(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
logger.Error("when read dir", zap.Error(err))
|
logger.Error("when read dir", zap.Error(err))
|
||||||
return []model.Path{}, err
|
return []model.Path{}, err
|
||||||
@@ -182,7 +182,12 @@ func (c *systemService) GetDirPath(path string) ([]model.Path, error) {
|
|||||||
if err != nil {
|
if err != nil {
|
||||||
link = filePath
|
link = filePath
|
||||||
}
|
}
|
||||||
temp := model.Path{Name: l.Name(), Path: filePath, IsDir: l.IsDir(), Date: l.ModTime(), Size: l.Size()}
|
tempFile, err := l.Info()
|
||||||
|
if err != nil {
|
||||||
|
logger.Error("when read dir", zap.Error(err))
|
||||||
|
return []model.Path{}, err
|
||||||
|
}
|
||||||
|
temp := model.Path{Name: l.Name(), Path: filePath, IsDir: l.IsDir(), Date: tempFile.ModTime(), Size: tempFile.Size()}
|
||||||
if filePath != link {
|
if filePath != link {
|
||||||
file, _ := os.Stat(link)
|
file, _ := os.Stat(link)
|
||||||
temp.IsDir = file.IsDir()
|
temp.IsDir = file.IsDir()
|
||||||
|
|||||||
Reference in New Issue
Block a user