mirror of
https://github.com/drakkan/sftpgo.git
synced 2026-03-14 14:25:52 +01:00
Merge branch 'main' into bugfix/CARECON-212-Kopiermonster-fix
This commit is contained in:
commit
5d4634b12a
162 changed files with 5118 additions and 1592 deletions
|
|
@ -2,17 +2,17 @@ freebsd_task:
|
|||
name: FreeBSD
|
||||
|
||||
matrix:
|
||||
- name: FreeBSD 14.1
|
||||
- name: FreeBSD 14.2
|
||||
freebsd_instance:
|
||||
image_family: freebsd-14-1
|
||||
image_family: freebsd-14-2
|
||||
|
||||
pkginstall_script:
|
||||
- pkg update -f
|
||||
- pkg install -y go123
|
||||
- pkg install -y go124
|
||||
- pkg install -y git
|
||||
|
||||
setup_script:
|
||||
- ln -s /usr/local/bin/go123 /usr/local/bin/go
|
||||
- ln -s /usr/local/bin/go124 /usr/local/bin/go
|
||||
- pw groupadd sftpgo
|
||||
- pw useradd sftpgo -g sftpgo -w none -m
|
||||
- mkdir /home/sftpgo/sftpgo
|
||||
|
|
|
|||
25
.github/workflows/development.yml
vendored
25
.github/workflows/development.yml
vendored
|
|
@ -15,7 +15,7 @@ jobs:
|
|||
runs-on: ${{ matrix.os }}
|
||||
strategy:
|
||||
matrix:
|
||||
go: ['1.23']
|
||||
go: ['1.24']
|
||||
os: [ubuntu-latest, macos-latest]
|
||||
|
||||
steps:
|
||||
|
|
@ -119,7 +119,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23'
|
||||
go-version: '1.24'
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
|
@ -130,7 +130,7 @@ jobs:
|
|||
$COMMITS_FROM_TAG= ((git rev-list $REV_LIST --count) | Out-String).Trim()
|
||||
$FILE_VERSION = $LATEST_TAG.substring(1) + "." + $COMMITS_FROM_TAG
|
||||
go install github.com/tc-hib/go-winres@latest
|
||||
go-winres simply --arch amd64 --product-version $LATEST_TAG-dev-$GIT_COMMIT --file-version $FILE_VERSION --file-description "SFTPGo server" --product-name SFTPGo --copyright "AGPL-3.0 with additional terms" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go-winres simply --arch amd64 --product-version $LATEST_TAG-dev-$GIT_COMMIT --file-version "$FILE_VERSION" --file-description "SFTPGo server" --product-name SFTPGo --copyright "2019-2025 Nicola Murino" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go build -trimpath -tags nopgxregisterdefaulttypes,disable_grpc_modules -ldflags "-s -w -X github.com/drakkan/sftpgo/v2/internal/version.commit=$GIT_COMMIT -X github.com/drakkan/sftpgo/v2/internal/version.date=$DATE_TIME" -o sftpgo.exe
|
||||
cd tests/eventsearcher
|
||||
go build -trimpath -ldflags "-s -w" -o eventsearcher.exe
|
||||
|
|
@ -142,11 +142,11 @@ jobs:
|
|||
$Env:CGO_ENABLED='0'
|
||||
$Env:GOOS='windows'
|
||||
$Env:GOARCH='arm64'
|
||||
go-winres simply --arch arm64 --product-version $LATEST_TAG-dev-$GIT_COMMIT --file-version $FILE_VERSION --file-description "SFTPGo server" --product-name SFTPGo --copyright "AGPL-3.0 with additional terms" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go-winres simply --arch arm64 --product-version $LATEST_TAG-dev-$GIT_COMMIT --file-version "$FILE_VERSION" --file-description "SFTPGo server" --product-name SFTPGo --copyright "2019-2025 Nicola Murino" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go build -trimpath -tags nopgxregisterdefaulttypes,disable_grpc_modules,nosqlite -ldflags "-s -w -X github.com/drakkan/sftpgo/v2/internal/version.commit=$GIT_COMMIT -X github.com/drakkan/sftpgo/v2/internal/version.date=$DATE_TIME" -o .\arm64\sftpgo.exe
|
||||
mkdir x86
|
||||
$Env:GOARCH='386'
|
||||
go-winres simply --arch 386 --product-version $LATEST_TAG-dev-$GIT_COMMIT --file-version $FILE_VERSION --file-description "SFTPGo server" --product-name SFTPGo --copyright "AGPL-3.0 with additional terms" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go-winres simply --arch 386 --product-version $LATEST_TAG-dev-$GIT_COMMIT --file-version "$FILE_VERSION" --file-description "SFTPGo server" --product-name SFTPGo --copyright "2019-2025 Nicola Murino" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go build -trimpath -tags nopgxregisterdefaulttypes,disable_grpc_modules,nosqlite -ldflags "-s -w -X github.com/drakkan/sftpgo/v2/internal/version.commit=$GIT_COMMIT -X github.com/drakkan/sftpgo/v2/internal/version.date=$DATE_TIME" -o .\x86\sftpgo.exe
|
||||
Remove-Item Env:\CGO_ENABLED
|
||||
Remove-Item Env:\GOOS
|
||||
|
|
@ -154,7 +154,7 @@ jobs:
|
|||
|
||||
- name: Sign binaries
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: azure/trusted-signing-action@v0.5.0
|
||||
uses: azure/trusted-signing-action@v0.5.1
|
||||
with:
|
||||
endpoint: https://eus.codesigning.azure.net/
|
||||
trusted-signing-account-name: nicola
|
||||
|
|
@ -248,7 +248,7 @@ jobs:
|
|||
|
||||
- name: Sign installers
|
||||
if: ${{ github.event_name != 'pull_request' }}
|
||||
uses: azure/trusted-signing-action@v0.5.0
|
||||
uses: azure/trusted-signing-action@v0.5.1
|
||||
with:
|
||||
endpoint: https://eus.codesigning.azure.net/
|
||||
trusted-signing-account-name: nicola
|
||||
|
|
@ -326,7 +326,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23'
|
||||
go-version: '1.24'
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
|
@ -390,7 +390,7 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23'
|
||||
go-version: '1.24'
|
||||
|
||||
- name: Build
|
||||
run: |
|
||||
|
|
@ -529,7 +529,7 @@ jobs:
|
|||
gzip output/man/man1/*
|
||||
cp sftpgo output/
|
||||
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
- uses: uraimo/run-on-arch-action@v3
|
||||
if: ${{ matrix.arch != 'amd64' }}
|
||||
name: Build for ${{ matrix.arch }}
|
||||
id: build
|
||||
|
|
@ -611,10 +611,9 @@ jobs:
|
|||
- name: Set up Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: '1.23'
|
||||
go-version: '1.24'
|
||||
- uses: actions/checkout@v4
|
||||
- name: Run golangci-lint
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
uses: golangci/golangci-lint-action@v7
|
||||
with:
|
||||
args: --timeout=10m
|
||||
version: latest
|
||||
|
|
|
|||
16
.github/workflows/release.yml
vendored
16
.github/workflows/release.yml
vendored
|
|
@ -9,7 +9,7 @@ permissions:
|
|||
contents: write
|
||||
|
||||
env:
|
||||
GO_VERSION: 1.23.3
|
||||
GO_VERSION: 1.24.0
|
||||
|
||||
jobs:
|
||||
prepare-sources-with-deps:
|
||||
|
|
@ -72,17 +72,17 @@ jobs:
|
|||
$DATE_TIME = ([datetime]::Now.ToUniversalTime().toString("yyyy-MM-ddTHH:mm:ssZ")) | Out-String
|
||||
$FILE_VERSION = $Env:SFTPGO_VERSION.substring(1) + ".0"
|
||||
go install github.com/tc-hib/go-winres@latest
|
||||
go-winres simply --arch amd64 --product-version $Env:SFTPGO_VERSION-$GIT_COMMIT --file-version $FILE_VERSION --file-description "SFTPGo server" --product-name SFTPGo --copyright "AGPL-3.0 with additional terms" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go-winres simply --arch amd64 --product-version $Env:SFTPGO_VERSION-$GIT_COMMIT --file-version "$FILE_VERSION" --file-description "SFTPGo server" --product-name SFTPGo --copyright "2019-2025 Nicola Murino" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go build -trimpath -tags nopgxregisterdefaulttypes,disable_grpc_modules -ldflags "-s -w -X github.com/drakkan/sftpgo/v2/internal/version.commit=$GIT_COMMIT -X github.com/drakkan/sftpgo/v2/internal/version.date=$DATE_TIME" -o sftpgo.exe
|
||||
mkdir arm64
|
||||
$Env:CGO_ENABLED='0'
|
||||
$Env:GOOS='windows'
|
||||
$Env:GOARCH='arm64'
|
||||
go-winres simply --arch arm64 --product-version $Env:SFTPGO_VERSION-$GIT_COMMIT --file-version $FILE_VERSION --file-description "SFTPGo server" --product-name SFTPGo --copyright "AGPL-3.0 with additional terms" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go-winres simply --arch arm64 --product-version $Env:SFTPGO_VERSION-$GIT_COMMIT --file-version "$FILE_VERSION" --file-description "SFTPGo server" --product-name SFTPGo --copyright "2019-2025 Nicola Murino" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go build -trimpath -tags nopgxregisterdefaulttypes,disable_grpc_modules,nosqlite -ldflags "-s -w -X github.com/drakkan/sftpgo/v2/internal/version.commit=$GIT_COMMIT -X github.com/drakkan/sftpgo/v2/internal/version.date=$DATE_TIME" -o .\arm64\sftpgo.exe
|
||||
mkdir x86
|
||||
$Env:GOARCH='386'
|
||||
go-winres simply --arch 386 --product-version $Env:SFTPGO_VERSION-$GIT_COMMIT --file-version $FILE_VERSION --file-description "SFTPGo server" --product-name SFTPGo --copyright "AGPL-3.0 with additional terms" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go-winres simply --arch 386 --product-version $Env:SFTPGO_VERSION-$GIT_COMMIT --file-version "$FILE_VERSION" --file-description "SFTPGo server" --product-name SFTPGo --copyright "2019-2025 Nicola Murino" --original-filename sftpgo.exe --icon .\windows-installer\icon.ico
|
||||
go build -trimpath -tags nopgxregisterdefaulttypes,disable_grpc_modules,nosqlite -ldflags "-s -w -X github.com/drakkan/sftpgo/v2/internal/version.commit=$GIT_COMMIT -X github.com/drakkan/sftpgo/v2/internal/version.date=$DATE_TIME" -o .\x86\sftpgo.exe
|
||||
Remove-Item Env:\CGO_ENABLED
|
||||
Remove-Item Env:\GOOS
|
||||
|
|
@ -91,7 +91,7 @@ jobs:
|
|||
SFTPGO_VERSION: ${{ steps.get_version.outputs.VERSION }}
|
||||
|
||||
- name: Sign binaries
|
||||
uses: azure/trusted-signing-action@v0.5.0
|
||||
uses: azure/trusted-signing-action@v0.5.1
|
||||
with:
|
||||
endpoint: https://eus.codesigning.azure.net/
|
||||
trusted-signing-account-name: nicola
|
||||
|
|
@ -153,7 +153,7 @@ jobs:
|
|||
SFTPGO_ISS_VERSION: ${{ steps.get_version.outputs.VERSION }}
|
||||
|
||||
- name: Sign installers
|
||||
uses: azure/trusted-signing-action@v0.5.0
|
||||
uses: azure/trusted-signing-action@v0.5.1
|
||||
with:
|
||||
endpoint: https://eus.codesigning.azure.net/
|
||||
trusted-signing-account-name: nicola
|
||||
|
|
@ -227,7 +227,7 @@ jobs:
|
|||
|
||||
prepare-mac:
|
||||
name: Prepare macOS binaries
|
||||
runs-on: macos-12
|
||||
runs-on: macos-13
|
||||
|
||||
steps:
|
||||
- uses: actions/checkout@v4
|
||||
|
|
@ -379,7 +379,7 @@ jobs:
|
|||
env:
|
||||
SFTPGO_VERSION: ${{ steps.get_version.outputs.SFTPGO_VERSION }}
|
||||
|
||||
- uses: uraimo/run-on-arch-action@v2
|
||||
- uses: uraimo/run-on-arch-action@v3
|
||||
if: ${{ matrix.arch != 'amd64' }}
|
||||
name: Build for ${{ matrix.arch }}
|
||||
id: build
|
||||
|
|
|
|||
|
|
@ -1,52 +1,54 @@
|
|||
version: "2"
|
||||
run:
|
||||
timeout: 10m
|
||||
issues-exit-code: 1
|
||||
tests: true
|
||||
|
||||
|
||||
linters-settings:
|
||||
dupl:
|
||||
threshold: 150
|
||||
errcheck:
|
||||
check-type-assertions: false
|
||||
check-blank: false
|
||||
goconst:
|
||||
min-len: 3
|
||||
min-occurrences: 3
|
||||
gocyclo:
|
||||
min-complexity: 15
|
||||
gofmt:
|
||||
simplify: true
|
||||
goimports:
|
||||
local-prefixes: github.com/drakkan/sftpgo
|
||||
#govet:
|
||||
# report about shadowed variables
|
||||
#check-shadowing: true
|
||||
#enable:
|
||||
# - fieldalignment
|
||||
|
||||
issues:
|
||||
include:
|
||||
- EXC0002
|
||||
- EXC0012
|
||||
- EXC0013
|
||||
- EXC0014
|
||||
- EXC0015
|
||||
|
||||
linters:
|
||||
enable:
|
||||
- goconst
|
||||
- errcheck
|
||||
- gofmt
|
||||
- goimports
|
||||
- revive
|
||||
- unconvert
|
||||
- unparam
|
||||
- bodyclose
|
||||
- dogsled
|
||||
- dupl
|
||||
- goconst
|
||||
- gocyclo
|
||||
- misspell
|
||||
- whitespace
|
||||
- dupl
|
||||
- revive
|
||||
- rowserrcheck
|
||||
- dogsled
|
||||
- govet
|
||||
- unconvert
|
||||
- unparam
|
||||
- whitespace
|
||||
settings:
|
||||
dupl:
|
||||
threshold: 150
|
||||
errcheck:
|
||||
check-type-assertions: false
|
||||
check-blank: false
|
||||
goconst:
|
||||
min-len: 3
|
||||
min-occurrences: 3
|
||||
gocyclo:
|
||||
min-complexity: 15
|
||||
exclusions:
|
||||
generated: lax
|
||||
presets:
|
||||
- common-false-positives
|
||||
- legacy
|
||||
- std-error-handling
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
formatters:
|
||||
enable:
|
||||
- gofmt
|
||||
- goimports
|
||||
settings:
|
||||
gofmt:
|
||||
simplify: true
|
||||
goimports:
|
||||
local-prefixes:
|
||||
- github.com/drakkan/sftpgo
|
||||
exclusions:
|
||||
generated: lax
|
||||
paths:
|
||||
- third_party$
|
||||
- builtin$
|
||||
- examples$
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.23-bookworm AS builder
|
||||
FROM golang:1.24-bookworm AS builder
|
||||
|
||||
ENV GOFLAGS="-mod=readonly"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.23-alpine3.21 AS builder
|
||||
FROM golang:1.24-alpine3.21 AS builder
|
||||
|
||||
ENV GOFLAGS="-mod=readonly"
|
||||
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
FROM golang:1.23-bookworm AS builder
|
||||
FROM golang:1.24-bookworm AS builder
|
||||
|
||||
ENV CGO_ENABLED=0 GOFLAGS="-mod=readonly"
|
||||
|
||||
|
|
|
|||
13
README.md
13
README.md
|
|
@ -1,7 +1,6 @@
|
|||
# SFTPGo
|
||||
|
||||
[](https://github.com/drakkan/sftpgo/workflows/CI/badge.svg?branch=main&event=push)
|
||||
[](https://codecov.io/gh/drakkan/sftpgo/branch/main)
|
||||
[](https://github.com/drakkan/sftpgo/workflows/CI/badge.svg)
|
||||
[](https://www.gnu.org/licenses/agpl-3.0)
|
||||
[](https://github.com/avelino/awesome-go)
|
||||
|
||||
|
|
@ -41,7 +40,9 @@ It is important to understand that you should support SFTPGo and any other Open
|
|||
|
||||
[<img src="./img/7digital.png" alt="7digital logo" width="178" height="56">](https://www.7digital.com/)
|
||||
</br></br>
|
||||
[<img src="./img/vps2day.png" alt="VPS2day logo" width="234" height="56">](https://www.vps2day.com/)
|
||||
[<img src="./img/servinga.png" alt="servinga logo" width="258" height="56">](https://servinga.com/)
|
||||
</br></br>
|
||||
[<img src="./img/reui.png" alt="ReUI logo" width="151" height="56">](https://www.reui.io/)
|
||||
|
||||
## Support
|
||||
|
||||
|
|
@ -76,7 +77,7 @@ We are very grateful to all the people who contributed with ideas and/or pull re
|
|||
|
||||
Thank you to [ysura](https://www.ysura.com/) for granting us stable access to a test AWS S3 account.
|
||||
|
||||
Thank you to [KeenThemes](https://keenthemes.com/) for granting us a custom license to use their amazing [Mega Bundle](https://keenthemes.com/products/templates-mega-bundle) for SFTPGo UI.
|
||||
Thank you to [KeenThemes](https://keenthemes.com/) for granting us a custom license to use their amazing [themes](https://keenthemes.com/bootstrap-templates) for the SFTPGo WebAdmin and WebClient user interfaces, across both the Open Source and Open Core versions.
|
||||
|
||||
Thank you to [Crowdin](https://crowdin.com/) for granting us an Open Source License.
|
||||
|
||||
|
|
@ -86,7 +87,7 @@ Thank you to [Incode](https://www.incode.it/) for helping us to improve the UI/U
|
|||
|
||||
SFTPGo source code is licensed under the GNU AGPL-3.0-only with [additional terms](./NOTICE).
|
||||
|
||||
The [theme](https://keenthemes.com/products/templates-mega-bundle) used in WebAdmin and WebClient user interfaces is proprietary, this means:
|
||||
The [theme](https://keenthemes.com/bootstrap-templates) used in WebAdmin and WebClient user interfaces is proprietary, this means:
|
||||
|
||||
- KeenThemes HTML/CSS/JS components are allowed for use only within the SFTPGo product and restricted to be used in a resealable HTML template that can compete with KeenThemes products anyhow.
|
||||
- The SFTPGo WebAdmin and WebClient user interfaces (HTML, CSS and JS components) based on this theme are allowed for use only within the SFTPGo product and therefore cannot be used in derivative works/products without an explicit grant from the [SFTPGo Team](mailto:support@sftpgo.com).
|
||||
|
|
@ -95,4 +96,4 @@ More information about [compliance](https://sftpgo.com/compliance.html).
|
|||
|
||||
## Copyright
|
||||
|
||||
Copyright (C) 2019 Nicola Murino
|
||||
Copyright (C) 2019 - 2025 Nicola Murino
|
||||
|
|
|
|||
|
|
@ -1,15 +1,15 @@
|
|||
module github.com/drakkan/ldapauth
|
||||
|
||||
go 1.22.2
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
github.com/go-ldap/ldap/v3 v3.4.8
|
||||
golang.org/x/crypto v0.31.0
|
||||
github.com/go-ldap/ldap/v3 v3.4.10
|
||||
golang.org/x/crypto v0.37.0
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,11 +5,11 @@ github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1L
|
|||
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ=
|
||||
github.com/go-ldap/ldap/v3 v3.4.8/go.mod h1:qS3Sjlu76eHfHGpUdWkAXQTw4beih+cHsco2jXlIXrk=
|
||||
github.com/go-ldap/ldap/v3 v3.4.10 h1:ot/iwPOhfpNVgB1o+AVXljizWZ9JTp7YF5oeyONmcJU=
|
||||
github.com/go-ldap/ldap/v3 v3.4.10/go.mod h1:JXh4Uxgi40P6E9rdsYqpUtbW46D9UTjJ9QSwGRznplY=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
|
||||
|
|
@ -43,12 +43,17 @@ github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5t
|
|||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
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/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
|
||||
|
|
@ -56,12 +61,18 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
|||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.22.0 h1:9sGLhx7iRIHEiX0oAJ3MRZMUCElJgy7Br1nO+AMN3Tc=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
|
|
@ -69,28 +80,38 @@ golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBc
|
|||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
|||
|
|
@ -1,43 +1,38 @@
|
|||
module github.com/drakkan/sftpgo/ldapauthserver
|
||||
|
||||
go 1.22.2
|
||||
go 1.23.0
|
||||
|
||||
require (
|
||||
github.com/go-chi/chi/v5 v5.1.0
|
||||
github.com/go-chi/chi/v5 v5.2.1
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/go-ldap/ldap/v3 v3.4.8
|
||||
github.com/go-ldap/ldap/v3 v3.4.10
|
||||
github.com/nathanaelle/password/v2 v2.0.1
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/viper v1.19.0
|
||||
golang.org/x/crypto v0.31.0
|
||||
github.com/rs/zerolog v1.34.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/viper v1.20.1
|
||||
golang.org/x/crypto v0.37.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
)
|
||||
|
||||
require (
|
||||
github.com/Azure/go-ntlmssp v0.0.0-20221128193559-754e69321358 // indirect
|
||||
github.com/ajg/form v1.5.1 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/google/uuid v1.6.0 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/magiconair/properties v1.8.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/sagikazarmark/locafero v0.9.0 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/afero v1.11.0 // indirect
|
||||
github.com/spf13/cast v1.7.0 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/spf13/afero v1.14.0 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/subosito/gotenv v1.6.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 // indirect
|
||||
golang.org/x/sys v0.28.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
golang.org/x/sys v0.32.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
|
|
|||
|
|
@ -5,24 +5,24 @@ github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY
|
|||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa h1:LHTHcTQiSGT7VVbI0o4wBRNQIgn917usHWOd6VAffYI=
|
||||
github.com/alexbrainman/sspi v0.0.0-20231016080023-1a75b4708caa/go.mod h1:cEWa1LVoE5KvSD9ONXsZrj0z6KqySlCCNKHlLzbqAt4=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
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/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.5/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7 h1:DTX+lbVTWaTw1hQ+PbZPlnDZPEIs0SS/GCZAl535dDk=
|
||||
github.com/go-asn1-ber/asn1-ber v1.5.7/go.mod h1:hEBeB/ic+5LoWskz+yKT7vGhhPYkProFKoKdwZRWMe0=
|
||||
github.com/go-chi/chi/v5 v5.1.0 h1:acVI1TYaD+hhedDJ3r54HyA6sExp3HfXq7QWEEY/xMw=
|
||||
github.com/go-chi/chi/v5 v5.1.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
|
||||
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||
github.com/go-ldap/ldap/v3 v3.4.8 h1:loKJyspcRezt2Q3ZRMq2p/0v8iOurlmeXDPw6fikSvQ=
|
||||
github.com/go-ldap/ldap/v3 v3.4.8/go.mod h1:qS3Sjlu76eHfHGpUdWkAXQTw4beih+cHsco2jXlIXrk=
|
||||
github.com/go-ldap/ldap/v3 v3.4.10 h1:ot/iwPOhfpNVgB1o+AVXljizWZ9JTp7YF5oeyONmcJU=
|
||||
github.com/go-ldap/ldap/v3 v3.4.10/go.mod h1:JXh4Uxgi40P6E9rdsYqpUtbW46D9UTjJ9QSwGRznplY=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
|
|
@ -33,8 +33,6 @@ github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/z
|
|||
github.com/hashicorp/go-uuid v1.0.2/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/go-uuid v1.0.3 h1:2gKiV6YVmrJ1i2CKKa9obLvRieoRGviZFL26PcT/Co8=
|
||||
github.com/hashicorp/go-uuid v1.0.3/go.mod h1:6SBZvOh/SIDV7/2o3Jml5SYk/TvGqwFJ/bN7x4byOro=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
github.com/inconshreveable/mousetrap v1.1.0/go.mod h1:vpF70FUmC8bwa3OWnCshd2FqLfsEA9PFc4w1p2J65bw=
|
||||
github.com/jcmturner/aescts/v2 v2.0.0 h1:9YKLH6ey7H4eDBXW8khjYslgyqG2xZikXP0EQFKrle8=
|
||||
|
|
@ -53,46 +51,40 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
|||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
|
||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
|
||||
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
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.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/nathanaelle/password/v2 v2.0.1 h1:ItoCTdsuIWzilYmllQPa3DR3YoCXcpfxScWLqr8Ii2s=
|
||||
github.com/nathanaelle/password/v2 v2.0.1/go.mod h1:eaoT+ICQEPNtikBRIAatN8ThWwMhVG+r1jTw60BvPJk=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
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/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 h1:Jamvg5psRIccs7FGNTlIRMkT8wgtp5eCXdBlqhYGL6U=
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
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/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
|
||||
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k=
|
||||
github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
|
||||
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
|
||||
github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
|
||||
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
|
|
@ -100,8 +92,8 @@ github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81P
|
|||
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.1/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
|
||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
|
||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
|
||||
github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
|
|
@ -111,14 +103,17 @@ golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACk
|
|||
golang.org/x/crypto v0.0.0-20200311171314-f7b00557c8c4/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
|
||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
|
||||
golang.org/x/crypto v0.6.0/go.mod h1:OFC/31mSvZgRz0V1QTNCzfAI1aIRzbiufJtkMIlEp58=
|
||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
|
||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
|
||||
golang.org/x/crypto v0.21.0/go.mod h1:0BP7YvVV9gBbVKyeTG0Gyn+gZm94bibOW5BjDEYAOMs=
|
||||
golang.org/x/crypto v0.31.0 h1:ihbySMvVjLAeSH1IbfcRTkD/iNscyz8rGzjF/E5hV6U=
|
||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
|
||||
golang.org/x/crypto v0.31.0/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884 h1:Y/Mj/94zIQQGHVSv1tTtQBDaQaJe62U9bkDZKKyhPCU=
|
||||
golang.org/x/exp v0.0.0-20241210194714-1829a127f884/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||
golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
|
||||
golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
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/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
|
||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
golang.org/x/net v0.0.0-20200114155413-6afb5195e5aa/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
|
||||
|
|
@ -127,13 +122,18 @@ golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug
|
|||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.7.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
|
||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.22.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.23.0 h1:7EYJ93RZ9vYSZAIb2x3lnuvqO5zneoD6IvWjuhfxjTs=
|
||||
golang.org/x/net v0.23.0/go.mod h1:JKghWKKOSdJwpW2GEx0Ja7fmaKnMsbu+MWVZTokSYmg=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/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/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
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-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -146,35 +146,42 @@ golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.18.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0 h1:Fksou7UEQUWlKvIdsqzJmUmCX3cZuD2+P3XyyzwMhlA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.18.0/go.mod h1:ILwASektA3OnRv7amZ1xhE/KTR+u50pbXfZ03+6Nx58=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
|
||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
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.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
|
||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
|
||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15 h1:YR8cESwS4TdDjEe65xsg0ogRM/Nc3DYOhEAlW+xobZo=
|
||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
|||
224
go.mod
224
go.mod
|
|
@ -1,203 +1,205 @@
|
|||
module github.com/drakkan/sftpgo/v2
|
||||
|
||||
go 1.22.7
|
||||
go 1.24.0
|
||||
|
||||
require (
|
||||
cloud.google.com/go/storage v1.49.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0
|
||||
cloud.google.com/go/storage v1.52.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1
|
||||
github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5
|
||||
github.com/alexedwards/argon2id v1.0.0
|
||||
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.7
|
||||
github.com/aws/aws-sdk-go-v2/config v1.28.7
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.48
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.45
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.25.8
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.72.0
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.8
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.3
|
||||
github.com/bmatcuk/doublestar/v4 v4.7.1
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.3.8
|
||||
github.com/coreos/go-oidc/v3 v3.12.0
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.3
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.14
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.73
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.29.0
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.79.2
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.4
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.4.0
|
||||
github.com/coreos/go-oidc/v3 v3.14.1
|
||||
github.com/drakkan/webdav v0.0.0-20241026165615-b8b8f74ae71b
|
||||
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001
|
||||
github.com/fclairamb/ftpserverlib v0.25.0
|
||||
github.com/fclairamb/go-log v0.5.0
|
||||
github.com/go-acme/lego/v4 v4.21.0
|
||||
github.com/go-chi/chi/v5 v5.2.0
|
||||
github.com/go-chi/jwtauth/v5 v5.3.2
|
||||
github.com/go-acme/lego/v4 v4.23.1
|
||||
github.com/go-chi/chi/v5 v5.2.1
|
||||
github.com/go-chi/jwtauth/v5 v5.3.3
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/go-sql-driver/mysql v1.8.1
|
||||
github.com/go-sql-driver/mysql v1.9.2
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510
|
||||
github.com/google/uuid v1.6.0
|
||||
github.com/hashicorp/go-hclog v1.6.3
|
||||
github.com/hashicorp/go-plugin v1.6.2
|
||||
github.com/hashicorp/go-plugin v1.6.3
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7
|
||||
github.com/jackc/pgx/v5 v5.7.2
|
||||
github.com/jackc/pgx/v5 v5.7.4
|
||||
github.com/jlaffaye/ftp v0.2.0
|
||||
github.com/klauspost/compress v1.17.11
|
||||
github.com/lestrrat-go/jwx/v2 v2.1.3
|
||||
github.com/klauspost/compress v1.18.0
|
||||
github.com/lestrrat-go/jwx/v2 v2.1.6-0.20250420095048-a18531964875
|
||||
github.com/lithammer/shortuuid/v4 v4.2.0
|
||||
github.com/mattn/go-sqlite3 v1.14.24
|
||||
github.com/mattn/go-sqlite3 v1.14.28
|
||||
github.com/mhale/smtpd v0.8.3
|
||||
github.com/minio/sio v0.4.1
|
||||
github.com/otiai10/copy v1.14.0
|
||||
github.com/otiai10/copy v1.14.1
|
||||
github.com/pires/go-proxyproto v0.8.0
|
||||
github.com/pkg/sftp v1.13.7
|
||||
github.com/pkg/sftp v1.13.9
|
||||
github.com/pquerna/otp v1.4.0
|
||||
github.com/prometheus/client_golang v1.20.5
|
||||
github.com/prometheus/client_golang v1.22.0
|
||||
github.com/robfig/cron/v3 v3.0.1
|
||||
github.com/rs/cors v1.11.1
|
||||
github.com/rs/xid v1.6.0
|
||||
github.com/rs/zerolog v1.33.0
|
||||
github.com/rs/zerolog v1.34.0
|
||||
github.com/sftpgo/sdk v0.1.9-0.20241011171103-64fc18a344f9
|
||||
github.com/shirou/gopsutil/v3 v3.24.5
|
||||
github.com/spf13/afero v1.11.0
|
||||
github.com/spf13/cobra v1.8.1
|
||||
github.com/spf13/viper v1.19.0
|
||||
github.com/spf13/afero v1.14.0
|
||||
github.com/spf13/cobra v1.9.1
|
||||
github.com/spf13/viper v1.20.1
|
||||
github.com/stretchr/testify v1.10.0
|
||||
github.com/studio-b12/gowebdav v0.10.0
|
||||
github.com/subosito/gotenv v1.6.0
|
||||
github.com/unrolled/secure v1.17.0
|
||||
github.com/wagslane/go-password-validator v0.3.0
|
||||
github.com/wneessen/go-mail v0.5.2
|
||||
github.com/wneessen/go-mail v0.6.2
|
||||
github.com/yl2chen/cidranger v1.0.3-0.20210928021809-d1cb2c52f37a
|
||||
go.etcd.io/bbolt v1.3.11
|
||||
go.etcd.io/bbolt v1.4.0
|
||||
go.uber.org/automaxprocs v1.6.0
|
||||
gocloud.dev v0.40.0
|
||||
golang.org/x/crypto v0.31.0
|
||||
golang.org/x/net v0.33.0
|
||||
golang.org/x/oauth2 v0.25.0
|
||||
golang.org/x/sys v0.29.0
|
||||
golang.org/x/term v0.27.0
|
||||
golang.org/x/time v0.9.0
|
||||
google.golang.org/api v0.214.0
|
||||
gocloud.dev v0.41.0
|
||||
golang.org/x/crypto v0.37.0
|
||||
golang.org/x/net v0.39.0
|
||||
golang.org/x/oauth2 v0.29.0
|
||||
golang.org/x/sys v0.32.0
|
||||
golang.org/x/term v0.31.0
|
||||
golang.org/x/time v0.11.0
|
||||
google.golang.org/api v0.230.0
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1
|
||||
)
|
||||
|
||||
require (
|
||||
cel.dev/expr v0.19.1 // indirect
|
||||
cloud.google.com/go v0.118.0 // indirect
|
||||
cloud.google.com/go/auth v0.13.0 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.6 // indirect
|
||||
cel.dev/expr v0.23.1 // indirect
|
||||
cloud.google.com/go v0.120.1 // indirect
|
||||
cloud.google.com/go/auth v0.16.1 // indirect
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 // indirect
|
||||
cloud.google.com/go/compute/metadata v0.6.0 // indirect
|
||||
cloud.google.com/go/iam v1.3.1 // indirect
|
||||
cloud.google.com/go/monitoring v1.22.1 // indirect
|
||||
cloud.google.com/go/iam v1.5.2 // indirect
|
||||
cloud.google.com/go/monitoring v1.24.2 // indirect
|
||||
filippo.io/edwards25519 v1.1.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 // indirect
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 // indirect
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 // indirect
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 // indirect
|
||||
github.com/ajg/form v1.5.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.26 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.7 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.8 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.7 // indirect
|
||||
github.com/aws/smithy-go v1.22.1 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.0 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 // indirect
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 // indirect
|
||||
github.com/aws/smithy-go v1.22.3 // indirect
|
||||
github.com/beorn7/perks v1.0.1 // indirect
|
||||
github.com/boombuler/barcode v1.0.2 // indirect
|
||||
github.com/cenkalti/backoff/v4 v4.3.0 // indirect
|
||||
github.com/cespare/xxhash/v2 v2.3.0 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 // indirect
|
||||
github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f // indirect
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 // indirect
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 // indirect
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 // indirect
|
||||
github.com/envoyproxy/go-control-plane v0.13.3 // indirect
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.32.2 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.1.0 // indirect
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 // indirect
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.32.4 // indirect
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1 // indirect
|
||||
github.com/fatih/color v1.18.0 // indirect
|
||||
github.com/felixge/httpsnoop v1.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.8.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.0.4 // indirect
|
||||
github.com/fsnotify/fsnotify v1.9.0 // indirect
|
||||
github.com/go-jose/go-jose/v4 v4.1.1-0.20250421195336-4ff65aefe8a5 // indirect
|
||||
github.com/go-logr/logr v1.4.2 // indirect
|
||||
github.com/go-logr/stdr v1.2.2 // indirect
|
||||
github.com/go-ole/go-ole v1.3.0 // indirect
|
||||
github.com/goccy/go-json v0.10.4 // indirect
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
|
||||
github.com/goccy/go-json v0.10.5 // indirect
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 // indirect
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 // indirect
|
||||
github.com/golang/protobuf v1.5.4 // indirect
|
||||
github.com/google/s2a-go v0.1.8 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 // indirect
|
||||
github.com/google/s2a-go v0.1.9 // indirect
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 // indirect
|
||||
github.com/googleapis/gax-go/v2 v2.14.1 // indirect
|
||||
github.com/hashicorp/errwrap v1.1.0 // indirect
|
||||
github.com/hashicorp/go-cleanhttp v0.5.2 // indirect
|
||||
github.com/hashicorp/go-multierror v1.1.1 // indirect
|
||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||
github.com/hashicorp/yamux v0.1.2 // indirect
|
||||
github.com/inconshreveable/mousetrap v1.1.0 // indirect
|
||||
github.com/jackc/pgpassfile v1.0.0 // indirect
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
|
||||
github.com/jackc/puddle/v2 v2.2.2 // indirect
|
||||
github.com/kr/fs v0.1.0 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.2 // indirect
|
||||
github.com/kylelemons/godebug v1.1.0 // indirect
|
||||
github.com/lestrrat-go/blackmagic v1.0.3 // indirect
|
||||
github.com/lestrrat-go/httpcc v1.0.1 // indirect
|
||||
github.com/lestrrat-go/httprc v1.0.6 // indirect
|
||||
github.com/lestrrat-go/iter v1.0.2 // indirect
|
||||
github.com/lestrrat-go/option v1.0.1 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 // indirect
|
||||
github.com/magiconair/properties v1.8.9 // indirect
|
||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 // indirect
|
||||
github.com/mattn/go-colorable v0.1.14 // indirect
|
||||
github.com/mattn/go-isatty v0.0.20 // indirect
|
||||
github.com/miekg/dns v1.1.62 // indirect
|
||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||
github.com/miekg/dns v1.1.65 // indirect
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 // indirect
|
||||
github.com/oklog/run v1.1.0 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 // indirect
|
||||
github.com/otiai10/mint v1.6.3 // indirect
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 // indirect
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c // indirect
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 // indirect
|
||||
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||
github.com/power-devops/perfstat v0.0.0-20240221224432-82ca36839d55 // indirect
|
||||
github.com/prometheus/client_model v0.6.1 // indirect
|
||||
github.com/prometheus/common v0.61.0 // indirect
|
||||
github.com/prometheus/procfs v0.15.1 // indirect
|
||||
github.com/prometheus/client_model v0.6.2 // indirect
|
||||
github.com/prometheus/common v0.63.0 // indirect
|
||||
github.com/prometheus/procfs v0.16.1 // indirect
|
||||
github.com/russross/blackfriday/v2 v2.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.6.0 // indirect
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||
github.com/sagikazarmark/locafero v0.9.0 // indirect
|
||||
github.com/segmentio/asm v1.2.0 // indirect
|
||||
github.com/shoenig/go-m1cpu v0.1.6 // indirect
|
||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||
github.com/spf13/cast v1.7.1 // indirect
|
||||
github.com/spf13/pflag v1.0.5 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.14 // indirect
|
||||
github.com/tklauser/numcpus v0.9.0 // indirect
|
||||
github.com/spf13/pflag v1.0.6 // indirect
|
||||
github.com/spiffe/go-spiffe/v2 v2.5.0 // indirect
|
||||
github.com/tklauser/go-sysconf v0.3.15 // indirect
|
||||
github.com/tklauser/numcpus v0.10.0 // indirect
|
||||
github.com/yusufpapurcu/wmi v1.2.4 // indirect
|
||||
github.com/zeebo/errs v1.4.0 // indirect
|
||||
go.opencensus.io v0.24.0 // indirect
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 // indirect
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.33.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 // indirect
|
||||
go.opentelemetry.io/otel v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.33.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.33.0 // indirect
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.35.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 // indirect
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 // indirect
|
||||
go.opentelemetry.io/otel v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/metric v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 // indirect
|
||||
go.opentelemetry.io/otel/trace v1.35.0 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329 // indirect
|
||||
golang.org/x/mod v0.22.0 // indirect
|
||||
golang.org/x/sync v0.10.0 // indirect
|
||||
golang.org/x/text v0.21.0 // indirect
|
||||
golang.org/x/tools v0.28.0 // indirect
|
||||
golang.org/x/mod v0.24.0 // indirect
|
||||
golang.org/x/sync v0.13.0 // indirect
|
||||
golang.org/x/text v0.24.0 // indirect
|
||||
golang.org/x/tools v0.32.0 // indirect
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da // indirect
|
||||
google.golang.org/genproto v0.0.0-20250102185135-69823020774d // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d // indirect
|
||||
google.golang.org/grpc v1.69.2 // indirect
|
||||
google.golang.org/protobuf v1.36.1 // indirect
|
||||
gopkg.in/ini.v1 v1.67.0 // indirect
|
||||
google.golang.org/genproto v0.0.0-20250422160041-2d3770c4ea7f // indirect
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f // indirect
|
||||
google.golang.org/grpc v1.72.0 // indirect
|
||||
google.golang.org/protobuf v1.36.6 // indirect
|
||||
gopkg.in/yaml.v3 v3.0.1 // indirect
|
||||
)
|
||||
|
||||
replace (
|
||||
github.com/fclairamb/ftpserverlib => github.com/drakkan/ftpserverlib v0.0.0-20240603150004-6a8f643fbf2e
|
||||
github.com/fclairamb/ftpserverlib => github.com/drakkan/ftpserverlib v0.0.0-20250204143431-e069fad14727
|
||||
github.com/jlaffaye/ftp => github.com/drakkan/ftp v0.0.0-20240430173938-7ba8270c8e7f
|
||||
github.com/robfig/cron/v3 => github.com/drakkan/cron/v3 v3.0.0-20230222140221-217a1e4d96c0
|
||||
golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20241215104834-a9cd4736223d
|
||||
golang.org/x/crypto => github.com/drakkan/crypto v0.0.0-20250420150858-04abdc60032d
|
||||
)
|
||||
|
|
|
|||
492
go.sum
492
go.sum
|
|
@ -1,106 +1,110 @@
|
|||
cel.dev/expr v0.19.1 h1:NciYrtDRIR0lNCnH1LFJegdjspNx9fI59O7TWcua/W4=
|
||||
cel.dev/expr v0.19.1/go.mod h1:MrpN08Q+lEBs+bGYdLxxHkZoUSsCp0nSKTs0nTymJgw=
|
||||
cel.dev/expr v0.23.1 h1:K4KOtPCJQjVggkARsjG9RWXP6O4R73aHeJMa/dmCQQg=
|
||||
cel.dev/expr v0.23.1/go.mod h1:hLPLo1W4QUmuYdA72RBX06QTs6MXw941piREPl3Yfiw=
|
||||
cloud.google.com/go v0.26.0/go.mod h1:aQUYkXzVsufM+DwF1aE+0xfcU+56JwCaLick0ClmMTw=
|
||||
cloud.google.com/go v0.118.0 h1:tvZe1mgqRxpiVa3XlIGMiPcEUbP1gNXELgD4y/IXmeQ=
|
||||
cloud.google.com/go v0.118.0/go.mod h1:zIt2pkedt/mo+DQjcT4/L3NDxzHPR29j5HcclNH+9PM=
|
||||
cloud.google.com/go/auth v0.13.0 h1:8Fu8TZy167JkW8Tj3q7dIkr2v4cndv41ouecJx0PAHs=
|
||||
cloud.google.com/go/auth v0.13.0/go.mod h1:COOjD9gwfKNKz+IIduatIhYJQIc0mG3H102r/EMxX6Q=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.6 h1:V6a6XDu2lTwPZWOawrAa9HUK+DB2zfJyTuciBG5hFkU=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.6/go.mod h1:AlmsELtlEBnaNTL7jCj8VQFLy6mbZv0s4Q7NGBeQ5E8=
|
||||
cloud.google.com/go v0.120.1 h1:Z+5V7yd383+9617XDCyszmK5E4wJRJL+tquMfDj9hLM=
|
||||
cloud.google.com/go v0.120.1/go.mod h1:56Vs7sf/i2jYM6ZL9NYlC82r04PThNcPS5YgFmb0rp8=
|
||||
cloud.google.com/go/auth v0.16.1 h1:XrXauHMd30LhQYVRHLGvJiYeczweKQXZxsTbV9TiguU=
|
||||
cloud.google.com/go/auth v0.16.1/go.mod h1:1howDHJ5IETh/LwYs3ZxvlkXF48aSqqJUM+5o02dNOI=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8 h1:keo8NaayQZ6wimpNSmW5OPc283g65QNIiLpZnkHRbnc=
|
||||
cloud.google.com/go/auth/oauth2adapt v0.2.8/go.mod h1:XQ9y31RkqZCcwJWNSx2Xvric3RrU88hAYYbjDWYDL+c=
|
||||
cloud.google.com/go/compute/metadata v0.6.0 h1:A6hENjEsCDtC1k8byVsgwvVcioamEHvZ4j01OwKxG9I=
|
||||
cloud.google.com/go/compute/metadata v0.6.0/go.mod h1:FjyFAW1MW0C203CEOMDTu3Dk1FlqW3Rga40jzHL4hfg=
|
||||
cloud.google.com/go/iam v1.3.1 h1:KFf8SaT71yYq+sQtRISn90Gyhyf4X8RGgeAVC8XGf3E=
|
||||
cloud.google.com/go/iam v1.3.1/go.mod h1:3wMtuyT4NcbnYNPLMBzYRFiEfjKfJlLVLrisE7bwm34=
|
||||
cloud.google.com/go/kms v1.20.3 h1:a61yIN5LN8ozWxOC6tjUx5V5SEzfkS+b69kYMQfzGzE=
|
||||
cloud.google.com/go/kms v1.20.3/go.mod h1:YvX+xhp2E2Sc3vol5IcRlBhH14Ecl3kegUY/DtH7EWQ=
|
||||
cloud.google.com/go/logging v1.12.0 h1:ex1igYcGFd4S/RZWOCU51StlIEuey5bjqwH9ZYjHibk=
|
||||
cloud.google.com/go/logging v1.12.0/go.mod h1:wwYBt5HlYP1InnrtYI0wtwttpVU1rifnMT7RejksUAM=
|
||||
cloud.google.com/go/longrunning v0.6.3 h1:A2q2vuyXysRcwzqDpMMLSI6mb6o39miS52UEG/Rd2ng=
|
||||
cloud.google.com/go/longrunning v0.6.3/go.mod h1:k/vIs83RN4bE3YCswdXC5PFfWVILjm3hpEUlSko4PiI=
|
||||
cloud.google.com/go/monitoring v1.22.1 h1:KQbnAC4IAH+5x3iWuPZT5iN9VXqKMzzOgqcYB6fqPDE=
|
||||
cloud.google.com/go/monitoring v1.22.1/go.mod h1:AuZZXAoN0WWWfsSvET1Cpc4/1D8LXq8KRDU87fMS6XY=
|
||||
cloud.google.com/go/storage v1.49.0 h1:zenOPBOWHCnojRd9aJZAyQXBYqkJkdQS42dxL55CIMw=
|
||||
cloud.google.com/go/storage v1.49.0/go.mod h1:k1eHhhpLvrPjVGfo0mOUPEJ4Y2+a/Hv5PiwehZI9qGU=
|
||||
cloud.google.com/go/trace v1.11.2 h1:4ZmaBdL8Ng/ajrgKqY5jfvzqMXbrDcBsUGXOT9aqTtI=
|
||||
cloud.google.com/go/trace v1.11.2/go.mod h1:bn7OwXd4pd5rFuAnTrzBuoZ4ax2XQeG3qNgYmfCy0Io=
|
||||
cloud.google.com/go/iam v1.5.2 h1:qgFRAGEmd8z6dJ/qyEchAuL9jpswyODjA2lS+w234g8=
|
||||
cloud.google.com/go/iam v1.5.2/go.mod h1:SE1vg0N81zQqLzQEwxL2WI6yhetBdbNQuTvIKCSkUHE=
|
||||
cloud.google.com/go/kms v1.21.2 h1:c/PRUSMNQ8zXrc1sdAUnsenWWaNXN+PzTXfXOcSFdoE=
|
||||
cloud.google.com/go/kms v1.21.2/go.mod h1:8wkMtHV/9Z8mLXEXr1GK7xPSBdi6knuLXIhqjuWcI6w=
|
||||
cloud.google.com/go/logging v1.13.0 h1:7j0HgAp0B94o1YRDqiqm26w4q1rDMH7XNRU34lJXHYc=
|
||||
cloud.google.com/go/logging v1.13.0/go.mod h1:36CoKh6KA/M0PbhPKMq6/qety2DCAErbhXT62TuXALA=
|
||||
cloud.google.com/go/longrunning v0.6.7 h1:IGtfDWHhQCgCjwQjV9iiLnUta9LBCo8R9QmAFsS/PrE=
|
||||
cloud.google.com/go/longrunning v0.6.7/go.mod h1:EAFV3IZAKmM56TyiE6VAP3VoTzhZzySwI/YI1s/nRsY=
|
||||
cloud.google.com/go/monitoring v1.24.2 h1:5OTsoJ1dXYIiMiuL+sYscLc9BumrL3CarVLL7dd7lHM=
|
||||
cloud.google.com/go/monitoring v1.24.2/go.mod h1:x7yzPWcgDRnPEv3sI+jJGBkwl5qINf+6qY4eq0I9B4U=
|
||||
cloud.google.com/go/storage v1.52.0 h1:ROpzMW/IwipKtatA69ikxibdzQSiXJrY9f6IgBa9AlA=
|
||||
cloud.google.com/go/storage v1.52.0/go.mod h1:4wrBAbAYUvYkbrf19ahGm4I5kDQhESSqN3CGEkMGvOY=
|
||||
cloud.google.com/go/trace v1.11.6 h1:2O2zjPzqPYAHrn3OKl029qlqG6W8ZdYaOWRyr8NgMT4=
|
||||
cloud.google.com/go/trace v1.11.6/go.mod h1:GA855OeDEBiBMzcckLPE2kDunIpC72N+Pq8WFieFjnI=
|
||||
filippo.io/edwards25519 v1.1.0 h1:FNf4tywRC1HmFuKW5xopWpigGjJKiJSV0Cqo0cJWDaA=
|
||||
filippo.io/edwards25519 v1.1.0/go.mod h1:BxyFTGdWcka3PhytdK4V28tE5sGfRvvvRV7EaN4VDT4=
|
||||
github.com/Azure/azure-sdk-for-go v68.0.0+incompatible h1:fcYLmCpyNYRnvJbPerq7U0hS+6+I79yEDJBqVNcqUzU=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0 h1:JZg6HRh6W6U4OLl6lk7BZ7BLisIzM9dG1R50zUk9C/M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.16.0/go.mod h1:YL1xnZ6QejvQHWJrX/AvhFl4WW4rqHVoKspWNVwFk0M=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0 h1:B/dfvscEQtew9dVuoxqxrUKKv8Ih2f55PydknDamU+g=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.8.0/go.mod h1:fiPSssYvltE08HJchL04dOy+RD4hgrjph0cwGGMntdI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0 h1:ywEEhmNahHBihViHepv3xPBn1663uRv2t2q/ESv9seY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.10.0/go.mod h1:iZDifYGJTIgIIkYRNWPENUnqx6bJ2xnSDFI2tjwZNuY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0 h1:PiSrjRPpkQNjrM8H0WwKMnZUdu1RGMtd/LdGKUrOo+c=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.6.0/go.mod h1:oDrbWx4ewMylP7xHivfgixbfGBT6APAwsSoHRKotnIc=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0 h1:mlmW46Q0B79I+Aj4azKC6xDMFN9a9SyZWESlGWYXbFs=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.5.0/go.mod h1:PXe2h+LKcWTX9afWdZoHyODqR4fBa5boUM/8uJfZ0Jo=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2 h1:XHOnouVk1mxXfQidrMEnLlPk9UMeRtyBTnEFtxkV0kU=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.2.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0 h1:Gt0j3wceWMwPmiazCa8MzMA0MfhmPIz0Qp0FJ6qcM0U=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azcore v1.18.0/go.mod h1:Ot/6aikWnKWi4l9QB7qVSwa8iMphQNqkWALMoNT3rzM=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0 h1:OVoM452qUFBrX+URdH3VpR299ma4kfom0yB0URYky9g=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity v1.9.0/go.mod h1:kUjrAo8bgEwLeZ/CmHqNl3Z/kPm7y6FKfxxK0izYUg4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2 h1:yz1bePFlP5Vws5+8ez6T3HWXPmwOK7Yvq8QxDBD3SKY=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/azidentity/cache v0.3.2/go.mod h1:Pa9ZNPuoNu/GztvBSKk9J1cDJW6vk/n0zLtV4mgd8N8=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1 h1:FPKJS1T+clwv+OLGt13a8UjqeRuh0O4SJ3lUriThc+4=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/internal v1.11.1/go.mod h1:j2chePtV91HrC22tGoRX3sGY42uF13WzmmV80/OdVAA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0 h1:LR0kAX9ykz8G4YgLCaRDVJ3+n43R8MneB5dTy2konZo=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/resourcemanager/storage/armstorage v1.8.0/go.mod h1:DWAciXemNf++PQJLeXUB4HHH5OpsAh12HZnu2wXE1jA=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1 h1:lhZdRq7TIx0GJQvSyX2Si406vrYsov2FXGp/RnSEtcs=
|
||||
github.com/Azure/azure-sdk-for-go/sdk/storage/azblob v1.6.1/go.mod h1:8cl44BDmi+effbARHMQjgOKA2AYvcohNm7KEt42mSV8=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1 h1:WJTmL004Abzc5wDB5VtZG2PJk5ndYDgVacGqfirKxjM=
|
||||
github.com/AzureAD/microsoft-authentication-extensions-for-go/cache v0.1.1/go.mod h1:tCcJZ0uHAmvjsVYzEFivsRTN00oz5BEsRgQHu5JZ9WE=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2 h1:oygO0locgZJe7PpYPXT5A29ZkwJaPqcva7BVeemZOZs=
|
||||
github.com/AzureAD/microsoft-authentication-library-for-go v1.4.2/go.mod h1:wP83P5OoQ5p6ip3ScPr0BAq0BvuPAvacpEuSzyouqAI=
|
||||
github.com/BurntSushi/toml v0.3.1/go.mod h1:xHWCNGjB5oqiDr8zfno3MHue2Ht5sIBksp03qcyfWMU=
|
||||
github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5 h1:IEjq88XO4PuBDcvmjQJcQGg+w+UaafSy8G5Kcb5tBhI=
|
||||
github.com/GehirnInc/crypt v0.0.0-20230320061759-8cc1b52080c5/go.mod h1:exZ0C/1emQJAw5tHOaUDyY1ycttqBAPcxuzf7QbY6ec=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0 h1:3c8yed4lgqTt+oTQ+JNMDo+F4xprBf+O/il4ZC0nRLw=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.25.0/go.mod h1:obipzmGjfSjam60XLwGfqUkJsfiheAl+TUjG+4yzyPM=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0 h1:o90wcURuxekmXrtxmYWTyNla0+ZEHhud6DI1ZTxd1vI=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.49.0/go.mod h1:6fTWu4m3jocfUZLYF5KsZC1TUfRvEjs7lM4crme/irw=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0 h1:jJKWl98inONJAr/IZrdFQUWcwUO95DLY1XMD1ZIut+g=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.49.0/go.mod h1:l2fIqmwB+FKSfvn3bAD/0i+AXAxhIZjTK2svT/mgUXs=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0 h1:GYUJLfvd++4DMuMhCFLgLXvFwofIxh/qOwoGuS/LTew=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.49.0/go.mod h1:wRbFgBQUVm1YXrvWKofAEmq9HNJTDphbAaJSSX01KUI=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0 h1:ErKg/3iS1AKcTkf3yixlZ54f9U1rljCkQyEXWUnIUxc=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/detectors/gcp v1.27.0/go.mod h1:yAZHSGnqScoU556rBOVkwLze6WP5N+U11RHuWaGVxwY=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0 h1:fYE9p3esPxA/C0rQ0AHhP0drtPXDRhaWiwg1DPqO7IU=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/exporter/metric v0.51.0/go.mod h1:BnBReJLvVYx2CS/UHOgVz2BXKXD9wsQPxZug20nZhd0=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.51.0 h1:OqVGm6Ei3x5+yZmSJG1Mh2NwHvpVmZ08CB5qJhT9Nuk=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/cloudmock v0.51.0/go.mod h1:SZiPHWGOOk3bl8tkevxkoiwPgsIl6CwrWcbwjfHZpdM=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0 h1:6/0iUd0xrnX7qt+mLNRwg5c0PGv8wpE8K90ryANQwMI=
|
||||
github.com/GoogleCloudPlatform/opentelemetry-operations-go/internal/resourcemapping v0.51.0/go.mod h1:otE2jQekW/PqXk1Awf5lmfokJx4uwuqcj1ab5SpGeW0=
|
||||
github.com/ajg/form v1.5.1 h1:t9c7v8JUKu/XxOGBU0yjNpaMloxGEJhUkqFRq0ibGeU=
|
||||
github.com/ajg/form v1.5.1/go.mod h1:uL1WgH+h2mgNtvBq0339dVnzXdBETtL2LeUXaIv25UY=
|
||||
github.com/alexedwards/argon2id v1.0.0 h1:wJzDx66hqWX7siL/SRUmgz3F8YMrd/nfX/xHHcQQP0w=
|
||||
github.com/alexedwards/argon2id v1.0.0/go.mod h1:tYKkqIjzXvZdzPvADMWOEZ+l6+BD6CtBXMj5fnJppiw=
|
||||
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964 h1:I9YN9WMo3SUh7p/4wKeNvD/IQla3U3SUa61U7ul+xM4=
|
||||
github.com/amoghe/go-crypt v0.0.0-20220222110647-20eada5f5964/go.mod h1:eFiR01PwTcpbzXtdMces7zxg6utvFM5puiWHpWB8D/k=
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.7 h1:ky5o35oENWi0JYWUZkB7WYvVPP+bcRF5/Iq7JWSb5Rw=
|
||||
github.com/aws/aws-sdk-go-v2 v1.32.7/go.mod h1:P5WJBrYqqbWVaOxgH0X/FYYD47/nooaPOZPlQdmiN2U=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7 h1:lL7IfaFzngfx0ZwUGOZdsFFnQ5uLvR0hWqqhyE7Q9M8=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.7/go.mod h1:QraP0UcVlQJsmHfioCrveWOC1nbiWUl3ej08h4mXWoc=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.28.7 h1:GduUnoTXlhkgnxTD93g1nv4tVPILbdNQOzav+Wpg7AE=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.28.7/go.mod h1:vZGX6GVkIE8uECSUHB6MWAUsd4ZcG2Yq/dMa4refR3M=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.48 h1:IYdLD1qTJ0zanRavulofmqut4afs45mOWEI+MzZtTfQ=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.48/go.mod h1:tOscxHN3CGmuX9idQ3+qbkzrjVIx32lqDSU1/0d/qXs=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22 h1:kqOrpojG71DxJm/KDPO+Z/y1phm1JlC8/iT+5XRmAn8=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.22/go.mod h1:NtSFajXVVL8TA2QNngagVZmUtXciyrHOt7xgz4faS/M=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.45 h1:ZxB8WFVYwolhDZxuZXoesHkl+L9cXLWy0K/G0QkNATc=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.45/go.mod h1:1krrbyoFFDqaNldmltPTP+mK3sAXLHPoaFtISOw2Hkk=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26 h1:I/5wmGMffY4happ8NOCuIUEWGUvvFp5NSeQcXl9RHcI=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.26/go.mod h1:FR8f4turZtNy6baO0KJ5FJUmXH/cSkI9fOngs0yl6mA=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26 h1:zXFLuEuMMUOvEARXFUVJdfqZ4bvvSgdGRq/ATcrQxzM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.26/go.mod h1:3o2Wpy0bogG1kyOPrgkXA8pgIfEEv0+m19O9D5+W8y8=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1 h1:VaRN3TlFdd6KxX1x3ILT5ynH6HvKgqdiXoTxAF4HQcQ=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.1/go.mod h1:FbtygfRFze9usAadmnGJNc8KsP346kEe+y2/oyhGAGc=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.26 h1:GeNJsIFHB+WW5ap2Tec4K6dzcVTsRbsT1Lra46Hv9ME=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.26/go.mod h1:zfgMpwHDXX2WGoG84xG2H+ZlPTkJUU4YUvx2svLQYWo=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1 h1:iXtILhvDxB6kPvEXgsDhGaZCSC6LQET5ZHSdJozeI0Y=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.1/go.mod h1:9nu0fVANtYiAePIBh2/pFUSwtJ402hLnp854CNoDOeE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.7 h1:tB4tNw83KcajNAzaIMhkhVI2Nt8fAZd5A5ro113FEMY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.4.7/go.mod h1:lvpyBGkZ3tZ9iSsUIcC2EWp+0ywa7aK3BLT+FwZi+mQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.7 h1:8eUsivBQzZHqe/3FE+cqwfH+0p5Jo8PFM/QYQSmeZ+M=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.7/go.mod h1:kLPQvGUmxn/fqiCrDeohwG33bq2pQpGeY62yRO6Nrh0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.7 h1:Hi0KGbrnr57bEHWM0bJ1QcBzxLrL/k2DHvGYhb8+W1w=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.7/go.mod h1:wKNgWgExdjjrm4qvfbTorkvocEstaoDl4WCvGfeCy9c=
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.25.8 h1:A9pJ60b8AKwlXiSbznKBcDaBTA7jIaI6gHSDqQeAZOg=
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.25.8/go.mod h1:/aDbp2jKTGdpJwFHuwQeypaIPlCjkxMqDVUB+7GizdU=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.72.0 h1:SAfh4pNx5LuTafKKWR02Y+hL3A+3TX8cTKG1OIAJaBk=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.72.0/go.mod h1:r+xl5yzMk9083rMR+sJ5TYj9Tihvf/l1oxzZXDgGj2Q=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.8 h1:WT3EPriVEpHE2jeNqHqj7l43JCIWPoZjNNRluZ7agII=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.34.8/go.mod h1:By/yiMzR0yfhPaqRWE3GrT9B/Z6871z1GfWGc+vf4Y8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.8 h1:CvuUmnXI7ebaUAhbJcDy9YQx8wHR69eZ9I7q5hszt/g=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.24.8/go.mod h1:XDeGv1opzwm8ubxddF0cgqkZWsyOtw4lr6dxwmb6YQg=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.7 h1:F2rBfNAL5UyswqoeWv9zs74N/NanhK16ydHW1pahX6E=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.28.7/go.mod h1:JfyQ0g2JG8+Krq0EuZNnRwX0mU0HrwY/tG6JNfcqh4k=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.3 h1:Xgv/hyNgvLda/M9l9qxXc4UFSgppnRczLxlMs5Ae/QY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.3/go.mod h1:5Gn+d+VaaRgsjewpMvGazt0WfcFO+Md4wLOuBfGR9Bc=
|
||||
github.com/aws/smithy-go v1.22.1 h1:/HPHZQ0g7f4eUeK6HKglFz8uwVfZKgoI25rb/J+dnro=
|
||||
github.com/aws/smithy-go v1.22.1/go.mod h1:irrKGvNn1InZwb2d7fkIRNucdfwR8R+Ts3wxYa/cJHg=
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.3 h1:mJoei2CxPutQVxaATCzDUjcZEjVRdpsiiXi2o38yqWM=
|
||||
github.com/aws/aws-sdk-go-v2 v1.36.3/go.mod h1:LLXuLpgzEbD766Z5ECcRmi8AzSwfZItDtmABVkRLGzg=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10 h1:zAybnyUQXIZ5mok5Jqwlf58/TFE7uvd3IAsa1aF9cXs=
|
||||
github.com/aws/aws-sdk-go-v2/aws/protocol/eventstream v1.6.10/go.mod h1:qqvMj6gHLR/EXWZw4ZbqlPbQUyenf4h82UQUlKc+l14=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.14 h1:f+eEi/2cKCg9pqKBoAIwRGzVb70MRKqWX4dg1BDcSJM=
|
||||
github.com/aws/aws-sdk-go-v2/config v1.29.14/go.mod h1:wVPHWcIFv3WO89w0rE10gzf17ZYy+UVS1Geq8Iei34g=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67 h1:9KxtdcIA/5xPNQyZRgUSpYOE6j9Bc4+D7nZua0KGYOM=
|
||||
github.com/aws/aws-sdk-go-v2/credentials v1.17.67/go.mod h1:p3C44m+cfnbv763s52gCqrjaqyPikj9Sg47kUVaNZQQ=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30 h1:x793wxmUWVDhshP8WW2mlnXuFrO4cOd3HLBroh1paFw=
|
||||
github.com/aws/aws-sdk-go-v2/feature/ec2/imds v1.16.30/go.mod h1:Jpne2tDnYiFascUEs2AWHJL9Yp7A5ZVy3TNyxaAjD6M=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.73 h1:I91eIdOJMVK9oNiH2jvhp/AxMW+Gff8Rb5VjVHMhcJU=
|
||||
github.com/aws/aws-sdk-go-v2/feature/s3/manager v1.17.73/go.mod h1:vq7/m7dahFXcdzWVOvvjasDI9RcsD3RsTfHmDundJYg=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34 h1:ZK5jHhnrioRkUNOc+hOgQKlUL5JeC3S6JgLxtQ+Rm0Q=
|
||||
github.com/aws/aws-sdk-go-v2/internal/configsources v1.3.34/go.mod h1:p4VfIceZokChbA9FzMbRGz5OV+lekcVtHlPKEO0gSZY=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34 h1:SZwFm17ZUNNg5Np0ioo/gq8Mn6u9w19Mri8DnJ15Jf0=
|
||||
github.com/aws/aws-sdk-go-v2/internal/endpoints/v2 v2.6.34/go.mod h1:dFZsC0BLo346mvKQLWmoJxT+Sjp+qcVR1tRVHQGOH9Q=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3 h1:bIqFDwgGXXN1Kpp99pDOdKMTTb5d2KyU5X/BZxjOkRo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/ini v1.8.3/go.mod h1:H5O/EsxDWyU+LP/V8i5sm8cxoZgc2fdNR9bxlOFrQTo=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34 h1:ZNTqv4nIdE/DiBfUUfXcLZ/Spcuz+RjeziUtNJackkM=
|
||||
github.com/aws/aws-sdk-go-v2/internal/v4a v1.3.34/go.mod h1:zf7Vcd1ViW7cPqYWEHLHJkS50X0JS2IKz9Cgaj6ugrs=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3 h1:eAh2A4b5IzM/lum78bZ590jy36+d/aFLgKF/4Vd1xPE=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/accept-encoding v1.12.3/go.mod h1:0yKJC/kb8sAnmlYa6Zs3QVYqaC8ug2AbnNChv5Ox3uA=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.0 h1:lguz0bmOoGzozP9XfRJR1QIayEYo+2vP/No3OfLF0pU=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/checksum v1.7.0/go.mod h1:iu6FSzgt+M2/x3Dk8zhycdIcHjEFb36IS8HVUVFoMg0=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15 h1:dM9/92u2F1JbDaGooxTq18wmmFzbJRfXfVfy96/1CXM=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/presigned-url v1.12.15/go.mod h1:SwFBy2vjtA0vZbjjaFtfN045boopadnoVPhu4Fv66vY=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15 h1:moLQUoVq91LiqT1nbvzDukyqAlCv89ZmwaHw/ZFlFZg=
|
||||
github.com/aws/aws-sdk-go-v2/service/internal/s3shared v1.18.15/go.mod h1:ZH34PJUc8ApjBIfgQCFvkWcUDBtl/WTD+uiYHjd8igA=
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.29.0 h1:ReXrjtwv4LSfi8bLmbMparantI0YnRb1NlPMf8gAVCQ=
|
||||
github.com/aws/aws-sdk-go-v2/service/marketplacemetering v1.29.0/go.mod h1:ctydsY6pVUtI6JnPssiu5YZabqUt4ZNONqJHehtiKBo=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.79.2 h1:tWUG+4wZqdMl/znThEk9tcCy8tTMxq8dW0JTgamohrY=
|
||||
github.com/aws/aws-sdk-go-v2/service/s3 v1.79.2/go.mod h1:U5SNqwhXB3Xe6F47kXvWihPl/ilGaEDe8HD/50Z9wxc=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.4 h1:EKXYJ8kgz4fiqef8xApu7eH0eae2SrVG+oHCLFybMRI=
|
||||
github.com/aws/aws-sdk-go-v2/service/secretsmanager v1.35.4/go.mod h1:yGhDiLKguA3iFJYxbrQkQiNzuy+ddxesSZYWVeeEH5Q=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3 h1:1Gw+9ajCV1jogloEv1RRnvfRFia2cL6c9cuKV2Ps+G8=
|
||||
github.com/aws/aws-sdk-go-v2/service/sso v1.25.3/go.mod h1:qs4a9T5EMLl/Cajiw2TcbNt2UNo/Hqlyp+GiuG4CFDI=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1 h1:hXmVKytPfTy5axZ+fYbR5d0cFmC3JvwLm5kM83luako=
|
||||
github.com/aws/aws-sdk-go-v2/service/ssooidc v1.30.1/go.mod h1:MlYRNmYu/fGPoxBQVvBYr9nyr948aY/WLUvwBMBJubs=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19 h1:1XuUZ8mYJw9B6lzAkXhqHlJd/XvaX32evhproijJEZY=
|
||||
github.com/aws/aws-sdk-go-v2/service/sts v1.33.19/go.mod h1:cQnB8CUnxbMU82JvlqjKR2HBOm3fe9pWorWBza6MBJ4=
|
||||
github.com/aws/smithy-go v1.22.3 h1:Z//5NuZCSW6R4PhQ93hShNbyBbn8BWCmCVCt+Q8Io5k=
|
||||
github.com/aws/smithy-go v1.22.3/go.mod h1:t1ufH5HMublsJYulve2RKmHDC15xu1f26kHCp/HgceI=
|
||||
github.com/beorn7/perks v1.0.1 h1:VlbKKnNfV8bJzeqoa4cOKqO6bYr3WgKZxO8Z16+hsOM=
|
||||
github.com/beorn7/perks v1.0.1/go.mod h1:G2ZrVWU2WbWT9wwq4/hrbKbnv/1ERSJQ0ibhJ6rlkpw=
|
||||
github.com/bmatcuk/doublestar/v4 v4.7.1 h1:fdDeAqgT47acgwd9bd9HxJRDmc9UAmPpc+2m0CXv75Q=
|
||||
github.com/bmatcuk/doublestar/v4 v4.7.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1 h1:54Bopc5c2cAvhLRAzqOGCYHYyhcDHsFF4wWIR5wKP38=
|
||||
github.com/bmatcuk/doublestar/v4 v4.8.1/go.mod h1:xBQ8jztBU6kakFMg+8WGxn0c6z1fTSPVIjEY1Wr7jzc=
|
||||
github.com/boombuler/barcode v1.0.1-0.20190219062509-6c824513bacc/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
github.com/boombuler/barcode v1.0.2 h1:79yrbttoZrLGkL/oOI8hBrUKucwOL0oOjUgEguGMcJ4=
|
||||
github.com/boombuler/barcode v1.0.2/go.mod h1:paBWMcWSl3LHKBqUq+rly7CNSldXjb2rDl3JlRe0mD8=
|
||||
|
|
@ -113,31 +117,32 @@ github.com/cespare/xxhash/v2 v2.3.0 h1:UL815xU9SqsFlibzuggzjXhog7bL6oX9BbNZnL2UF
|
|||
github.com/cespare/xxhash/v2 v2.3.0/go.mod h1:VGX0DQ3Q6kWi7AoAeZDth3/j3BFtOZR5XLFGgcrjCOs=
|
||||
github.com/client9/misspell v0.3.4/go.mod h1:qj6jICC3Q7zFZvVWo7KLAzC3yx5G7kyvSDkc90ppPyw=
|
||||
github.com/cncf/udpa/go v0.0.0-20191209042840-269d4d468f6f/go.mod h1:M8M6+tZqaGXZJjfX53e64911xZQV5JYwmTeXPW+k8Sc=
|
||||
github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3 h1:boJj011Hh+874zpIySeApCX4GeOjPl9qhRF3QuIZq+Q=
|
||||
github.com/cncf/xds/go v0.0.0-20241223141626-cff3c89139a3/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.3.8 h1:53yoUo4+EtrC1NrAEgnnad4AS3ntNvGup1PAXZ7UmpE=
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.3.8/go.mod h1:9uH5jK4yQ3ZQUT9IXe4I2fHzMIF5+JC/oOdzTRgJYJk=
|
||||
github.com/coreos/go-oidc/v3 v3.12.0 h1:sJk+8G2qq94rDI6ehZ71Bol3oUHy63qNYmkiSjrc/Jo=
|
||||
github.com/coreos/go-oidc/v3 v3.12.0/go.mod h1:gE3LgjOgFoHi9a4ce4/tJczr0Ai2/BoDhf0r5lltWI0=
|
||||
github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f h1:C5bqEmzEPLsHm9Mv73lSE9e9bKV23aB1vxOsmZrkl3k=
|
||||
github.com/cncf/xds/go v0.0.0-20250326154945-ae57f3c0d45f/go.mod h1:W+zGtBO5Y1IgJhy4+A9GOqVhqLpfZi+vwmdNXUehLA8=
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.4.0 h1:7K5vpE3m7LylIbmpbr4eEhApDTPMgFgR+eDPy1sdJjM=
|
||||
github.com/cockroachdb/cockroach-go/v2 v2.4.0/go.mod h1:9U179XbCx4qFWtNhc7BiWLPfuyMVQ7qdAhfrwLz1vH0=
|
||||
github.com/coreos/go-oidc/v3 v3.14.1 h1:9ePWwfdwC4QKRlCXsJGou56adA/owXczOzwKdOumLqk=
|
||||
github.com/coreos/go-oidc/v3 v3.14.1/go.mod h1:HaZ3szPaZ0e4r6ebqvsLWlk2Tn+aejfmrfah6hnSYEU=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0 h1:RrqgGjYQKalulkV8NGVIfkXQf6YYmOyiJKk8iXXhfZs=
|
||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.4/go.mod h1:tgQtvFlXSQOSOSIRvRPT7W67SCa46tRHOmNcaadrF8o=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6 h1:XJtiaUW6dEEqVuZiMTn1ldk455QWwEIsMIJlo5vtkx0=
|
||||
github.com/cpuguy83/go-md2man/v2 v2.0.6/go.mod h1:oOW0eioCTA6cOiMLiUPZOpcVxMig6NIQQ7OS05n1F4g=
|
||||
github.com/davecgh/go-spew v1.1.0/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.1/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc h1:U9qPSI2PIWSS1VwoXQT9A3Wy9MM3WgvqSxFWenqJduM=
|
||||
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc/go.mod h1:J7Y8YcW2NihsgmVo/mv3lAwl/skON4iLHjSsI+c5H38=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0 h1:rpfIENRNNilwHwZeG5+P150SMrnNEcHYvcCuK6dPZSg=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.3.0/go.mod h1:v57UDF4pDQJcEfFUCRop3lJL149eHGSe9Jvczhzjo/0=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0 h1:NMZiJj8QnKe1LgsbDayM4UoHwbvwDRwnI3hwNaAHRnc=
|
||||
github.com/decred/dcrd/dcrec/secp256k1/v4 v4.4.0/go.mod h1:ZXNYxsqcloTdSy/rNShjYzMhyjf0LaoftYK0p+A3h40=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f h1:lO4WD4F/rVNCu3HqELle0jiPLLBs70cWOduZpkS1E78=
|
||||
github.com/dgryski/go-rendezvous v0.0.0-20200823014737-9f7001d12a5f/go.mod h1:cuUVRXasLTGF7a8hSLbxyZXjz+1KgoB3wDUb6vlszIc=
|
||||
github.com/drakkan/cron/v3 v3.0.0-20230222140221-217a1e4d96c0 h1:EW9gIJRmt9lzk66Fhh4S8VEtURA6QHZqGeSRE9Nb2/U=
|
||||
github.com/drakkan/cron/v3 v3.0.0-20230222140221-217a1e4d96c0/go.mod h1:eQICP3HwyT7UooqI/z+Ov+PtYAWygg1TEWWzGIFLtro=
|
||||
github.com/drakkan/crypto v0.0.0-20241215104834-a9cd4736223d h1:xpQVtm9fMX+Moy260dDuYlKyER0L8jj7WJF6bcLXtL4=
|
||||
github.com/drakkan/crypto v0.0.0-20241215104834-a9cd4736223d/go.mod h1:kDsLvtWBEx7MV9tJOj9bnXsPbxwJQ6csT/x4KIN4Ssk=
|
||||
github.com/drakkan/crypto v0.0.0-20250420150858-04abdc60032d h1:uPtHXlWXdRX3GU7o72UFr+N4gkWXJ9UuBsNAqjqnB2k=
|
||||
github.com/drakkan/crypto v0.0.0-20250420150858-04abdc60032d/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
|
||||
github.com/drakkan/ftp v0.0.0-20240430173938-7ba8270c8e7f h1:S9JUlrOzjK58UKoLqqb40YLyVlt0bcIFtYrvnanV3zc=
|
||||
github.com/drakkan/ftp v0.0.0-20240430173938-7ba8270c8e7f/go.mod h1:4p8lUl4vQ80L598CygL+3IFtm+3nggvvW/palOlViwE=
|
||||
github.com/drakkan/ftpserverlib v0.0.0-20240603150004-6a8f643fbf2e h1:VBpqQeChkGXSV1FXCtvd3BJTyB+DcMgiu7SfkpsGuKw=
|
||||
github.com/drakkan/ftpserverlib v0.0.0-20240603150004-6a8f643fbf2e/go.mod h1:aAwyOAC6IIe+IZeeGD1QjuE3GGDzqW/c5Xtn+Dp0JUM=
|
||||
github.com/drakkan/ftpserverlib v0.0.0-20250204143431-e069fad14727 h1:OwxAvQejxuEYFtuXcOxuepEjt6VPLEQ3zK+5k9p4M60=
|
||||
github.com/drakkan/ftpserverlib v0.0.0-20250204143431-e069fad14727/go.mod h1:TRdVBbJEt+KihZKGl6jgSp6H/yPc0NxMUAlMZuNHcmY=
|
||||
github.com/drakkan/webdav v0.0.0-20241026165615-b8b8f74ae71b h1:Y1tLiQ8fnxM5f3wiBjAXsHzHNwiY9BR+mXZA75nZwrs=
|
||||
github.com/drakkan/webdav v0.0.0-20241026165615-b8b8f74ae71b/go.mod h1:zOVb1QDhwwqWn2L2qZ0U3swMSO4GTSNyIwXCGO/UGWE=
|
||||
github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001 h1:/ZshrfQzayqRSBDodmp3rhNCHJCff+utvgBuWRbiqu4=
|
||||
|
|
@ -145,15 +150,15 @@ github.com/eikenb/pipeat v0.0.0-20210730190139-06b3e6902001/go.mod h1:kltMsfRMTH
|
|||
github.com/envoyproxy/go-control-plane v0.9.0/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.1-0.20191026205805-5f8ba28d4473/go.mod h1:YTl/9mNaCwkRvm6d1a2C3ymFceY/DCBVvsKhRF0iEA4=
|
||||
github.com/envoyproxy/go-control-plane v0.9.4/go.mod h1:6rpuAdCZL397s3pYoYcLgu1mIlRU8Am5FuJP05cCM98=
|
||||
github.com/envoyproxy/go-control-plane v0.13.3 h1:F2vYcSF8iRNhfvhZQRZ5Dvuyu0TpXazE9+h53TzkvA4=
|
||||
github.com/envoyproxy/go-control-plane v0.13.3/go.mod h1:uhvHSBAMSvy2Y+CuAYfByIRH19zcdir1rgmMzKUo3eA=
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.32.2 h1:zidqwmijfcbyKqVxjQDFx042PgX+p9U+/fu/f9VtSk8=
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.32.2/go.mod h1:eR2SOX2IedqlPvmiKjUH7Wu//S602JKI7HPC/L3SRq8=
|
||||
github.com/envoyproxy/go-control-plane v0.13.4 h1:zEqyPVyku6IvWCFwux4x9RxkLOMUL+1vC9xUFv5l2/M=
|
||||
github.com/envoyproxy/go-control-plane v0.13.4/go.mod h1:kDfuBlDVsSj2MjrLEtRWtHlsWIFcGyB2RMO44Dc5GZA=
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.32.4 h1:jb83lalDRZSpPWW2Z7Mck/8kXZ5CQAFYVjQcdVIr83A=
|
||||
github.com/envoyproxy/go-control-plane/envoy v1.32.4/go.mod h1:Gzjc5k8JcJswLjAx1Zm+wSYE20UrLtt7JZMWiWQXQEw=
|
||||
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0 h1:/G9QYbddjL25KvtKTv3an9lx6VBE2cnb8wp1vEGNYGI=
|
||||
github.com/envoyproxy/go-control-plane/ratelimit v0.1.0/go.mod h1:Wk+tMFAFbCXaJPzVVHnPgRKdUdwW/KdbRt94AzgRee4=
|
||||
github.com/envoyproxy/protoc-gen-validate v0.1.0/go.mod h1:iSmxcyjqTsJpI2R4NaDN7+kN2VEUnK/pcBlmesArF7c=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.1.0 h1:tntQDh69XqOCOZsDz0lVJQez/2L6Uu2PdjCQwWCJ3bM=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.1.0/go.mod h1:sXRDRVmzEbkM7CVcM06s9shE/m23dg3wzjl0UWqJ2q4=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1 h1:DEo3O99U8j4hBFwbJfrz9VtgcDfUKS7KJ7spH3d86P8=
|
||||
github.com/envoyproxy/protoc-gen-validate v1.2.1/go.mod h1:d/C80l/jxXLdfEIhX1W2TmLfsJ31lvEjwamM4DxlWXU=
|
||||
github.com/fatih/color v1.13.0/go.mod h1:kLAiJbzzSOZDVNGyDpeOxJ47H46qBXwg5ILebYFFOfk=
|
||||
github.com/fatih/color v1.18.0 h1:S8gINlzdQ840/4pfAwic/ZE0djQEH3wM94VfqLTZcOM=
|
||||
github.com/fatih/color v1.18.0/go.mod h1:4FelSpRwEGDpQ12mAdzqdOukCy4u8WUtOY6lkT/6HfU=
|
||||
|
|
@ -163,18 +168,18 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
|
|||
github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
|
||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
|
||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
|
||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
|
||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-acme/lego/v4 v4.21.0 h1:arEW+8o5p7VI8Bk1kr/PDlgD1DrxtTH1gJ4b7mehL8o=
|
||||
github.com/go-acme/lego/v4 v4.21.0/go.mod h1:HrSWzm3Ckj45Ie3i+p1zKVobbQoMOaGu9m4up0dUeDI=
|
||||
github.com/go-chi/chi/v5 v5.2.0 h1:Aj1EtB0qR2Rdo2dG4O94RIU35w2lvQSj6BRA4+qwFL0=
|
||||
github.com/go-chi/chi/v5 v5.2.0/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/jwtauth/v5 v5.3.2 h1:s+ON3ATyyMs3Me0kqyuua6Rwu+2zqIIkL0GCaMarwvs=
|
||||
github.com/go-chi/jwtauth/v5 v5.3.2/go.mod h1:O4QvPRuZLZghl9WvfVaON+ARfGzpD2PBX/QY5vUz7aQ=
|
||||
github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
|
||||
github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
|
||||
github.com/go-acme/lego/v4 v4.23.1 h1:lZ5fGtGESA2L9FB8dNTvrQUq3/X4QOb8ExkKyY7LSV4=
|
||||
github.com/go-acme/lego/v4 v4.23.1/go.mod h1:7UMVR7oQbIYw6V7mTgGwi4Er7B6Ww0c+c8feiBM0EgI=
|
||||
github.com/go-chi/chi/v5 v5.2.1 h1:KOIHODQj58PmL80G2Eak4WdvUzjSJSm0vG72crDCqb8=
|
||||
github.com/go-chi/chi/v5 v5.2.1/go.mod h1:L2yAIGWB3H+phAw1NxKwWM+7eUH/lU8pOMm5hHcoops=
|
||||
github.com/go-chi/jwtauth/v5 v5.3.3 h1:50Uzmacu35/ZP9ER2Ht6SazwPsnLQ9LRJy6zTZJpHEo=
|
||||
github.com/go-chi/jwtauth/v5 v5.3.3/go.mod h1:O4QvPRuZLZghl9WvfVaON+ARfGzpD2PBX/QY5vUz7aQ=
|
||||
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||
github.com/go-jose/go-jose/v4 v4.0.4 h1:VsjPI33J0SB9vQM6PLmNjoHqMQNGPiZ0rHL7Ni7Q6/E=
|
||||
github.com/go-jose/go-jose/v4 v4.0.4/go.mod h1:NKb5HO1EZccyMpiZNbdUw/14tiXNyUJh188dfnMCAfc=
|
||||
github.com/go-jose/go-jose/v4 v4.1.1-0.20250421195336-4ff65aefe8a5 h1:bOa3sZOH8fLlvgO9T1avU8Rwe79aNDyrOSRb1XHeqRM=
|
||||
github.com/go-jose/go-jose/v4 v4.1.1-0.20250421195336-4ff65aefe8a5/go.mod h1:6zIvRV16dgvcCxXgz0tOZ9XjntGo7SWTeTEd2hR5JlE=
|
||||
github.com/go-kit/log v0.2.1 h1:MRVx0/zhvdseW+Gza6N9rVzU/IVzaeE1SFI4raAhmBU=
|
||||
github.com/go-kit/log v0.2.1/go.mod h1:NwTd00d/i8cPZ3xOwwiv2PO5MOcx78fFErGNcVmBjv0=
|
||||
github.com/go-logfmt/logfmt v0.5.1 h1:otpy5pqBCBZ1ng9RQ0dPu4PN7ba75Y/aA+UpowDyNVA=
|
||||
|
|
@ -187,15 +192,17 @@ github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre
|
|||
github.com/go-ole/go-ole v1.2.6/go.mod h1:pprOEPIfldk/42T2oK7lQ4v4JSDwmV0As9GaiUsvbm0=
|
||||
github.com/go-ole/go-ole v1.3.0 h1:Dt6ye7+vXGIKZ7Xtk4s6/xVdGDQynvom7xCFEdWr6uE=
|
||||
github.com/go-ole/go-ole v1.3.0/go.mod h1:5LS6F96DhAwUc7C+1HLexzMXY1xGRSryjyPPKW6zv78=
|
||||
github.com/go-sql-driver/mysql v1.8.1 h1:LedoTUt/eveggdHS9qUFC1EFSa8bU2+1pZjSRpvNJ1Y=
|
||||
github.com/go-sql-driver/mysql v1.8.1/go.mod h1:wEBSXgmK//2ZFJyE+qWnIsVGmvmEKlqwuVSjsCm7DZg=
|
||||
github.com/goccy/go-json v0.10.4 h1:JSwxQzIqKfmFX1swYPpUThQZp/Ka4wzJdK0LWVytLPM=
|
||||
github.com/goccy/go-json v0.10.4/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/go-sql-driver/mysql v1.9.2 h1:4cNKDYQ1I84SXslGddlsrMhc8k4LeDVj6Ad6WRjiHuU=
|
||||
github.com/go-sql-driver/mysql v1.9.2/go.mod h1:qn46aNg1333BRMNU69Lq93t8du/dwxI64Gl8i5p1WMU=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
|
||||
github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
|
||||
github.com/goccy/go-json v0.10.5 h1:Fq85nIqj+gXn/S5ahsiTlK3TmC85qgirsdTP/+DeaC4=
|
||||
github.com/goccy/go-json v0.10.5/go.mod h1:oq7eo15ShAhp70Anwd5lgX2pLfOS3QCiwU/PULtXL6M=
|
||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
|
||||
github.com/gofrs/flock v0.12.1 h1:MTLVXXHf8ekldpJk3AKicLij9MdwOWkZ+a/jHHZby9E=
|
||||
github.com/gofrs/flock v0.12.1/go.mod h1:9zxTsyu5xtJ9DK+1tFZyibEV7y3uwDxPPfbxeeHCoD0=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1 h1:OuVbFODueb089Lh128TAcimifWaLhJwVflnrgM17wHk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.1/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2 h1:Rl4B7itRWVtYIHFrSNd7vhTiz9UpLdi6gZhZ3wEeDy8=
|
||||
github.com/golang-jwt/jwt/v5 v5.2.2/go.mod h1:pqrtFR0X4osieyHYxtmOUWsAWrfe1Q5UVIyoH402zdk=
|
||||
github.com/golang/glog v0.0.0-20160126235308-23def4e6c14b/go.mod h1:SBH7ygxi8pfUlaOkMMuAQtPIUF8ecWP5IEl/CR7VP2Q=
|
||||
github.com/golang/groupcache v0.0.0-20200121045136-8c9f03a8e57e/go.mod h1:cIg4eruTrX1D+g88fzRXU5OdNfaM+9IcxsU14FzY7Hc=
|
||||
github.com/golang/groupcache v0.0.0-20241129210726-2c02b8208cf8 h1:f+oWsMOmNPc8JmEHVZIycC7hBoQxHH9pNKQORJNozsQ=
|
||||
|
|
@ -218,12 +225,13 @@ github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMyw
|
|||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.5.3/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
|
||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
|
||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
|
||||
github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
|
||||
github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
|
||||
github.com/google/martian/v3 v3.3.3 h1:DIhPTQrbPkgs2yJYdXU/eNACCG5DVQjySNRNlflZ9Fc=
|
||||
github.com/google/martian/v3 v3.3.3/go.mod h1:iEPrYcgCF7jA9OtScMFQyAlZZ4YXTKEtJ1E6RWzmBA0=
|
||||
github.com/google/s2a-go v0.1.8 h1:zZDs9gcbt9ZPLV0ndSyQk6Kacx2g/X+SKYovpnz3SMM=
|
||||
github.com/google/s2a-go v0.1.8/go.mod h1:6iNWHTpQ+nfNRN5E00MSdfDwVesa8hhS32PhPO8deJA=
|
||||
github.com/google/s2a-go v0.1.9 h1:LGD7gtMgezd8a/Xak7mEWL0PjoTQFvpRudN895yqKW0=
|
||||
github.com/google/s2a-go v0.1.9/go.mod h1:YA0Ei2ZQL3acow2O62kdp9UlnvMmU7kA6Eutn0dXayM=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510 h1:El6M4kTTCOh6aBiKaUGG7oYTSPP8MxqL4YI3kZKwcP4=
|
||||
github.com/google/shlex v0.0.0-20191202100458-e7afc7fbc510/go.mod h1:pupxD2MaaD3pAXIBCelhxNneeOaAeabZDe5s4K6zSpQ=
|
||||
github.com/google/uuid v1.1.2/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
|
|
@ -231,8 +239,8 @@ github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
|
|||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
|
||||
github.com/google/wire v0.6.0 h1:HBkoIh4BdSxoyo9PveV8giw7ZsaBOvzWKfcg/6MrVwI=
|
||||
github.com/google/wire v0.6.0/go.mod h1:F4QhpQ9EDIdJ1Mbop/NZBRB+5yrR6qg3BnctaoUk6NA=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4 h1:XYIDZApgAnrN1c855gTgghdIA6Stxb52D5RnLI1SLyw=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.4/go.mod h1:YKe7cfqYXjKGpGvmSg28/fFvhNzinZQm8DGnaburhGA=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6 h1:GW/XbdyBFQ8Qe+YAmFU9uHLo7OnF5tL52HFAgMmyrf4=
|
||||
github.com/googleapis/enterprise-certificate-proxy v0.3.6/go.mod h1:MkHOF77EYAE7qfSuSS9PU6g4Nt4e11cnsDUowfwewLA=
|
||||
github.com/googleapis/gax-go/v2 v2.14.1 h1:hb0FFeiPaQskmvakKu5EbCbpntQn48jyHuvrkurSS/Q=
|
||||
github.com/googleapis/gax-go/v2 v2.14.1/go.mod h1:Hb/NubMaVM88SrNkvl8X/o8XWwDJEPqouaLeN2IUxoA=
|
||||
github.com/hashicorp/errwrap v1.0.0/go.mod h1:YH+1FKiLXxHSkmPseP+kNlulaMuP3n2brvKWEqk/Jc4=
|
||||
|
|
@ -244,12 +252,10 @@ github.com/hashicorp/go-hclog v1.6.3 h1:Qr2kF+eVWjTiYmU7Y31tYlP1h0q/X3Nl3tPGdaB1
|
|||
github.com/hashicorp/go-hclog v1.6.3/go.mod h1:W4Qnvbt70Wk/zYJryRzDRU/4r0kIg0PVHBcfoyhpF5M=
|
||||
github.com/hashicorp/go-multierror v1.1.1 h1:H5DkEtf6CXdFp0N0Em5UCwQpXMWke8IA0+lD48awMYo=
|
||||
github.com/hashicorp/go-multierror v1.1.1/go.mod h1:iw975J/qwKPdAO1clOe2L8331t/9/fmwbPZ6JB6eMoM=
|
||||
github.com/hashicorp/go-plugin v1.6.2 h1:zdGAEd0V1lCaU0u+MxWQhtSDQmahpkwOun8U8EiRVog=
|
||||
github.com/hashicorp/go-plugin v1.6.2/go.mod h1:CkgLQ5CZqNmdL9U9JzM532t8ZiYQ35+pj3b1FD37R0Q=
|
||||
github.com/hashicorp/go-plugin v1.6.3 h1:xgHB+ZUSYeuJi96WtxEjzi23uh7YQpznjGh0U0UUrwg=
|
||||
github.com/hashicorp/go-plugin v1.6.3/go.mod h1:MRobyh+Wc/nYy1V4KAXUiYfzxoYhs7V1mlH1Z7iY2h0=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7 h1:C8hUCYzor8PIfXHa4UrZkU4VvK8o9ISHxT2Q8+VepXU=
|
||||
github.com/hashicorp/go-retryablehttp v0.7.7/go.mod h1:pkQpWZeYWskR+D1tR2O5OcBFOxfA7DoAO6xtkuQnHTk=
|
||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
|
||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
|
||||
github.com/hashicorp/yamux v0.1.2 h1:XtB8kyFOyHXYVFnwT5C3+Bdo8gArse7j2AQ0DA0Uey8=
|
||||
github.com/hashicorp/yamux v0.1.2/go.mod h1:C+zze2n6e/7wshOZep2A70/aQU6QBRWJO/G6FT1wIns=
|
||||
github.com/inconshreveable/mousetrap v1.1.0 h1:wN+x4NVGpMsO7ErUn/mUI3vEoE6Jt13X2s0bqwp9tc8=
|
||||
|
|
@ -258,14 +264,16 @@ github.com/jackc/pgpassfile v1.0.0 h1:/6Hmqy13Ss2zCq62VdNG8tM1wchn8zjSGOBJ6icpsI
|
|||
github.com/jackc/pgpassfile v1.0.0/go.mod h1:CEx0iS5ambNFdcRtxPj5JhEz+xB6uRky5eyVu/W2HEg=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 h1:iCEnooe7UlwOQYpKFhBabPMi4aNAfoODPEFNiAnClxo=
|
||||
github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761/go.mod h1:5TJZWKEWniPve33vlWYSoGYefn3gLQRzjfDlhSJ9ZKM=
|
||||
github.com/jackc/pgx/v5 v5.7.2 h1:mLoDLV6sonKlvjIEsV56SkWNCnuNv531l94GaIzO+XI=
|
||||
github.com/jackc/pgx/v5 v5.7.2/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
|
||||
github.com/jackc/pgx/v5 v5.7.4 h1:9wKznZrhWa2QiHL+NjTSPP6yjl3451BX3imWDnokYlg=
|
||||
github.com/jackc/pgx/v5 v5.7.4/go.mod h1:ncY89UGWxg82EykZUwSpUKEfccBGGYq1xjrOpsbsfGQ=
|
||||
github.com/jackc/puddle/v2 v2.2.2 h1:PR8nw+E/1w0GLuRFSmiioY6UooMp6KJv0/61nB7icHo=
|
||||
github.com/jackc/puddle/v2 v2.2.2/go.mod h1:vriiEXHvEE654aYKXXjOvZM39qJ0q+azkZFrfEOc3H4=
|
||||
github.com/jhump/protoreflect v1.15.1 h1:HUMERORf3I3ZdX05WaQ6MIpd/NJ434hTp5YiKgfCL6c=
|
||||
github.com/jhump/protoreflect v1.15.1/go.mod h1:jD/2GMKKE6OqX8qTjhADU1e6DShO+gavG9e0Q693nKo=
|
||||
github.com/klauspost/compress v1.17.11 h1:In6xLpyWOi1+C7tXUUWv2ot1QvBjxevKAaI6IXrJmUc=
|
||||
github.com/klauspost/compress v1.17.11/go.mod h1:pMDklpSncoRMuLFrf1W9Ss9KT+0rH90U12bZKk7uwG0=
|
||||
github.com/keybase/go-keychain v0.0.1 h1:way+bWYa6lDppZoZcgMbYsvC7GxljxrskdNInRtuthU=
|
||||
github.com/keybase/go-keychain v0.0.1/go.mod h1:PdEILRW3i9D8JcdM+FmY6RwkHGnhHxXwkPPMeUgOK1k=
|
||||
github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
|
||||
github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
|
||||
github.com/kr/fs v0.1.0 h1:Jskdu9ieNAYnjxsi0LbQp1ulIKZV1LAFgK1tWhpZgl8=
|
||||
github.com/kr/fs v0.1.0/go.mod h1:FFnZGqtBN9Gxj7eW1uZ42v5BccTP0vu6NEaFoC2HwRg=
|
||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
|
||||
|
|
@ -274,63 +282,60 @@ github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
|
|||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
|
||||
github.com/kylelemons/godebug v1.1.0 h1:RPNrshWIDI6G2gRW9EHilWtl7Z6Sb1BR0xunSBf0SNc=
|
||||
github.com/kylelemons/godebug v1.1.0/go.mod h1:9/0rRGxNHcop5bhtWyNeEfOS8JIWk580+fNqagV/RAw=
|
||||
github.com/lestrrat-go/blackmagic v1.0.2 h1:Cg2gVSc9h7sz9NOByczrbUvLopQmXrfFx//N+AkAr5k=
|
||||
github.com/lestrrat-go/blackmagic v1.0.2/go.mod h1:UrEqBzIR2U6CnzVyUtfM6oZNMt/7O7Vohk2J0OGSAtU=
|
||||
github.com/lestrrat-go/blackmagic v1.0.3 h1:94HXkVLxkZO9vJI/w2u1T0DAoprShFd13xtnSINtDWs=
|
||||
github.com/lestrrat-go/blackmagic v1.0.3/go.mod h1:6AWFyKNNj0zEXQYfTMPfZrAXUWUfTIZ5ECEUEJaijtw=
|
||||
github.com/lestrrat-go/httpcc v1.0.1 h1:ydWCStUeJLkpYyjLDHihupbn2tYmZ7m22BGkcvZZrIE=
|
||||
github.com/lestrrat-go/httpcc v1.0.1/go.mod h1:qiltp3Mt56+55GPVCbTdM9MlqhvzyuL6W/NMDA8vA5E=
|
||||
github.com/lestrrat-go/httprc v1.0.6 h1:qgmgIRhpvBqexMJjA/PmwSvhNk679oqD1RbovdCGW8k=
|
||||
github.com/lestrrat-go/httprc v1.0.6/go.mod h1:mwwz3JMTPBjHUkkDv/IGJ39aALInZLrhBp0X7KGUZlo=
|
||||
github.com/lestrrat-go/iter v1.0.2 h1:gMXo1q4c2pHmC3dn8LzRhJfP1ceCbgSiT9lUydIzltI=
|
||||
github.com/lestrrat-go/iter v1.0.2/go.mod h1:Momfcq3AnRlRjI5b5O8/G5/BvpzrhoFTZcn06fEOPt4=
|
||||
github.com/lestrrat-go/jwx/v2 v2.1.3 h1:Ud4lb2QuxRClYAmRleF50KrbKIoM1TddXgBrneT5/Jo=
|
||||
github.com/lestrrat-go/jwx/v2 v2.1.3/go.mod h1:q6uFgbgZfEmQrfJfrCo90QcQOcXFMfbI/fO0NqRtvZo=
|
||||
github.com/lestrrat-go/jwx/v2 v2.1.6-0.20250420095048-a18531964875 h1:96mya9rDuzBBnNlzlIjiQBBuUkNxCaysfTb8mU4xFRo=
|
||||
github.com/lestrrat-go/jwx/v2 v2.1.6-0.20250420095048-a18531964875/go.mod h1:Y722kU5r/8mV7fYDifjug0r8FK8mZdw0K0GpJw/l8pU=
|
||||
github.com/lestrrat-go/option v1.0.1 h1:oAzP2fvZGQKWkvHa1/SAcFolBEca1oN+mQ7eooNBEYU=
|
||||
github.com/lestrrat-go/option v1.0.1/go.mod h1:5ZHFbivi4xwXxhxY9XHDe2FHo6/Z7WWmtT7T5nBBp3I=
|
||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
|
||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
|
||||
github.com/lithammer/shortuuid/v4 v4.2.0 h1:LMFOzVB3996a7b8aBuEXxqOBflbfPQAiVzkIcHO0h8c=
|
||||
github.com/lithammer/shortuuid/v4 v4.2.0/go.mod h1:D5noHZ2oFw/YaKCfGy0YxyE7M0wMbezmMjPdhyEFe6Y=
|
||||
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683 h1:7UMa6KCCMjZEMDtTVdcGu0B1GmmC7QJKiCCjyTAWQy0=
|
||||
github.com/lufia/plan9stats v0.0.0-20240909124753-873cd0166683/go.mod h1:ilwx/Dta8jXAgpFYFvSWEMwxmbWXyiUHkd5FwyKhb5k=
|
||||
github.com/magiconair/properties v1.8.9 h1:nWcCbLq1N2v/cpNsy5WvQ37Fb+YElfq20WJ/a8RkpQM=
|
||||
github.com/magiconair/properties v1.8.9/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35 h1:PpXWgLPs+Fqr325bN2FD2ISlRRztXibcX6e8f5FR5Dc=
|
||||
github.com/lufia/plan9stats v0.0.0-20250317134145-8bc96cf8fc35/go.mod h1:autxFIvghDt3jPTLoqZ9OZ7s9qTGNAWmYCjVFWPX/zg=
|
||||
github.com/mattn/go-colorable v0.1.9/go.mod h1:u6P/XSegPjTcexA+o6vUJrdnUu04hMope9wVRipJSqc=
|
||||
github.com/mattn/go-colorable v0.1.12/go.mod h1:u5H1YNBxpqRaxsYJYSkiCWKzEfiAb1Gb520KVy5xxl4=
|
||||
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.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
|
||||
github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
|
||||
github.com/mattn/go-isatty v0.0.12/go.mod h1:cbi8OIDigv2wuxKPP5vlRcQ1OAZbq2CE4Kysco4FUpU=
|
||||
github.com/mattn/go-isatty v0.0.14/go.mod h1:7GGIvUiUoEMVVmxf/4nioHXj79iQHKdU27kJ6hsGG94=
|
||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
|
||||
github.com/mattn/go-isatty v0.0.19/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-isatty v0.0.20 h1:xfD0iDuEKnDkl03q4limB+vH+GxLEtL/jb4xVJSWWEY=
|
||||
github.com/mattn/go-isatty v0.0.20/go.mod h1:W+V8PltTTMOvKvAeJH7IuucS94S2C6jfK/D7dTCTo3Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.24 h1:tpSp2G2KyMnnQu99ngJ47EIkWVmliIizyZBfPrBWDRM=
|
||||
github.com/mattn/go-sqlite3 v1.14.24/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mattn/go-sqlite3 v1.14.28 h1:ThEiQrnbtumT+QMknw63Befp/ce/nUPgBPMlRFEum7A=
|
||||
github.com/mattn/go-sqlite3 v1.14.28/go.mod h1:Uh1q+B4BYcTPb+yiD3kU8Ct7aC0hY9fxUwlHK0RXw+Y=
|
||||
github.com/mhale/smtpd v0.8.3 h1:8j8YNXajksoSLZja3HdwvYVZPuJSqAxFsib3adzRRt8=
|
||||
github.com/mhale/smtpd v0.8.3/go.mod h1:MQl+y2hwIEQCXtNhe5+55n0GZOjSmeqORDIXbqUL3x4=
|
||||
github.com/miekg/dns v1.1.62 h1:cN8OuEF1/x5Rq6Np+h1epln8OiyPWV+lROx9LxcGgIQ=
|
||||
github.com/miekg/dns v1.1.62/go.mod h1:mvDlcItzm+br7MToIKqkglaGhlFMHJ9DTNNWONWXbNQ=
|
||||
github.com/miekg/dns v1.1.65 h1:0+tIPHzUW0GCge7IiK3guGP57VAw7hoPDfApjkMD1Fc=
|
||||
github.com/miekg/dns v1.1.65/go.mod h1:Dzw9769uoKVaLuODMDZz9M6ynFU6Em65csPuoi8G0ck=
|
||||
github.com/minio/sio v0.4.1 h1:EMe3YBC1nf+sRQia65Rutxi+Z554XPV0dt8BIBA+a/0=
|
||||
github.com/minio/sio v0.4.1/go.mod h1:oBSjJeGbBdRMZZwna07sX9EFzZy+ywu5aofRiV1g79I=
|
||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
|
||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822 h1:C3w9PqII01/Oq1c1nUAm88MOHcQC9l5mIlSMApZMrHA=
|
||||
github.com/munnerz/goautoneg v0.0.0-20191010083416-a7dc8b61c822/go.mod h1:+n7T8mK8HuQTcFwEeznm/DIxMOiR9yIdICNftLE1DvQ=
|
||||
github.com/oklog/run v1.1.0 h1:GEenZ1cK0+q0+wsJew9qUg/DyD8k3JzYsZAi5gYi2mA=
|
||||
github.com/oklog/run v1.1.0/go.mod h1:sVPdnTZT1zYwAJeCMu2Th4T21pA3FPOQRfWjQlk7DVU=
|
||||
github.com/otiai10/copy v1.14.0 h1:dCI/t1iTdYGtkvCuBG2BgR6KZa83PTclw4U5n2wAllU=
|
||||
github.com/otiai10/copy v1.14.0/go.mod h1:ECfuL02W+/FkTWZWgQqXPWZgW9oeKCSQ5qVfSc4qc4w=
|
||||
github.com/otiai10/mint v1.5.1 h1:XaPLeE+9vGbuyEHem1JNk3bYc7KKqyI/na0/mLd/Kks=
|
||||
github.com/otiai10/mint v1.5.1/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
|
||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
|
||||
github.com/otiai10/copy v1.14.1 h1:5/7E6qsUMBaH5AnQ0sSLzzTg1oTECmcCmT6lvF45Na8=
|
||||
github.com/otiai10/copy v1.14.1/go.mod h1:oQwrEDDOci3IM8dJF0d8+jnbfPDllW6vUjNc3DoZm9I=
|
||||
github.com/otiai10/mint v1.6.3 h1:87qsV/aw1F5as1eH1zS/yqHY85ANKVMgkDrf9rcxbQs=
|
||||
github.com/otiai10/mint v1.6.3/go.mod h1:MJm72SBthJjz8qhefc4z1PYEieWmy8Bku7CjcAqyUSM=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
|
||||
github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
|
||||
github.com/pires/go-proxyproto v0.8.0 h1:5unRmEAPbHXHuLjDg01CxJWf91cw3lKHc/0xzKpXEe0=
|
||||
github.com/pires/go-proxyproto v0.8.0/go.mod h1:iknsfgnH8EkjrMeMyvfKByp9TiBZCKZM0jx2xmKqnVY=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c h1:+mdjkGKdHQG3305AYmdv1U2eRNDiU2ErMBj1gwrq8eQ=
|
||||
github.com/pkg/browser v0.0.0-20240102092130-5ac0b6a4141c/go.mod h1:7rwL4CYBLnjLxUqIJNnCWiEdr3bn6IUYi15bNlnbCCU=
|
||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
|
||||
github.com/pkg/sftp v1.13.7 h1:uv+I3nNJvlKZIQGSr8JVQLNHFU9YhhNpvC14Y6KgmSM=
|
||||
github.com/pkg/sftp v1.13.7/go.mod h1:KMKI0t3T6hfA+lTR/ssZdunHo+uwq7ghoN09/FSu3DY=
|
||||
github.com/pkg/sftp v1.13.9 h1:4NGkvGudBL7GteO3m6qnaQ4pC0Kvf0onSVc9gR3EWBw=
|
||||
github.com/pkg/sftp v1.13.9/go.mod h1:OBN7bVXdstkFFN/gdnHPUb5TE8eb8G1Rp9wCItqjkkA=
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10 h1:GFCKgmp0tecUJ0sJuv4pzYCqS9+RGSn52M3FUwPs+uo=
|
||||
github.com/planetscale/vtprotobuf v0.6.1-0.20240319094008-0393e58bdf10/go.mod h1:t/avpk3KcrXxUnYOhZhMXJlSEyie6gQbtLq5NM3loB8=
|
||||
github.com/pmezard/go-difflib v1.0.0/go.mod h1:iKH77koFhYxTK1pcRnkKkqfTogsbg7gZNVY4sRDYZ/4=
|
||||
|
|
@ -342,30 +347,29 @@ github.com/pquerna/otp v1.4.0 h1:wZvl1TIVxKRThZIBiwOOHOGP/1+nZyWBil9Y2XNEDzg=
|
|||
github.com/pquerna/otp v1.4.0/go.mod h1:dkJfzwRKNiegxyNb54X/3fLwhCynbMspSyWKnvi1AEg=
|
||||
github.com/prashantv/gostub v1.1.0 h1:BTyx3RfQjRHnUWaGF9oQos79AlQ5k8WNktv7VGvVH4g=
|
||||
github.com/prashantv/gostub v1.1.0/go.mod h1:A5zLQHz7ieHGG7is6LLXLz7I8+3LZzsrV0P1IAHhP5U=
|
||||
github.com/prometheus/client_golang v1.20.5 h1:cxppBPuYhUnsO6yo/aoRol4L7q7UFfdm+bR9r+8l63Y=
|
||||
github.com/prometheus/client_golang v1.20.5/go.mod h1:PIEt8X02hGcP8JWbeHyeZ53Y/jReSnHgO035n//V5WE=
|
||||
github.com/prometheus/client_golang v1.22.0 h1:rb93p9lokFEsctTys46VnV1kLCDpVZ0a/Y92Vm0Zc6Q=
|
||||
github.com/prometheus/client_golang v1.22.0/go.mod h1:R7ljNsLXhuQXYZYtw6GAE9AZg8Y7vEW5scdCXrWRXC0=
|
||||
github.com/prometheus/client_model v0.0.0-20190812154241-14fe0d1b01d4/go.mod h1:xMI15A0UPsDsEKsMN9yxemIoYk6Tm2C1GtYGdfGttqA=
|
||||
github.com/prometheus/client_model v0.6.1 h1:ZKSh/rekM+n3CeS952MLRAdFwIKqeY8b62p8ais2e9E=
|
||||
github.com/prometheus/client_model v0.6.1/go.mod h1:OrxVMOVHjw3lKMa8+x6HeMGkHMQyHDk9E3jmP2AmGiY=
|
||||
github.com/prometheus/common v0.61.0 h1:3gv/GThfX0cV2lpO7gkTUwZru38mxevy90Bj8YFSRQQ=
|
||||
github.com/prometheus/common v0.61.0/go.mod h1:zr29OCN/2BsJRaFwG8QOBr41D6kkchKbpeNH7pAjb/s=
|
||||
github.com/prometheus/procfs v0.15.1 h1:YagwOFzUgYfKKHX6Dr+sHT7km/hxC76UB0learggepc=
|
||||
github.com/prometheus/procfs v0.15.1/go.mod h1:fB45yRUv8NstnjriLhBQLuOUt+WW4BsoGhij/e3PBqk=
|
||||
github.com/prometheus/client_model v0.6.2 h1:oBsgwpGs7iVziMvrGhE53c/GrLUsZdHnqNwqPLxwZyk=
|
||||
github.com/prometheus/client_model v0.6.2/go.mod h1:y3m2F6Gdpfy6Ut/GBsUqTWZqCUvMVzSfMLjcu6wAwpE=
|
||||
github.com/prometheus/common v0.63.0 h1:YR/EIY1o3mEFP/kZCD7iDMnLPlGyuU2Gb3HIcXnA98k=
|
||||
github.com/prometheus/common v0.63.0/go.mod h1:VVFF/fBIoToEnWRVkYoXEkq3R3paCoxG9PXP74SnV18=
|
||||
github.com/prometheus/procfs v0.16.1 h1:hZ15bTNuirocR6u0JZ6BAHHmwS1p8B4P6MRqxtzMyRg=
|
||||
github.com/prometheus/procfs v0.16.1/go.mod h1:teAbpZRB1iIAJYREa1LsoWUXykVXA1KlTmWl8x/U+Is=
|
||||
github.com/redis/go-redis/v9 v9.7.3 h1:YpPyAayJV+XErNsatSElgRZZVCwXX9QzkKYNvO7x0wM=
|
||||
github.com/redis/go-redis/v9 v9.7.3/go.mod h1:bGUrSggJ9X9GUmZpZNEOQKaANxSGgOEBRltRTZHSvrA=
|
||||
github.com/rogpeppe/go-internal v1.13.1 h1:KvO1DLK/DRN07sQ1LQKScxyZJuNnedQ5/wKSR38lUII=
|
||||
github.com/rogpeppe/go-internal v1.13.1/go.mod h1:uMEvuHeurkdAXX61udpOXGD/AzZDWNMNyH2VO9fmH0o=
|
||||
github.com/rs/cors v1.11.1 h1:eU3gRzXLRK57F5rKMGMZURNdIG4EoAmX8k94r9wXWHA=
|
||||
github.com/rs/cors v1.11.1/go.mod h1:XyqrcTp5zjWr1wsJ8PIRZssZ8b/WMcMf71DJnit4EMU=
|
||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
|
||||
github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
|
||||
github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
|
||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
|
||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
|
||||
github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
|
||||
github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
|
||||
github.com/russross/blackfriday/v2 v2.1.0 h1:JIOH55/0cWyOuilr9/qlrm0BSXldqnqwMsf35Ld67mk=
|
||||
github.com/russross/blackfriday/v2 v2.1.0/go.mod h1:+Rmxgy9KzJVeS9/2gXHxylqXiyQDYRxCVz55jmeOWTM=
|
||||
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
|
||||
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
|
||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
|
||||
github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k=
|
||||
github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk=
|
||||
github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4 h1:PT+ElG/UUFMfqy5HrxJxNzj3QBOf7dZwupeVC+mG1Lo=
|
||||
github.com/secsy/goftp v0.0.0-20200609142545-aa2de14babf4/go.mod h1:MnkX001NG75g3p8bhFycnyIjeQoOjGL6CEIsdE/nKSY=
|
||||
github.com/segmentio/asm v1.2.0 h1:9BQrFxC+YOHJlTlHGkTrFWf59nbL3XnCoFLTwDCI7ys=
|
||||
|
|
@ -380,16 +384,18 @@ github.com/shoenig/test v0.6.4 h1:kVTaSd7WLz5WZ2IaoM0RSzRsUD+m8wRR+5qvntpn4LU=
|
|||
github.com/shoenig/test v0.6.4/go.mod h1:byHiCGXqrVaflBLAMq/srcZIHynQPQgeyvkvXnjqq0k=
|
||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
|
||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
|
||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
|
||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
|
||||
github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
|
||||
github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
|
||||
github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
|
||||
github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
|
||||
github.com/spf13/cobra v1.8.1 h1:e5/vxKd/rZsfSJMUX1agtjeTDf+qv1/JdBF8gg5k9ZM=
|
||||
github.com/spf13/cobra v1.8.1/go.mod h1:wHxEcudfqmLYa8iTfL+OuZPbBZkmvliBWKIezN3kD9Y=
|
||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
|
||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
|
||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
|
||||
github.com/spf13/cobra v1.9.1 h1:CXSaggrXdbHK9CF+8ywj8Amf7PBRmPCOJugH954Nnlo=
|
||||
github.com/spf13/cobra v1.9.1/go.mod h1:nDyEzZ8ogv936Cinf6g1RU9MRY64Ir93oCnqb9wxYW0=
|
||||
github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
|
||||
github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
|
||||
github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
|
||||
github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
|
||||
github.com/spiffe/go-spiffe/v2 v2.5.0 h1:N2I01KCUkv1FAjZXJMwh95KK1ZIQLYbPfhaxw8WS0hE=
|
||||
github.com/spiffe/go-spiffe/v2 v2.5.0/go.mod h1:P+NxobPc6wXhVtINNtFjNWGBTreew1GBUCwT2wPmb7g=
|
||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
|
||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
|
||||
github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
|
||||
|
|
@ -406,54 +412,54 @@ github.com/studio-b12/gowebdav v0.10.0 h1:Yewz8FFiadcGEu4hxS/AAJQlHelndqln1bns3h
|
|||
github.com/studio-b12/gowebdav v0.10.0/go.mod h1:bHA7t77X/QFExdeAnDzK6vKM34kEZAcE1OX4MfiwjkE=
|
||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
|
||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
|
||||
github.com/tklauser/go-sysconf v0.3.14 h1:g5vzr9iPFFz24v2KZXs/pvpvh8/V9Fw6vQK5ZZb78yU=
|
||||
github.com/tklauser/go-sysconf v0.3.14/go.mod h1:1ym4lWMLUOhuBOPGtRcJm7tEGX4SCYNEEEtghGG/8uY=
|
||||
github.com/tklauser/numcpus v0.9.0 h1:lmyCHtANi8aRUgkckBgoDk1nHCux3n2cgkJLXdQGPDo=
|
||||
github.com/tklauser/numcpus v0.9.0/go.mod h1:SN6Nq1O3VychhC1npsWostA+oW+VOQTxZrS604NSRyI=
|
||||
github.com/tklauser/go-sysconf v0.3.15 h1:VE89k0criAymJ/Os65CSn1IXaol+1wrsFHEB8Ol49K4=
|
||||
github.com/tklauser/go-sysconf v0.3.15/go.mod h1:Dmjwr6tYFIseJw7a3dRLJfsHAMXZ3nEnL/aZY+0IuI4=
|
||||
github.com/tklauser/numcpus v0.10.0 h1:18njr6LDBk1zuna922MgdjQuJFjrdppsZG60sHGfjso=
|
||||
github.com/tklauser/numcpus v0.10.0/go.mod h1:BiTKazU708GQTYF4mB+cmlpT2Is1gLk7XVuEeem8LsQ=
|
||||
github.com/unrolled/secure v1.17.0 h1:Io7ifFgo99Bnh0J7+Q+qcMzWM6kaDPCA5FroFZEdbWU=
|
||||
github.com/unrolled/secure v1.17.0/go.mod h1:BmF5hyM6tXczk3MpQkFf1hpKSRqCyhqcbiQtiAF7+40=
|
||||
github.com/wagslane/go-password-validator v0.3.0 h1:vfxOPzGHkz5S146HDpavl0cw1DSVP061Ry2PX0/ON6I=
|
||||
github.com/wagslane/go-password-validator v0.3.0/go.mod h1:TI1XJ6T5fRdRnHqHt14pvy1tNVnrwe7m3/f1f2fDphQ=
|
||||
github.com/wneessen/go-mail v0.5.2 h1:MZKwgHJoRboLJ+EHMLuHpZc95wo+u1xViL/4XSswDT8=
|
||||
github.com/wneessen/go-mail v0.5.2/go.mod h1:kRroJvEq2hOSEPFRiKjN7Csrz0G1w+RpiGR3b6yo+Ck=
|
||||
github.com/wneessen/go-mail v0.6.2 h1:c6V7c8D2mz868z9WJ+8zDKtUyLfZ1++uAZmo2GRFji8=
|
||||
github.com/wneessen/go-mail v0.6.2/go.mod h1:L/PYjPK3/2ZlNb2/FjEBIn9n1rUWjW+Toy531oVmeb4=
|
||||
github.com/yl2chen/cidranger v1.0.3-0.20210928021809-d1cb2c52f37a h1:XfF01GyP+0eWCaVp0y6rNN+kFp7pt9Da4UUYrJ5XPWA=
|
||||
github.com/yl2chen/cidranger v1.0.3-0.20210928021809-d1cb2c52f37a/go.mod h1:aXb8yZQEWo1XHGMf1qQfnb83GR/EJ2EBlwtUgAaNBoE=
|
||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
|
||||
github.com/yusufpapurcu/wmi v1.2.4 h1:zFUKzehAFReQwLys1b/iSMl+JQGSCSjtVqQn9bBrPo0=
|
||||
github.com/yusufpapurcu/wmi v1.2.4/go.mod h1:SBZ9tNy3G9/m5Oi98Zks0QjeHVDvuK0qfxQmPyzfmi0=
|
||||
go.etcd.io/bbolt v1.3.11 h1:yGEzV1wPz2yVCLsD8ZAiGHhHVlczyC9d1rP43/VCRJ0=
|
||||
go.etcd.io/bbolt v1.3.11/go.mod h1:dksAq7YMXoljX0xu6VF5DMZGbhYYoLUalEiSySYAS4I=
|
||||
github.com/zeebo/errs v1.4.0 h1:XNdoD/RRMKP7HD0UhJnIzUy74ISdGGxURlYG8HSWSfM=
|
||||
github.com/zeebo/errs v1.4.0/go.mod h1:sgbWHsvVuTPHcqJJGQ1WhI5KbWlHYz+2+2C/LSEtCw4=
|
||||
go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
|
||||
go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
|
||||
go.opencensus.io v0.24.0 h1:y73uSU6J157QMP2kn2r30vwW1A2W2WFwSCGnAVxeaD0=
|
||||
go.opencensus.io v0.24.0/go.mod h1:vNK8G9p7aAivkbmorf4v+7Hgx+Zs0yY+0fOtgBfjQKo=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
|
||||
go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.33.0 h1:FVPoXEoILwgbZUu4X7YSgsESsAmGRgoYcnXkzgQPhP4=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.33.0/go.mod h1:ZHrLmr4ikK2AwRj9QL+c9s2SOlgoSRyMpNVzUj2fZqI=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0 h1:PS8wXpbyaDJQ2VDHHncMe9Vct0Zn1fEjpsjrLxGJoSc=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.58.0/go.mod h1:HDBUsEjOuRC0EzKZ1bSaRGZWUBAzo+MhAcUUORSr4D0=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0 h1:yd02MEjBdJkG3uabWP9apV+OuWRIXGDuJEUJbOHmCFU=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.58.0/go.mod h1:umTcuxiv1n/s/S6/c2AT/g2CQ7u5C59sHDNmfSwgz7Q=
|
||||
go.opentelemetry.io/otel v1.33.0 h1:/FerN9bax5LoK51X/sI0SVYrjSE0/yUL7DpxW4K3FWw=
|
||||
go.opentelemetry.io/otel v1.33.0/go.mod h1:SUUkR6csvUQl+yjReHu5uM3EtVV7MBm5FHKRlNx4I8I=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0 h1:WDdP9acbMYjbKIyJUhTvtzj601sVJOqgWdUxSdR/Ysc=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.29.0/go.mod h1:BLbf7zbNIONBLPwvFnwNHGj4zge8uTCM/UPIVW1Mq2I=
|
||||
go.opentelemetry.io/otel/metric v1.33.0 h1:r+JOocAyeRVXD8lZpjdQjzMadVZp2M4WmQ+5WtEnklQ=
|
||||
go.opentelemetry.io/otel/metric v1.33.0/go.mod h1:L9+Fyctbp6HFTddIxClbQkjtubW6O9QS3Ann/M82u6M=
|
||||
go.opentelemetry.io/otel/sdk v1.33.0 h1:iax7M131HuAm9QkZotNHEfstof92xM+N8sr3uHXc2IM=
|
||||
go.opentelemetry.io/otel/sdk v1.33.0/go.mod h1:A1Q5oi7/9XaMlIWzPSxLRWOI8nG3FnzHJNbiENQuihM=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.33.0 h1:Gs5VK9/WUJhNXZgn8MR6ITatvAmKeIuCtNbsP3JkNqU=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.33.0/go.mod h1:dL5ykHZmm1B1nVRk9dDjChwDmt81MjVp3gLkQRwKf/Q=
|
||||
go.opentelemetry.io/otel/trace v1.33.0 h1:cCJuF7LRjUFso9LPnEAHJDB2pqzp+hbO8eu1qqW2d/s=
|
||||
go.opentelemetry.io/otel/trace v1.33.0/go.mod h1:uIcdVUZMpTAmz0tI1z04GoVSezK37CbGV4fr1f2nBck=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.35.0 h1:bGvFt68+KTiAKFlacHW6AhA56GF2rS0bdD3aJYEnmzA=
|
||||
go.opentelemetry.io/contrib/detectors/gcp v1.35.0/go.mod h1:qGWP8/+ILwMRIUf9uIVLloR1uo5ZYAslM4O6OqUi1DA=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0 h1:x7wzEgXfnzJcHDwStJT+mxOz4etr2EcexjqhBvmoakw=
|
||||
go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc v0.60.0/go.mod h1:rg+RlpR5dKwaS95IyyZqj5Wd4E13lk/msnTS0Xl9lJM=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0 h1:sbiXRNDSWJOTobXh5HyQKjq6wUC5tNybqjIqDpAY4CU=
|
||||
go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp v0.60.0/go.mod h1:69uWxva0WgAA/4bu2Yy70SLDBwZXuQ6PbBpbsa5iZrQ=
|
||||
go.opentelemetry.io/otel v1.35.0 h1:xKWKPxrxB6OtMCbmMY021CqC45J+3Onta9MqjhnusiQ=
|
||||
go.opentelemetry.io/otel v1.35.0/go.mod h1:UEqy8Zp11hpkUrL73gSlELM0DupHoiq72dR+Zqel/+Y=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0 h1:PB3Zrjs1sG1GBX51SXyTSoOTqcDglmsk7nT6tkKPb/k=
|
||||
go.opentelemetry.io/otel/exporters/stdout/stdoutmetric v1.35.0/go.mod h1:U2R3XyVPzn0WX7wOIypPuptulsMcPDPs/oiSVOMVnHY=
|
||||
go.opentelemetry.io/otel/metric v1.35.0 h1:0znxYu2SNyuMSQT4Y9WDWej0VpcsxkuklLa4/siN90M=
|
||||
go.opentelemetry.io/otel/metric v1.35.0/go.mod h1:nKVFgxBZ2fReX6IlyW28MgZojkoAkJGaE8CpgeAU3oE=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0 h1:iPctf8iprVySXSKJffSS79eOjl9pvxV9ZqOWT0QejKY=
|
||||
go.opentelemetry.io/otel/sdk v1.35.0/go.mod h1:+ga1bZliga3DxJ3CQGg3updiaAJoNECOgJREo9KHGQg=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0 h1:1RriWBmCKgkeHEhM7a2uMjMUfP7MsOF5JpUCaEqEI9o=
|
||||
go.opentelemetry.io/otel/sdk/metric v1.35.0/go.mod h1:is6XYCUMpcKi+ZsOvfluY5YstFnhW0BidkR+gL+qN+w=
|
||||
go.opentelemetry.io/otel/trace v1.35.0 h1:dPpEfJu1sDIqruz7BHFG3c7528f6ddfSWfFDVt/xgMs=
|
||||
go.opentelemetry.io/otel/trace v1.35.0/go.mod h1:WUk7DtFp1Aw2MkvqGdwiXYDZZNvA/1J8o6xRXLrIkyc=
|
||||
go.uber.org/automaxprocs v1.6.0 h1:O3y2/QNTOdbF+e/dpXNNW7Rx2hZ4sTIPyybbxyNqTUs=
|
||||
go.uber.org/automaxprocs v1.6.0/go.mod h1:ifeIMSnPZuznNm6jmdzmU3/bfk01Fe2fotchwEFJ8r8=
|
||||
go.uber.org/multierr v1.11.0 h1:blXXJkSxSSfBVBlC76pxqeO+LN3aDfLQo+309xJstO0=
|
||||
go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN80Y=
|
||||
gocloud.dev v0.40.0 h1:f8LgP+4WDqOG/RXoUcyLpeIAGOcAbZrZbDQCUee10ng=
|
||||
gocloud.dev v0.40.0/go.mod h1:drz+VyYNBvrMTW0KZiBAYEdl8lbNZx+OQ7oQvdrFmSQ=
|
||||
gocloud.dev v0.41.0 h1:qBKd9jZkBKEghYbP/uThpomhedK5s2Gy6Lz7h/zYYrM=
|
||||
gocloud.dev v0.41.0/go.mod h1:IetpBcWLUwroOOxKr90lhsZ8vWxeSkuszBnW62sbcf0=
|
||||
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
|
||||
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329 h1:9kj3STMvgqy3YA4VQXBrN7925ICMxD5wzMRcgA30588=
|
||||
golang.org/x/exp v0.0.0-20250103183323-7d7fa50e5329/go.mod h1:qj5a5QZpwLU2NLQudwIN5koi3beDhSAlJwa67PuM98c=
|
||||
golang.org/x/lint v0.0.0-20181026193005-c67002cb31c3/go.mod h1:UVdnD1Gm6xHRNCYTkRU2/jEulfH38KcIWyp/GAMgvoE=
|
||||
golang.org/x/lint v0.0.0-20190227174305-5b3e6a55c961/go.mod h1:wehouNa3lNwaWXcvxsM5YxQ5yQlVC4a0KAMCusXpPoU=
|
||||
golang.org/x/lint v0.0.0-20190313153728-d0100b6bd8b3/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
|
||||
|
|
@ -462,8 +468,8 @@ golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
|||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
|
||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
|
||||
golang.org/x/mod v0.22.0 h1:D4nJWe9zXqHOmWqj4VMOJhvzj7bEZg4wEYa759z1pH4=
|
||||
golang.org/x/mod v0.22.0/go.mod h1:6SkKJ3Xj0I0BrPOZoBy3bdMptDDU9oJrpohJ3eWZ1fY=
|
||||
golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
|
||||
golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
|
||||
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
golang.org/x/net v0.0.0-20190213061140-3a22650c66bd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
|
||||
|
|
@ -475,11 +481,11 @@ golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
|
|||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
|
||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
|
||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
|
||||
golang.org/x/net v0.33.0 h1:74SYHlV8BIgHIFC/LrYkOGIwL19eTYXQ5wc6TBuO36I=
|
||||
golang.org/x/net v0.33.0/go.mod h1:HXLR5J+9DxmrqMwG9qjGCxZ+zKXxBru04zlTvWlWuN4=
|
||||
golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
|
||||
golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
|
||||
golang.org/x/oauth2 v0.0.0-20180821212333-d2e6202438be/go.mod h1:N/0e6XlmueqKjAGxoOufVs8QHGRruUQn6yWY3a++T0U=
|
||||
golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
|
||||
golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
|
||||
golang.org/x/oauth2 v0.29.0 h1:WdYw2tdTK1S8olAzWHdgeqfy+Mtm9XNhv/xJsY65d98=
|
||||
golang.org/x/oauth2 v0.29.0/go.mod h1:onh5ek6nERTohokkhCD/y2cV4Do3fxFHFuAejCkRWT8=
|
||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20181108010431-42b317875d0f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
||||
|
|
@ -488,9 +494,9 @@ golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
|
|||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
|
||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.10.0 h1:3NQrjDixjgGwUOCaF8w2+VYHv0Ve/vGYSbdkTa98gmQ=
|
||||
golang.org/x/sync v0.10.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
|
||||
golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
|
||||
golang.org/x/sys v0.0.0-20180830151530-49385e6e1522/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-20190916202348-b4ddaad3f8a3/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
|
|
@ -513,16 +519,16 @@ golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
|||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.28.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.29.0 h1:TPYlXGxvx1MGTn2GiZDhnjPA9wZzZeGKHHmKhHYvgaU=
|
||||
golang.org/x/sys v0.29.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
|
||||
golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
|
||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
|
||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
|
||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
|
||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
|
||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
|
||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
|
||||
golang.org/x/term v0.27.0 h1:WP60Sv1nlK1T6SupCHbXzSaN0b9wUmsPoRS9b61A23Q=
|
||||
golang.org/x/term v0.27.0/go.mod h1:iMsnZpn0cago0GOrHO2+Y7u7JPn5AylBrcoWkElMTSM=
|
||||
golang.org/x/term v0.31.0 h1:erwDkOK1Msy6offm1mOgvspSkslFnIGsFnxOKoufg3o=
|
||||
golang.org/x/term v0.31.0/go.mod h1:R4BeIy7D95HzImkxGkTW1UQTtP54tio2RyHz7PwK0aw=
|
||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
|
||||
|
|
@ -530,11 +536,11 @@ golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
|
|||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
|
||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
|
||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/text v0.21.0 h1:zyQAAkrwaneQ066sspRyJaG9VNi/YJ1NfzcGB3hZ/qo=
|
||||
golang.org/x/text v0.21.0/go.mod h1:4IBbMaMmOPCJ8SecivzSH54+73PCFmPWxNTLm+vZkEQ=
|
||||
golang.org/x/time v0.9.0 h1:EsRrnYcQiGH+5FfbgvV4AP7qEZstoyrHB0DzarOQ4ZY=
|
||||
golang.org/x/time v0.9.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
|
||||
golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
|
||||
golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
|
||||
golang.org/x/time v0.11.0 h1:/bpjEDfN9tkoN/ryeYHnv5hcMlc8ncjMcM4XBk5NWV0=
|
||||
golang.org/x/time v0.11.0/go.mod h1:CDIdPxbZBQxdj6cxyCIdrNogrJKMJ7pr37NYpMcMDSg=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190114222345-bf090417da8b/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
golang.org/x/tools v0.0.0-20190226205152-f727befe758c/go.mod h1:9Yl7xja0Znq3iFh3HoIrodX9oNMXvdceNzlUR8zjMvY=
|
||||
|
|
@ -545,32 +551,32 @@ 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/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
|
||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
|
||||
golang.org/x/tools v0.28.0 h1:WuB6qZ4RPCQo5aP3WdKZS7i595EdWqWR8vqJTlwTVK8=
|
||||
golang.org/x/tools v0.28.0/go.mod h1:dcIOrVd3mfQKTgrDVQHqCPMWy6lnhfhtX3hLXYVLfRw=
|
||||
golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
|
||||
golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
|
||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/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-20240903120638-7835f813f4da h1:noIWHXmPHxILtqtCOPIhSt0ABwskkZKjD3bXGnZGpNY=
|
||||
golang.org/x/xerrors v0.0.0-20240903120638-7835f813f4da/go.mod h1:NDW/Ps6MPRej6fsCIbMTohpP40sJ/P/vI1MoTEGwX90=
|
||||
google.golang.org/api v0.214.0 h1:h2Gkq07OYi6kusGOaT/9rnNljuXmqPnaig7WGPmKbwA=
|
||||
google.golang.org/api v0.214.0/go.mod h1:bYPpLG8AyeMWwDU6NXoB00xC0DFkikVvd5MfwoxjLqE=
|
||||
google.golang.org/api v0.230.0 h1:2u1hni3E+UXAXrONrrkfWpi/V6cyKVAbfGVeGtC3OxM=
|
||||
google.golang.org/api v0.230.0/go.mod h1:aqvtoMk7YkiXx+6U12arQFExiRV9D/ekvMCwCd/TksQ=
|
||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
|
||||
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
|
||||
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=
|
||||
google.golang.org/genproto v0.0.0-20190819201941-24fa4b261c55/go.mod h1:DMBHOl98Agz4BDEuKkezgsaosCRResVns1a3J2ZsMNc=
|
||||
google.golang.org/genproto v0.0.0-20200526211855-cb27e3aa2013/go.mod h1:NbSheEEYHJ7i3ixzK3sjbqSGDJWnxyFXZblF3eUsNvo=
|
||||
google.golang.org/genproto v0.0.0-20250102185135-69823020774d h1:3NH+6ZtWWhXDpEJEAtzF1Gp/zA87pKkIB4gO1Ag8VSI=
|
||||
google.golang.org/genproto v0.0.0-20250102185135-69823020774d/go.mod h1:zhXVSAeuPiprFfMSrt7Jo1Uighv2Nfu3HAZrw83tcYE=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d h1:H8tOf8XM88HvKqLTxe755haY6r1fqqzLbEnfrmLXlSA=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250102185135-69823020774d/go.mod h1:2v7Z7gP2ZUOGsaFyxATQSRoBnKygqVq2Cwnvom7QiqY=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d h1:xJJRGY7TJcvIlpSrN3K6LAWgNFUILlO+OMAqtg9aqnw=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250102185135-69823020774d/go.mod h1:3ENsm/5D1mzDyhpzeRi1NR784I0BcofWBoSc5QqqMK4=
|
||||
google.golang.org/genproto v0.0.0-20250422160041-2d3770c4ea7f h1:iZiXS7qm4saaCcdK7S/i1Qx9ZHO2oa16HQqwYc1tPKY=
|
||||
google.golang.org/genproto v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:Cej/8iHf9mPl71o/a+R1rrvSFrAAVCUFX9s/sbNttBc=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f h1:tjZsroqekhC63+WMqzmWyW5Twj/ZfR5HAlpd5YQ1Vs0=
|
||||
google.golang.org/genproto/googleapis/api v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:Cd8IzgPo5Akum2c9R6FsXNaZbH3Jpa2gpHlW89FqlyQ=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f h1:N/PrbTw4kdkqNRzVfWPrBekzLuarFREcbFOiOLkXon4=
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20250422160041-2d3770c4ea7f/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
|
||||
google.golang.org/grpc v1.19.0/go.mod h1:mqu4LbDTu4XGKhr4mRzUsmM4RtVoemTSY81AxZiDr8c=
|
||||
google.golang.org/grpc v1.23.0/go.mod h1:Y5yQAOtifL1yxbo5wqy6BxZv8vAUGQwXBOALyacEbxg=
|
||||
google.golang.org/grpc v1.25.1/go.mod h1:c3i+UQWmh7LiEpx4sFZnkU36qjEYZ0imhYfXVyQciAY=
|
||||
google.golang.org/grpc v1.27.0/go.mod h1:qbnxyOmOxrQa7FizSgH+ReBfzJrCY1pSN7KXBS8abTk=
|
||||
google.golang.org/grpc v1.33.2/go.mod h1:JMHMWHQWaTccqQQlmk3MJZS+GWXOdAesneDmEnv2fbc=
|
||||
google.golang.org/grpc v1.69.2 h1:U3S9QEtbXC0bYNvRtcoklF3xGtLViumSYxWykJS+7AU=
|
||||
google.golang.org/grpc v1.69.2/go.mod h1:vyjdE6jLBI76dgpDojsFGNaHlxdjXN9ghpnd2o7JGZ4=
|
||||
google.golang.org/grpc v1.72.0 h1:S7UkcVa60b5AAQTaO6ZKamFp1zMZSU0fGDK2WZLbBnM=
|
||||
google.golang.org/grpc v1.72.0/go.mod h1:wH5Aktxcg25y1I3w7H69nHfXdOG3UiadoBtjh3izSDM=
|
||||
google.golang.org/protobuf v0.0.0-20200109180630-ec00e32a8dfd/go.mod h1:DFci5gLYBciE7Vtevhsrf46CRTquxDuWsQurQQe4oz8=
|
||||
google.golang.org/protobuf v0.0.0-20200221191635-4d8936d0db64/go.mod h1:kwYJMbMJ01Woi6D6+Kah6886xMZcty6N08ah7+eCXa0=
|
||||
google.golang.org/protobuf v0.0.0-20200228230310-ab0ca4ff8a60/go.mod h1:cfTl7dwQJ+fmap5saPgwCLgHXTUD7jkjRqWcaiX5VyM=
|
||||
|
|
@ -580,13 +586,11 @@ google.golang.org/protobuf v1.22.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2
|
|||
google.golang.org/protobuf v1.23.0/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.23.1-0.20200526195155-81db48ad09cc/go.mod h1:EGpADcykh3NcUnDUJcl1+ZksZNG86OlYog2l/sGQquU=
|
||||
google.golang.org/protobuf v1.25.0/go.mod h1:9JNX74DMeImyA3h4bdi1ymwjUzf21/xIlbajtzgsN7c=
|
||||
google.golang.org/protobuf v1.36.1 h1:yBPeRvTftaleIgM3PZ/WBIZ7XM/eEYAaEyCwvyjq/gk=
|
||||
google.golang.org/protobuf v1.36.1/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/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/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
|
||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
|
||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1 h1:bBRl1b0OH9s/DuPhuXpNl+VtCaJXFZ5/uEFST95x9zc=
|
||||
gopkg.in/natefinch/lumberjack.v2 v2.2.1/go.mod h1:YD8tP3GAjkrDg1eZH7EGmyESg/lsYskCTPBJVb9jqSc=
|
||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
|
||||
|
|
|
|||
BIN
img/reui.png
Normal file
BIN
img/reui.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 3.5 KiB |
BIN
img/servinga.png
Normal file
BIN
img/servinga.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 8.5 KiB |
BIN
img/vps2day.png
BIN
img/vps2day.png
Binary file not shown.
|
Before Width: | Height: | Size: 8 KiB |
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build bundle
|
||||
// +build bundle
|
||||
|
||||
package bundle
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/drakkan/sftpgo/v2/internal/config"
|
||||
"github.com/drakkan/sftpgo/v2/internal/dataprovider"
|
||||
"github.com/drakkan/sftpgo/v2/internal/logger"
|
||||
"github.com/drakkan/sftpgo/v2/internal/plugin"
|
||||
"github.com/drakkan/sftpgo/v2/internal/util"
|
||||
)
|
||||
|
||||
|
|
@ -56,6 +57,15 @@ renewed by the SFTPGo service
|
|||
logger.ErrorToConsole("unable to initialize KMS: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if config.HasKMSPlugin() {
|
||||
if err := plugin.Initialize(config.GetPluginsConfig(), "debug"); err != nil {
|
||||
logger.ErrorToConsole("unable to initialize plugin system: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
registerSignals()
|
||||
defer plugin.Handler.Cleanup()
|
||||
}
|
||||
|
||||
mfaConfig := config.GetMFAConfig()
|
||||
err = mfaConfig.Initialize()
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build awscontainer
|
||||
// +build awscontainer
|
||||
|
||||
package cmd
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !awscontainer
|
||||
// +build !awscontainer
|
||||
|
||||
package cmd
|
||||
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/drakkan/sftpgo/v2/internal/config"
|
||||
"github.com/drakkan/sftpgo/v2/internal/dataprovider"
|
||||
"github.com/drakkan/sftpgo/v2/internal/logger"
|
||||
"github.com/drakkan/sftpgo/v2/internal/plugin"
|
||||
"github.com/drakkan/sftpgo/v2/internal/service"
|
||||
"github.com/drakkan/sftpgo/v2/internal/util"
|
||||
)
|
||||
|
|
@ -65,6 +66,15 @@ Please take a look at the usage below to customize the options.`,
|
|||
logger.ErrorToConsole("Unable to initialize KMS: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if config.HasKMSPlugin() {
|
||||
if err := plugin.Initialize(config.GetPluginsConfig(), "debug"); err != nil {
|
||||
logger.ErrorToConsole("unable to initialize plugin system: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
registerSignals()
|
||||
defer plugin.Handler.Cleanup()
|
||||
}
|
||||
|
||||
mfaConfig := config.GetMFAConfig()
|
||||
err = mfaConfig.Initialize()
|
||||
if err != nil {
|
||||
|
|
@ -78,11 +88,12 @@ Please take a look at the usage below to customize the options.`,
|
|||
providerConf.Actions.ExecuteOn = nil
|
||||
logger.InfoToConsole("Initializing provider: %q config file: %q", providerConf.Driver, viper.ConfigFileUsed())
|
||||
err = dataprovider.InitializeDatabase(providerConf, configDir)
|
||||
if err == nil {
|
||||
switch err {
|
||||
case nil:
|
||||
logger.InfoToConsole("Data provider successfully initialized/updated")
|
||||
} else if err == dataprovider.ErrNoInitRequired {
|
||||
case dataprovider.ErrNoInitRequired:
|
||||
logger.InfoToConsole("%v", err.Error())
|
||||
} else {
|
||||
default:
|
||||
logger.ErrorToConsole("Unable to initialize/update the data provider: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !noportable
|
||||
// +build !noportable
|
||||
|
||||
package cmd
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build noportable
|
||||
// +build noportable
|
||||
|
||||
package cmd
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"github.com/drakkan/sftpgo/v2/internal/config"
|
||||
"github.com/drakkan/sftpgo/v2/internal/dataprovider"
|
||||
"github.com/drakkan/sftpgo/v2/internal/logger"
|
||||
"github.com/drakkan/sftpgo/v2/internal/plugin"
|
||||
"github.com/drakkan/sftpgo/v2/internal/util"
|
||||
)
|
||||
|
||||
|
|
@ -58,6 +59,15 @@ Please take a look at the usage below to customize the options.`,
|
|||
logger.ErrorToConsole("unable to initialize KMS: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if config.HasKMSPlugin() {
|
||||
if err := plugin.Initialize(config.GetPluginsConfig(), "debug"); err != nil {
|
||||
logger.ErrorToConsole("unable to initialize plugin system: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
registerSignals()
|
||||
defer plugin.Handler.Cleanup()
|
||||
}
|
||||
|
||||
mfaConfig := config.GetMFAConfig()
|
||||
err = mfaConfig.Initialize()
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"github.com/drakkan/sftpgo/v2/internal/config"
|
||||
"github.com/drakkan/sftpgo/v2/internal/dataprovider"
|
||||
"github.com/drakkan/sftpgo/v2/internal/logger"
|
||||
"github.com/drakkan/sftpgo/v2/internal/plugin"
|
||||
"github.com/drakkan/sftpgo/v2/internal/util"
|
||||
)
|
||||
|
||||
|
|
@ -56,6 +57,21 @@ Please take a look at the usage below to customize the options.`,
|
|||
logger.ErrorToConsole("unable to initialize KMS: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if config.HasKMSPlugin() {
|
||||
if err := plugin.Initialize(config.GetPluginsConfig(), "debug"); err != nil {
|
||||
logger.ErrorToConsole("unable to initialize plugin system: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
registerSignals()
|
||||
defer plugin.Handler.Cleanup()
|
||||
}
|
||||
|
||||
mfaConfig := config.GetMFAConfig()
|
||||
err = mfaConfig.Initialize()
|
||||
if err != nil {
|
||||
logger.ErrorToConsole("Unable to initialize MFA: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
providerConf := config.GetProviderConf()
|
||||
logger.InfoToConsole("Reverting provider: %q config file: %q target version %d", providerConf.Driver,
|
||||
viper.ConfigFileUsed(), revertProviderTargetVersion)
|
||||
|
|
|
|||
41
internal/cmd/signals_unix.go
Normal file
41
internal/cmd/signals_unix.go
Normal file
|
|
@ -0,0 +1,41 @@
|
|||
// Copyright (C) 2025 Nicola Murino
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !windows
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
"syscall"
|
||||
|
||||
"github.com/drakkan/sftpgo/v2/internal/logger"
|
||||
"github.com/drakkan/sftpgo/v2/internal/plugin"
|
||||
)
|
||||
|
||||
func registerSignals() {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, syscall.SIGINT, syscall.SIGTERM)
|
||||
go func() {
|
||||
for sig := range c {
|
||||
switch sig {
|
||||
case syscall.SIGINT, syscall.SIGTERM:
|
||||
logger.DebugToConsole("Received interrupt request")
|
||||
plugin.Handler.Cleanup()
|
||||
os.Exit(0)
|
||||
}
|
||||
}
|
||||
}()
|
||||
}
|
||||
36
internal/cmd/signals_windows.go
Normal file
36
internal/cmd/signals_windows.go
Normal file
|
|
@ -0,0 +1,36 @@
|
|||
// Copyright (C) 2025 Nicola Murino
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"os"
|
||||
"os/signal"
|
||||
|
||||
"github.com/drakkan/sftpgo/v2/internal/logger"
|
||||
"github.com/drakkan/sftpgo/v2/internal/plugin"
|
||||
)
|
||||
|
||||
func registerSignals() {
|
||||
c := make(chan os.Signal, 1)
|
||||
signal.Notify(c, os.Interrupt)
|
||||
|
||||
go func() {
|
||||
for range c {
|
||||
logger.DebugToConsole("Received interrupt request")
|
||||
plugin.Handler.Cleanup()
|
||||
os.Exit(0)
|
||||
}
|
||||
}()
|
||||
}
|
||||
|
|
@ -1,227 +0,0 @@
|
|||
// Copyright (C) 2019 Nicola Murino
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
package cmd
|
||||
|
||||
import (
|
||||
"io"
|
||||
"os"
|
||||
"os/user"
|
||||
"path/filepath"
|
||||
|
||||
"github.com/rs/xid"
|
||||
"github.com/rs/zerolog"
|
||||
"github.com/spf13/cobra"
|
||||
"github.com/spf13/viper"
|
||||
|
||||
"github.com/drakkan/sftpgo/v2/internal/common"
|
||||
"github.com/drakkan/sftpgo/v2/internal/config"
|
||||
"github.com/drakkan/sftpgo/v2/internal/dataprovider"
|
||||
"github.com/drakkan/sftpgo/v2/internal/logger"
|
||||
"github.com/drakkan/sftpgo/v2/internal/plugin"
|
||||
"github.com/drakkan/sftpgo/v2/internal/sftpd"
|
||||
"github.com/drakkan/sftpgo/v2/internal/version"
|
||||
)
|
||||
|
||||
var (
|
||||
logJournalD = false
|
||||
preserveHomeDir = false
|
||||
baseHomeDir = ""
|
||||
subsystemCmd = &cobra.Command{
|
||||
Use: "startsubsys",
|
||||
Short: "Use sftpgo as SFTP file transfer subsystem",
|
||||
Long: `In this mode SFTPGo speaks the server side of SFTP protocol to stdout and
|
||||
expects client requests from stdin.
|
||||
This mode is not intended to be called directly, but from sshd using the
|
||||
Subsystem option.
|
||||
For example adding a line like this one in "/etc/ssh/sshd_config":
|
||||
|
||||
Subsystem sftp sftpgo startsubsys
|
||||
|
||||
Command-line flags should be specified in the Subsystem declaration.
|
||||
`,
|
||||
Run: func(_ *cobra.Command, _ []string) {
|
||||
logSender := "startsubsys"
|
||||
connectionID := xid.New().String()
|
||||
var zeroLogLevel zerolog.Level
|
||||
switch logLevel {
|
||||
case "info":
|
||||
zeroLogLevel = zerolog.InfoLevel
|
||||
case "warn":
|
||||
zeroLogLevel = zerolog.WarnLevel
|
||||
case "error":
|
||||
zeroLogLevel = zerolog.ErrorLevel
|
||||
default:
|
||||
zeroLogLevel = zerolog.DebugLevel
|
||||
}
|
||||
logger.SetLogTime(logUTCTime)
|
||||
if logJournalD {
|
||||
logger.InitJournalDLogger(zeroLogLevel)
|
||||
} else {
|
||||
logger.InitStdErrLogger(zeroLogLevel)
|
||||
}
|
||||
osUser, err := user.Current()
|
||||
if err != nil {
|
||||
logger.Error(logSender, connectionID, "unable to get the current user: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
username := osUser.Username
|
||||
homedir := osUser.HomeDir
|
||||
logger.Info(logSender, connectionID, "starting SFTPGo %v as subsystem, user %q home dir %q config dir %q base home dir %q",
|
||||
version.Get(), username, homedir, configDir, baseHomeDir)
|
||||
err = config.LoadConfig(configDir, configFile)
|
||||
if err != nil {
|
||||
logger.Error(logSender, connectionID, "unable to load configuration: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
kmsConfig := config.GetKMSConfig()
|
||||
if err := kmsConfig.Initialize(); err != nil {
|
||||
logger.Error(logSender, connectionID, "unable to initialize KMS: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
if err := plugin.Initialize(config.GetPluginsConfig(), logLevel); err != nil {
|
||||
logger.Error(logSender, connectionID, "unable to initialize plugin system: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
mfaConfig := config.GetMFAConfig()
|
||||
err = mfaConfig.Initialize()
|
||||
if err != nil {
|
||||
logger.Error(logSender, "", "unable to initialize MFA: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
dataProviderConf := config.GetProviderConf()
|
||||
if dataProviderConf.Driver == dataprovider.SQLiteDataProviderName || dataProviderConf.Driver == dataprovider.BoltDataProviderName {
|
||||
logger.Debug(logSender, connectionID, "data provider %q not supported in subsystem mode, using %q provider",
|
||||
dataProviderConf.Driver, dataprovider.MemoryDataProviderName)
|
||||
dataProviderConf.Driver = dataprovider.MemoryDataProviderName
|
||||
dataProviderConf.Name = ""
|
||||
}
|
||||
config.SetProviderConf(dataProviderConf)
|
||||
err = dataprovider.Initialize(dataProviderConf, configDir, false)
|
||||
if err != nil {
|
||||
logger.Error(logSender, connectionID, "unable to initialize the data provider: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
smtpConfig := config.GetSMTPConfig()
|
||||
err = smtpConfig.Initialize(configDir, false)
|
||||
if err != nil {
|
||||
logger.Error(logSender, connectionID, "unable to initialize SMTP configuration: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
commonConfig := config.GetCommonConfig()
|
||||
// idle connection are managed externally
|
||||
commonConfig.IdleTimeout = 0
|
||||
config.SetCommonConfig(commonConfig)
|
||||
if err := common.Initialize(config.GetCommonConfig(), dataProviderConf.GetShared()); err != nil {
|
||||
logger.Error(logSender, connectionID, "%v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
httpConfig := config.GetHTTPConfig()
|
||||
if err := httpConfig.Initialize(configDir); err != nil {
|
||||
logger.Error(logSender, connectionID, "unable to initialize http client: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
commandConfig := config.GetCommandConfig()
|
||||
if err := commandConfig.Initialize(); err != nil {
|
||||
logger.Error(logSender, connectionID, "unable to initialize commands configuration: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
user, err := dataprovider.UserExists(username, "")
|
||||
if err == nil {
|
||||
if user.HomeDir != filepath.Clean(homedir) && !preserveHomeDir {
|
||||
// update the user
|
||||
user.HomeDir = filepath.Clean(homedir)
|
||||
err = dataprovider.UpdateUser(&user, dataprovider.ActionExecutorSystem, "", "")
|
||||
if err != nil {
|
||||
logger.Error(logSender, connectionID, "unable to update user %q: %v", username, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
user.Username = username
|
||||
if baseHomeDir != "" && filepath.IsAbs(baseHomeDir) {
|
||||
user.HomeDir = filepath.Join(baseHomeDir, username)
|
||||
} else {
|
||||
user.HomeDir = filepath.Clean(homedir)
|
||||
}
|
||||
logger.Debug(logSender, connectionID, "home dir for new user %q", user.HomeDir)
|
||||
user.Password = connectionID
|
||||
user.Permissions = make(map[string][]string)
|
||||
user.Permissions["/"] = []string{dataprovider.PermAny}
|
||||
err = dataprovider.AddUser(&user, dataprovider.ActionExecutorSystem, "", "")
|
||||
if err != nil {
|
||||
logger.Error(logSender, connectionID, "unable to add user %q: %v", username, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
}
|
||||
err = user.LoadAndApplyGroupSettings()
|
||||
if err != nil {
|
||||
logger.Error(logSender, connectionID, "unable to apply group settings for user %q: %v", username, err)
|
||||
os.Exit(1)
|
||||
}
|
||||
err = sftpd.ServeSubSystemConnection(&user, connectionID, os.Stdin, os.Stdout)
|
||||
if err != nil && err != io.EOF {
|
||||
logger.Warn(logSender, connectionID, "serving subsystem finished with error: %v", err)
|
||||
os.Exit(1)
|
||||
}
|
||||
logger.Info(logSender, connectionID, "serving subsystem finished")
|
||||
plugin.Handler.Cleanup()
|
||||
os.Exit(0)
|
||||
},
|
||||
}
|
||||
)
|
||||
|
||||
func init() {
|
||||
subsystemCmd.Flags().BoolVarP(&preserveHomeDir, "preserve-home", "p", false, `If the user already exists, the existing home
|
||||
directory will not be changed`)
|
||||
subsystemCmd.Flags().StringVarP(&baseHomeDir, "base-home-dir", "d", "", `If the user does not exist specify an alternate
|
||||
starting directory. The home directory for a new
|
||||
user will be:
|
||||
|
||||
[base-home-dir]/[username]
|
||||
|
||||
base-home-dir must be an absolute path.`)
|
||||
subsystemCmd.Flags().BoolVarP(&logJournalD, "log-to-journald", "j", false, `Send logs to journald. Only available on Linux.
|
||||
Use:
|
||||
|
||||
$ journalctl -o verbose -f
|
||||
|
||||
To see full logs.
|
||||
If not set, the logs will be sent to the standard
|
||||
error`)
|
||||
|
||||
addConfigFlags(subsystemCmd)
|
||||
|
||||
viper.SetDefault(logLevelKey, defaultLogLevel)
|
||||
viper.BindEnv(logLevelKey, "SFTPGO_LOG_LEVEL") //nolint:errcheck
|
||||
subsystemCmd.Flags().StringVar(&logLevel, logLevelFlag, viper.GetString(logLevelKey),
|
||||
`Set the log level. Supported values:
|
||||
|
||||
debug, info, warn, error.
|
||||
|
||||
This flag can be set
|
||||
using SFTPGO_LOG_LEVEL env var too.
|
||||
`)
|
||||
viper.BindPFlag(logLevelKey, subsystemCmd.Flags().Lookup(logLevelFlag)) //nolint:errcheck
|
||||
|
||||
viper.SetDefault(logUTCTimeKey, defaultLogUTCTime)
|
||||
viper.BindEnv(logUTCTimeKey, "SFTPGO_LOG_UTC_TIME") //nolint:errcheck
|
||||
subsystemCmd.Flags().BoolVar(&logUTCTime, logUTCTimeFlag, viper.GetBool(logUTCTimeKey),
|
||||
`Use UTC time for logging. This flag can be set
|
||||
using SFTPGO_LOG_UTC_TIME env var too.
|
||||
`)
|
||||
viper.BindPFlag(logUTCTimeKey, subsystemCmd.Flags().Lookup(logUTCTimeFlag)) //nolint:errcheck
|
||||
|
||||
rootCmd.AddCommand(subsystemCmd)
|
||||
}
|
||||
|
|
@ -19,6 +19,7 @@ import (
|
|||
"context"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
|
@ -899,12 +900,12 @@ func getProxyPolicy(allowed, skipped []func(net.IP) bool, def proxyproto.Policy)
|
|||
// Each SSH connection can open several channels for SFTP or SSH commands
|
||||
type SSHConnection struct {
|
||||
id string
|
||||
conn net.Conn
|
||||
conn io.Closer
|
||||
lastActivity atomic.Int64
|
||||
}
|
||||
|
||||
// NewSSHConnection returns a new SSHConnection
|
||||
func NewSSHConnection(id string, conn net.Conn) *SSHConnection {
|
||||
func NewSSHConnection(id string, conn io.Closer) *SSHConnection {
|
||||
c := &SSHConnection{
|
||||
id: id,
|
||||
conn: conn,
|
||||
|
|
|
|||
|
|
@ -64,7 +64,7 @@ func (c *fakeConnection) AddUser(user dataprovider.User) error {
|
|||
if err != nil {
|
||||
return err
|
||||
}
|
||||
c.BaseConnection.User = user
|
||||
c.User = user
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
@ -999,9 +999,10 @@ func TestConnectionStatus(t *testing.T) {
|
|||
assert.Len(t, stats, 3)
|
||||
for _, stat := range stats {
|
||||
assert.Equal(t, stat.Username, username)
|
||||
if stat.ConnectionID == "SFTP_id1" {
|
||||
switch stat.ConnectionID {
|
||||
case "SFTP_id1":
|
||||
assert.Len(t, stat.Transfers, 2)
|
||||
} else if stat.ConnectionID == "DAV_id3" {
|
||||
case "DAV_id3":
|
||||
assert.Len(t, stat.Transfers, 1)
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -771,10 +771,7 @@ func (c *BaseConnection) Copy(virtualSourcePath, virtualTargetPath string) error
|
|||
return err
|
||||
}
|
||||
}
|
||||
createTargetDir := true
|
||||
if dstInfo != nil && dstInfo.IsDir() {
|
||||
createTargetDir = false
|
||||
}
|
||||
createTargetDir := dstInfo == nil || !dstInfo.IsDir()
|
||||
if err := c.checkCopy(srcInfo, dstInfo, virtualSourcePath, destPath); err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -62,7 +62,7 @@ func (d *dbDefender) GetHost(ip string) (dataprovider.DefenderEntry, error) {
|
|||
// and increase ban time if the IP is found.
|
||||
// This method must be called as soon as the client connects
|
||||
func (d *dbDefender) IsBanned(ip, protocol string) bool {
|
||||
if d.baseDefender.isBanned(ip, protocol) {
|
||||
if d.isBanned(ip, protocol) {
|
||||
return true
|
||||
}
|
||||
|
||||
|
|
@ -95,15 +95,15 @@ func (d *dbDefender) AddEvent(ip, protocol string, event HostEvent) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
score := d.baseDefender.getScore(event)
|
||||
score := d.getScore(event)
|
||||
|
||||
host, err := dataprovider.AddDefenderEvent(ip, score, d.getStartObservationTime())
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
d.baseDefender.logEvent(ip, protocol, event, host.Score)
|
||||
d.logEvent(ip, protocol, event, host.Score)
|
||||
if host.Score > d.config.Threshold {
|
||||
d.baseDefender.logBan(ip, protocol)
|
||||
d.logBan(ip, protocol)
|
||||
banTime := time.Now().Add(time.Duration(d.config.BanTime) * time.Minute)
|
||||
err = dataprovider.SetDefenderBanTime(ip, util.GetTimeAsMsSinceEpoch(banTime))
|
||||
if err == nil {
|
||||
|
|
|
|||
|
|
@ -148,7 +148,7 @@ func (d *memoryDefender) IsBanned(ip, protocol string) bool {
|
|||
|
||||
defer d.RUnlock()
|
||||
|
||||
return d.baseDefender.isBanned(ip, protocol)
|
||||
return d.isBanned(ip, protocol)
|
||||
}
|
||||
|
||||
// DeleteHost removes the specified IP from the defender lists
|
||||
|
|
@ -188,7 +188,7 @@ func (d *memoryDefender) AddEvent(ip, protocol string, event HostEvent) bool {
|
|||
delete(d.banned, ip)
|
||||
}
|
||||
|
||||
score := d.baseDefender.getScore(event)
|
||||
score := d.getScore(event)
|
||||
|
||||
ev := hostEvent{
|
||||
dateTime: time.Now(),
|
||||
|
|
@ -207,11 +207,11 @@ func (d *memoryDefender) AddEvent(ip, protocol string, event HostEvent) bool {
|
|||
idx++
|
||||
}
|
||||
}
|
||||
d.baseDefender.logEvent(ip, protocol, event, hs.TotalScore)
|
||||
d.logEvent(ip, protocol, event, hs.TotalScore)
|
||||
|
||||
hs.Events = hs.Events[:idx]
|
||||
if hs.TotalScore >= d.config.Threshold {
|
||||
d.baseDefender.logBan(ip, protocol)
|
||||
d.logBan(ip, protocol)
|
||||
d.banned[ip] = time.Now().Add(time.Duration(d.config.BanTime) * time.Minute)
|
||||
delete(d.hosts, ip)
|
||||
d.cleanupBanned()
|
||||
|
|
@ -225,7 +225,7 @@ func (d *memoryDefender) AddEvent(ip, protocol string, event HostEvent) bool {
|
|||
d.hosts[ip] = hs
|
||||
}
|
||||
} else {
|
||||
d.baseDefender.logEvent(ip, protocol, event, ev.score)
|
||||
d.logEvent(ip, protocol, event, ev.score)
|
||||
d.hosts[ip] = hostScore{
|
||||
TotalScore: ev.score,
|
||||
Events: []hostEvent{ev},
|
||||
|
|
|
|||
|
|
@ -21,6 +21,7 @@ import (
|
|||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"html"
|
||||
"io"
|
||||
"mime"
|
||||
"mime/multipart"
|
||||
|
|
@ -56,8 +57,8 @@ import (
|
|||
const (
|
||||
ipBlockedEventName = "IP Blocked"
|
||||
maxAttachmentsSize = int64(10 * 1024 * 1024)
|
||||
objDataPlaceholder = "{{ObjectData}}"
|
||||
objDataPlaceholderString = "{{ObjectDataString}}"
|
||||
objDataPlaceholder = "{{.ObjectData}}"
|
||||
objDataPlaceholderString = "{{.ObjectDataString}}"
|
||||
dateTimeMillisFormat = "2006-01-02T15:04:05.000"
|
||||
)
|
||||
|
||||
|
|
@ -775,55 +776,70 @@ func (p *EventParams) getRetentionReportsAsMailAttachment() (*mail.File, error)
|
|||
}, nil
|
||||
}
|
||||
|
||||
func (*EventParams) getStringReplacement(val string, jsonEscaped bool) string {
|
||||
if jsonEscaped {
|
||||
func (*EventParams) getStringReplacement(val string, escapeMode int) string {
|
||||
switch escapeMode {
|
||||
case 1:
|
||||
return util.JSONEscape(val)
|
||||
case 2:
|
||||
return html.EscapeString(val)
|
||||
default:
|
||||
return val
|
||||
}
|
||||
return val
|
||||
}
|
||||
|
||||
func (p *EventParams) getStringReplacements(addObjectData, jsonEscaped bool) []string {
|
||||
func (p *EventParams) getStringReplacements(addObjectData bool, escapeMode int) []string {
|
||||
var dateTimeString string
|
||||
if Config.TZ == "local" {
|
||||
dateTimeString = p.Timestamp.Local().Format(dateTimeMillisFormat)
|
||||
} else {
|
||||
dateTimeString = p.Timestamp.UTC().Format(dateTimeMillisFormat)
|
||||
}
|
||||
year := dateTimeString[0:4]
|
||||
month := dateTimeString[5:7]
|
||||
day := dateTimeString[8:10]
|
||||
hour := dateTimeString[11:13]
|
||||
minute := dateTimeString[14:16]
|
||||
|
||||
replacements := []string{
|
||||
"{{Name}}", p.getStringReplacement(p.Name, jsonEscaped),
|
||||
"{{Event}}", p.Event,
|
||||
"{{Status}}", fmt.Sprintf("%d", p.Status),
|
||||
"{{VirtualPath}}", p.getStringReplacement(p.VirtualPath, jsonEscaped),
|
||||
"{{EscapedVirtualPath}}", p.getStringReplacement(url.QueryEscape(p.VirtualPath), jsonEscaped),
|
||||
"{{FsPath}}", p.getStringReplacement(p.FsPath, jsonEscaped),
|
||||
"{{VirtualTargetPath}}", p.getStringReplacement(p.VirtualTargetPath, jsonEscaped),
|
||||
"{{FsTargetPath}}", p.getStringReplacement(p.FsTargetPath, jsonEscaped),
|
||||
"{{ObjectName}}", p.getStringReplacement(p.ObjectName, jsonEscaped),
|
||||
"{{ObjectBaseName}}", p.getStringReplacement(strings.TrimSuffix(p.ObjectName, p.Extension), jsonEscaped),
|
||||
"{{ObjectType}}", p.ObjectType,
|
||||
"{{FileSize}}", strconv.FormatInt(p.FileSize, 10),
|
||||
"{{Elapsed}}", strconv.FormatInt(p.Elapsed, 10),
|
||||
"{{Protocol}}", p.Protocol,
|
||||
"{{IP}}", p.IP,
|
||||
"{{Role}}", p.getStringReplacement(p.Role, jsonEscaped),
|
||||
"{{Email}}", p.getStringReplacement(p.Email, jsonEscaped),
|
||||
"{{Timestamp}}", strconv.FormatInt(p.Timestamp.UnixNano(), 10),
|
||||
"{{DateTime}}", dateTimeString,
|
||||
"{{StatusString}}", p.getStatusString(),
|
||||
"{{UID}}", p.getStringReplacement(p.UID, jsonEscaped),
|
||||
"{{Ext}}", p.getStringReplacement(p.Extension, jsonEscaped),
|
||||
"{{.Name}}", p.getStringReplacement(p.Name, escapeMode),
|
||||
"{{.Event}}", p.Event,
|
||||
"{{.Status}}", fmt.Sprintf("%d", p.Status),
|
||||
"{{.VirtualPath}}", p.getStringReplacement(p.VirtualPath, escapeMode),
|
||||
"{{.EscapedVirtualPath}}", p.getStringReplacement(url.QueryEscape(p.VirtualPath), escapeMode),
|
||||
"{{.FsPath}}", p.getStringReplacement(p.FsPath, escapeMode),
|
||||
"{{.VirtualTargetPath}}", p.getStringReplacement(p.VirtualTargetPath, escapeMode),
|
||||
"{{.FsTargetPath}}", p.getStringReplacement(p.FsTargetPath, escapeMode),
|
||||
"{{.ObjectName}}", p.getStringReplacement(p.ObjectName, escapeMode),
|
||||
"{{.ObjectBaseName}}", p.getStringReplacement(strings.TrimSuffix(p.ObjectName, p.Extension), escapeMode),
|
||||
"{{.ObjectType}}", p.ObjectType,
|
||||
"{{.FileSize}}", strconv.FormatInt(p.FileSize, 10),
|
||||
"{{.Elapsed}}", strconv.FormatInt(p.Elapsed, 10),
|
||||
"{{.Protocol}}", p.Protocol,
|
||||
"{{.IP}}", p.IP,
|
||||
"{{.Role}}", p.getStringReplacement(p.Role, escapeMode),
|
||||
"{{.Email}}", p.getStringReplacement(p.Email, escapeMode),
|
||||
"{{.Timestamp}}", strconv.FormatInt(p.Timestamp.UnixNano(), 10),
|
||||
"{{.DateTime}}", dateTimeString,
|
||||
"{{.Year}}", year,
|
||||
"{{.Month}}", month,
|
||||
"{{.Day}}", day,
|
||||
"{{.Hour}}", hour,
|
||||
"{{.Minute}}", minute,
|
||||
"{{.StatusString}}", p.getStatusString(),
|
||||
"{{.UID}}", p.getStringReplacement(p.UID, escapeMode),
|
||||
"{{.Ext}}", p.getStringReplacement(p.Extension, escapeMode),
|
||||
}
|
||||
if p.VirtualPath != "" {
|
||||
replacements = append(replacements, "{{VirtualDirPath}}", p.getStringReplacement(path.Dir(p.VirtualPath), jsonEscaped))
|
||||
replacements = append(replacements, "{{.VirtualDirPath}}", p.getStringReplacement(path.Dir(p.VirtualPath), escapeMode))
|
||||
}
|
||||
if p.VirtualTargetPath != "" {
|
||||
replacements = append(replacements, "{{VirtualTargetDirPath}}", p.getStringReplacement(path.Dir(p.VirtualTargetPath), jsonEscaped))
|
||||
replacements = append(replacements, "{{TargetName}}", p.getStringReplacement(path.Base(p.VirtualTargetPath), jsonEscaped))
|
||||
replacements = append(replacements, "{{.VirtualTargetDirPath}}", p.getStringReplacement(path.Dir(p.VirtualTargetPath), escapeMode))
|
||||
replacements = append(replacements, "{{.TargetName}}", p.getStringReplacement(path.Base(p.VirtualTargetPath), escapeMode))
|
||||
}
|
||||
if len(p.errors) > 0 {
|
||||
replacements = append(replacements, "{{ErrorString}}", p.getStringReplacement(strings.Join(p.errors, ", "), jsonEscaped))
|
||||
replacements = append(replacements, "{{.ErrorString}}", p.getStringReplacement(strings.Join(p.errors, ", "), escapeMode))
|
||||
} else {
|
||||
replacements = append(replacements, "{{ErrorString}}", "")
|
||||
replacements = append(replacements, "{{.ErrorString}}", "")
|
||||
}
|
||||
replacements = append(replacements, objDataPlaceholder, "{}")
|
||||
replacements = append(replacements, objDataPlaceholderString, "")
|
||||
|
|
@ -831,23 +847,23 @@ func (p *EventParams) getStringReplacements(addObjectData, jsonEscaped bool) []s
|
|||
data, err := p.Object.RenderAsJSON(p.Event != operationDelete)
|
||||
if err == nil {
|
||||
dataString := util.BytesToString(data)
|
||||
replacements[len(replacements)-3] = p.getStringReplacement(dataString, false)
|
||||
replacements[len(replacements)-1] = p.getStringReplacement(dataString, true)
|
||||
replacements[len(replacements)-3] = p.getStringReplacement(dataString, 0)
|
||||
replacements[len(replacements)-1] = p.getStringReplacement(dataString, 1)
|
||||
}
|
||||
}
|
||||
if p.IDPCustomFields != nil {
|
||||
for k, v := range *p.IDPCustomFields {
|
||||
replacements = append(replacements, fmt.Sprintf("{{IDPField%s}}", k), p.getStringReplacement(v, jsonEscaped))
|
||||
replacements = append(replacements, fmt.Sprintf("{{.IDPField%s}}", k), p.getStringReplacement(v, escapeMode))
|
||||
}
|
||||
}
|
||||
replacements = append(replacements, "{{Metadata}}", "{}")
|
||||
replacements = append(replacements, "{{MetadataString}}", "")
|
||||
replacements = append(replacements, "{{.Metadata}}", "{}")
|
||||
replacements = append(replacements, "{{.MetadataString}}", "")
|
||||
if len(p.Metadata) > 0 {
|
||||
data, err := json.Marshal(p.Metadata)
|
||||
if err == nil {
|
||||
dataString := util.BytesToString(data)
|
||||
replacements[len(replacements)-3] = p.getStringReplacement(dataString, false)
|
||||
replacements[len(replacements)-1] = p.getStringReplacement(dataString, true)
|
||||
replacements[len(replacements)-3] = p.getStringReplacement(dataString, 0)
|
||||
replacements[len(replacements)-1] = p.getStringReplacement(dataString, 1)
|
||||
}
|
||||
}
|
||||
return replacements
|
||||
|
|
@ -1182,7 +1198,7 @@ func getMailAttachments(conn *BaseConnection, attachments []string, replacer *st
|
|||
}
|
||||
|
||||
func replaceWithReplacer(input string, replacer *strings.Replacer) string {
|
||||
if !strings.Contains(input, "{{") {
|
||||
if !strings.Contains(input, "{{.") {
|
||||
return input
|
||||
}
|
||||
return replacer.Replace(input)
|
||||
|
|
@ -1269,7 +1285,7 @@ func getHTTPRuleActionEndpoint(c *dataprovider.EventActionHTTPConfig, replacer *
|
|||
if err != nil {
|
||||
return "", fmt.Errorf("invalid endpoint: %w", err)
|
||||
}
|
||||
if strings.Contains(u.Path, "{{") {
|
||||
if strings.Contains(u.Path, "{{.") {
|
||||
pathComponents := strings.Split(u.Path, "/")
|
||||
for idx := range pathComponents {
|
||||
part := replaceWithReplacer(pathComponents[idx], replacer)
|
||||
|
|
@ -1303,7 +1319,7 @@ func writeHTTPPart(m *multipart.Writer, part dataprovider.HTTPPart, h textproto.
|
|||
if part.Body != "" {
|
||||
cType := h.Get("Content-Type")
|
||||
if strings.Contains(strings.ToLower(cType), "application/json") {
|
||||
replacements := params.getStringReplacements(addObjectData, true)
|
||||
replacements := params.getStringReplacements(addObjectData, 1)
|
||||
jsonReplacer := strings.NewReplacer(replacements...)
|
||||
_, err = partWriter.Write(util.StringToBytes(replaceWithReplacer(part.Body, jsonReplacer)))
|
||||
} else {
|
||||
|
|
@ -1351,7 +1367,7 @@ func getHTTPRuleActionBody(c *dataprovider.EventActionHTTPConfig, replacer *stri
|
|||
return bytes.NewBuffer(data), "", nil
|
||||
}
|
||||
if c.HasJSONBody() {
|
||||
replacements := params.getStringReplacements(addObjectData, true)
|
||||
replacements := params.getStringReplacements(addObjectData, 1)
|
||||
jsonReplacer := strings.NewReplacer(replacements...)
|
||||
return bytes.NewBufferString(replaceWithReplacer(c.Body, jsonReplacer)), "", nil
|
||||
}
|
||||
|
|
@ -1439,7 +1455,7 @@ func executeHTTPRuleAction(c dataprovider.EventActionHTTPConfig, params *EventPa
|
|||
addObjectData = c.HasObjectData()
|
||||
}
|
||||
|
||||
replacements := params.getStringReplacements(addObjectData, false)
|
||||
replacements := params.getStringReplacements(addObjectData, 0)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
endpoint, err := getHTTPRuleActionEndpoint(&c, replacer)
|
||||
if err != nil {
|
||||
|
|
@ -1510,7 +1526,7 @@ func executeCommandRuleAction(c dataprovider.EventActionCommandConfig, params *E
|
|||
}
|
||||
}
|
||||
}
|
||||
replacements := params.getStringReplacements(addObjectData, false)
|
||||
replacements := params.getStringReplacements(addObjectData, 0)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
|
||||
args := make([]string, 0, len(c.Args))
|
||||
|
|
@ -1524,7 +1540,7 @@ func executeCommandRuleAction(c dataprovider.EventActionCommandConfig, params *E
|
|||
cmd := exec.CommandContext(ctx, c.Cmd, args...)
|
||||
cmd.Env = []string{}
|
||||
for _, keyVal := range c.EnvVars {
|
||||
if keyVal.Value == "$" {
|
||||
if keyVal.Value == "$" && !strings.HasPrefix(strings.ToUpper(keyVal.Key), "SFTPGO_") {
|
||||
val := os.Getenv(keyVal.Key)
|
||||
if val == "" {
|
||||
eventManagerLog(logger.LevelDebug, "empty value for environment variable %q", keyVal.Key)
|
||||
|
|
@ -1565,9 +1581,16 @@ func executeEmailRuleAction(c dataprovider.EventActionEmailConfig, params *Event
|
|||
addObjectData = true
|
||||
}
|
||||
}
|
||||
replacements := params.getStringReplacements(addObjectData, false)
|
||||
replacements := params.getStringReplacements(addObjectData, 0)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
body := replaceWithReplacer(c.Body, replacer)
|
||||
var body string
|
||||
if c.ContentType == 1 {
|
||||
replacements := params.getStringReplacements(addObjectData, 2)
|
||||
bodyReplacer := strings.NewReplacer(replacements...)
|
||||
body = replaceWithReplacer(c.Body, bodyReplacer)
|
||||
} else {
|
||||
body = replaceWithReplacer(c.Body, replacer)
|
||||
}
|
||||
subject := replaceWithReplacer(c.Subject, replacer)
|
||||
recipients := getEmailAddressesWithReplacer(c.Recipients, replacer)
|
||||
bcc := getEmailAddressesWithReplacer(c.Bcc, replacer)
|
||||
|
|
@ -2139,7 +2162,7 @@ func executeFsRuleAction(c dataprovider.EventActionFilesystemConfig, conditions
|
|||
params *EventParams,
|
||||
) error {
|
||||
addObjectData := false
|
||||
replacements := params.getStringReplacements(addObjectData, false)
|
||||
replacements := params.getStringReplacements(addObjectData, 0)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
switch c.Type {
|
||||
case dataprovider.FilesystemActionRename:
|
||||
|
|
@ -2539,7 +2562,7 @@ func executeAdminCheckAction(c *dataprovider.EventActionIDPAccountCheck, params
|
|||
return nil, err
|
||||
}
|
||||
|
||||
replacements := params.getStringReplacements(false, true)
|
||||
replacements := params.getStringReplacements(false, 1)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
data := replaceWithReplacer(c.TemplateAdmin, replacer)
|
||||
|
||||
|
|
@ -2609,7 +2632,7 @@ func executeUserCheckAction(c *dataprovider.EventActionIDPAccountCheck, params *
|
|||
if err != nil && !errors.Is(err, util.ErrNotFound) {
|
||||
return nil, err
|
||||
}
|
||||
replacements := params.getStringReplacements(false, true)
|
||||
replacements := params.getStringReplacements(false, 1)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
data := replaceWithReplacer(c.TemplateUser, replacer)
|
||||
|
||||
|
|
@ -2831,6 +2854,16 @@ func (j *eventCronJob) getTask(rule *dataprovider.EventRule) (dataprovider.Task,
|
|||
return dataprovider.Task{}, nil
|
||||
}
|
||||
|
||||
func (j *eventCronJob) getEventParams() EventParams {
|
||||
return EventParams{
|
||||
Event: "Schedule",
|
||||
Name: j.ruleName,
|
||||
Status: 1,
|
||||
Timestamp: time.Now(),
|
||||
updateStatusFromError: true,
|
||||
}
|
||||
}
|
||||
|
||||
func (j *eventCronJob) Run() {
|
||||
eventManagerLog(logger.LevelDebug, "executing scheduled rule %q", j.ruleName)
|
||||
rule, err := dataprovider.EventRuleExists(j.ruleName)
|
||||
|
|
@ -2881,9 +2914,9 @@ func (j *eventCronJob) Run() {
|
|||
}
|
||||
}(task.Name)
|
||||
|
||||
executeAsyncRulesActions([]dataprovider.EventRule{rule}, EventParams{Status: 1, updateStatusFromError: true})
|
||||
executeAsyncRulesActions([]dataprovider.EventRule{rule}, j.getEventParams())
|
||||
} else {
|
||||
executeAsyncRulesActions([]dataprovider.EventRule{rule}, EventParams{Status: 1, updateStatusFromError: true})
|
||||
executeAsyncRulesActions([]dataprovider.EventRule{rule}, j.getEventParams())
|
||||
}
|
||||
eventManagerLog(logger.LevelDebug, "execution for scheduled rule %q finished", j.ruleName)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -808,16 +808,20 @@ func TestDateTimePlaceholder(t *testing.T) {
|
|||
params := EventParams{
|
||||
Timestamp: dateTime,
|
||||
}
|
||||
replacements := params.getStringReplacements(false, false)
|
||||
replacements := params.getStringReplacements(false, 0)
|
||||
r := strings.NewReplacer(replacements...)
|
||||
res := r.Replace("{{DateTime}}")
|
||||
res := r.Replace("{{.DateTime}}")
|
||||
assert.Equal(t, dateTime.UTC().Format(dateTimeMillisFormat), res)
|
||||
res = r.Replace("{{.Year}}-{{.Month}}-{{.Day}}T{{.Hour}}:{{.Minute}}")
|
||||
assert.Equal(t, dateTime.UTC().Format(dateTimeMillisFormat)[:16], res)
|
||||
|
||||
Config.TZ = "local"
|
||||
replacements = params.getStringReplacements(false, false)
|
||||
replacements = params.getStringReplacements(false, 0)
|
||||
r = strings.NewReplacer(replacements...)
|
||||
res = r.Replace("{{DateTime}}")
|
||||
res = r.Replace("{{.DateTime}}")
|
||||
assert.Equal(t, dateTime.Local().Format(dateTimeMillisFormat), res)
|
||||
res = r.Replace("{{.Year}}-{{.Month}}-{{.Day}}T{{.Hour}}:{{.Minute}}")
|
||||
assert.Equal(t, dateTime.Local().Format(dateTimeMillisFormat)[:16], res)
|
||||
|
||||
Config.TZ = oldTZ
|
||||
}
|
||||
|
|
@ -841,7 +845,7 @@ func TestEventRuleActions(t *testing.T) {
|
|||
HTTPConfig: dataprovider.EventActionHTTPConfig{
|
||||
Endpoint: "http://foo\x7f.com/", // invalid URL
|
||||
SkipTLSVerify: true,
|
||||
Body: `"data": "{{ObjectDataString}}"`,
|
||||
Body: `"data": "{{.ObjectDataString}}"`,
|
||||
Method: http.MethodPost,
|
||||
QueryParameters: []dataprovider.KeyValue{
|
||||
{
|
||||
|
|
@ -909,7 +913,7 @@ func TestEventRuleActions(t *testing.T) {
|
|||
assert.Contains(t, getErrorString(err), "error getting user")
|
||||
|
||||
action.Options.HTTPConfig.Parts = nil
|
||||
action.Options.HTTPConfig.Body = "{{ObjectData}}"
|
||||
action.Options.HTTPConfig.Body = "{{.ObjectData}}"
|
||||
// test disk and transfer quota reset
|
||||
username1 := "user1"
|
||||
username2 := "user2"
|
||||
|
|
@ -1245,7 +1249,7 @@ func TestEventRuleActions(t *testing.T) {
|
|||
Type: dataprovider.FilesystemActionCompress,
|
||||
Compress: dataprovider.EventActionFsCompress{
|
||||
Name: "test.zip",
|
||||
Paths: []string{"/{{VirtualPath}}"},
|
||||
Paths: []string{"/{{.VirtualPath}}"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -1950,12 +1954,27 @@ func TestScheduledActions(t *testing.T) {
|
|||
backupsPath := filepath.Join(os.TempDir(), "backups")
|
||||
err := os.RemoveAll(backupsPath)
|
||||
assert.NoError(t, err)
|
||||
now := time.Now().UTC().Format(dateTimeMillisFormat)
|
||||
// The backup action sets the home directory to the backup path.
|
||||
expectedDirPath := filepath.Join(backupsPath, fmt.Sprintf("%s_%s_%s", now[0:4], now[5:7], now[8:10]))
|
||||
|
||||
action := &dataprovider.BaseEventAction{
|
||||
Name: "action",
|
||||
action1 := &dataprovider.BaseEventAction{
|
||||
Name: "action1",
|
||||
Type: dataprovider.ActionTypeBackup,
|
||||
}
|
||||
err = dataprovider.AddEventAction(action, "", "", "")
|
||||
err = dataprovider.AddEventAction(action1, "", "", "")
|
||||
assert.NoError(t, err)
|
||||
action2 := &dataprovider.BaseEventAction{
|
||||
Name: "action2",
|
||||
Type: dataprovider.ActionTypeFilesystem,
|
||||
Options: dataprovider.BaseEventActionOptions{
|
||||
FsConfig: dataprovider.EventActionFilesystemConfig{
|
||||
Type: dataprovider.FilesystemActionMkdirs,
|
||||
MkDirs: []string{"{{.Year}}_{{.Month}}_{{.Day}}"},
|
||||
},
|
||||
},
|
||||
}
|
||||
err = dataprovider.AddEventAction(action2, "", "", "")
|
||||
assert.NoError(t, err)
|
||||
rule := &dataprovider.EventRule{
|
||||
Name: "rule",
|
||||
|
|
@ -1974,10 +1993,16 @@ func TestScheduledActions(t *testing.T) {
|
|||
Actions: []dataprovider.EventAction{
|
||||
{
|
||||
BaseEventAction: dataprovider.BaseEventAction{
|
||||
Name: action.Name,
|
||||
Name: action1.Name,
|
||||
},
|
||||
Order: 1,
|
||||
},
|
||||
{
|
||||
BaseEventAction: dataprovider.BaseEventAction{
|
||||
Name: action2.Name,
|
||||
},
|
||||
Order: 2,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -1992,9 +2017,10 @@ func TestScheduledActions(t *testing.T) {
|
|||
|
||||
job.Run()
|
||||
assert.DirExists(t, backupsPath)
|
||||
assert.DirExists(t, expectedDirPath)
|
||||
|
||||
action.Type = dataprovider.ActionTypeEmail
|
||||
action.Options = dataprovider.BaseEventActionOptions{
|
||||
action1.Type = dataprovider.ActionTypeEmail
|
||||
action1.Options = dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"example@example.com"},
|
||||
Subject: "test with attachments",
|
||||
|
|
@ -2002,16 +2028,19 @@ func TestScheduledActions(t *testing.T) {
|
|||
Attachments: []string{"/file1.txt"},
|
||||
},
|
||||
}
|
||||
err = dataprovider.UpdateEventAction(action, "", "", "")
|
||||
err = dataprovider.UpdateEventAction(action1, "", "", "")
|
||||
assert.NoError(t, err)
|
||||
job.Run() // action is not compatible with a scheduled rule
|
||||
|
||||
err = dataprovider.DeleteEventRule(rule.Name, "", "", "")
|
||||
assert.NoError(t, err)
|
||||
err = dataprovider.DeleteEventAction(action.Name, "", "", "")
|
||||
err = dataprovider.DeleteEventAction(action1.Name, "", "", "")
|
||||
assert.NoError(t, err)
|
||||
err = dataprovider.DeleteEventAction(action2.Name, "", "", "")
|
||||
assert.NoError(t, err)
|
||||
err = os.RemoveAll(backupsPath)
|
||||
assert.NoError(t, err)
|
||||
|
||||
stopEventScheduler()
|
||||
}
|
||||
|
||||
|
|
@ -2130,11 +2159,11 @@ func TestWriteHTTPPartsError(t *testing.T) {
|
|||
}
|
||||
|
||||
func TestReplacePathsPlaceholders(t *testing.T) {
|
||||
replacer := strings.NewReplacer("{{VirtualPath}}", "/path1")
|
||||
paths := []string{"{{VirtualPath}}", "/path1"}
|
||||
replacer := strings.NewReplacer("{{.VirtualPath}}", "/path1")
|
||||
paths := []string{"{{.VirtualPath}}", "/path1"}
|
||||
paths = replacePathsPlaceholders(paths, replacer)
|
||||
assert.Equal(t, []string{"/path1"}, paths)
|
||||
paths = []string{"{{VirtualPath}}", "/path2"}
|
||||
paths = []string{"{{.VirtualPath}}", "/path2"}
|
||||
paths = replacePathsPlaceholders(paths, replacer)
|
||||
assert.Equal(t, []string{"/path1", "/path2"}, paths)
|
||||
}
|
||||
|
|
@ -2227,7 +2256,7 @@ func TestOnDemandRule(t *testing.T) {
|
|||
Recipients: []string{"example@example.org"},
|
||||
Subject: "subject",
|
||||
Body: "body",
|
||||
Attachments: []string{"/{{VirtualPath}}"},
|
||||
Attachments: []string{"/{{.VirtualPath}}"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -2268,21 +2297,21 @@ func getErrorString(err error) string {
|
|||
|
||||
func TestHTTPEndpointWithPlaceholders(t *testing.T) {
|
||||
c := dataprovider.EventActionHTTPConfig{
|
||||
Endpoint: "http://127.0.0.1:8080/base/url/{{Name}}/{{VirtualPath}}/upload",
|
||||
Endpoint: "http://127.0.0.1:8080/base/url/{{.Name}}/{{.VirtualPath}}/upload",
|
||||
QueryParameters: []dataprovider.KeyValue{
|
||||
{
|
||||
Key: "u",
|
||||
Value: "{{Name}}",
|
||||
Value: "{{.Name}}",
|
||||
},
|
||||
{
|
||||
Key: "p",
|
||||
Value: "{{VirtualPath}}",
|
||||
Value: "{{.VirtualPath}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
name := "uname"
|
||||
vPath := "/a dir/@ file.txt"
|
||||
replacer := strings.NewReplacer("{{Name}}", name, "{{VirtualPath}}", vPath)
|
||||
replacer := strings.NewReplacer("{{.Name}}", name, "{{.VirtualPath}}", vPath)
|
||||
u, err := getHTTPRuleActionEndpoint(&c, replacer)
|
||||
assert.NoError(t, err)
|
||||
expected := "http://127.0.0.1:8080/base/url/" + url.PathEscape(name) + "/" + url.PathEscape(vPath) +
|
||||
|
|
@ -2302,9 +2331,9 @@ func TestMetadataReplacement(t *testing.T) {
|
|||
"key": "value",
|
||||
},
|
||||
}
|
||||
replacements := params.getStringReplacements(false, false)
|
||||
replacements := params.getStringReplacements(false, 0)
|
||||
replacer := strings.NewReplacer(replacements...)
|
||||
reader, _, err := getHTTPRuleActionBody(&dataprovider.EventActionHTTPConfig{Body: "{{Metadata}} {{MetadataString}}"}, replacer, nil, dataprovider.User{}, params, false)
|
||||
reader, _, err := getHTTPRuleActionBody(&dataprovider.EventActionHTTPConfig{Body: "{{.Metadata}} {{.MetadataString}}"}, replacer, nil, dataprovider.User{}, params, false)
|
||||
require.NoError(t, err)
|
||||
data, err := io.ReadAll(reader)
|
||||
require.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -3784,8 +3784,8 @@ func TestEventRule(t *testing.T) {
|
|||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test1@example.com", "test2@example.com"},
|
||||
Bcc: []string{"test3@example.com"},
|
||||
Subject: `New "{{Event}}" from "{{Name}}" status {{StatusString}}`,
|
||||
Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}} Data: {{ObjectData}} {{ErrorString}}",
|
||||
Subject: `New "{{.Event}}" from "{{.Name}}" status {{.StatusString}}`,
|
||||
Body: "Fs path {{.FsPath}}, size: {{.FileSize}}, protocol: {{.Protocol}}, IP: {{.IP}} Data: {{.ObjectData}} {{.ErrorString}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -3795,8 +3795,8 @@ func TestEventRule(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"failure@example.com"},
|
||||
Subject: `Failed "{{Event}}" from "{{Name}}"`,
|
||||
Body: "Fs path {{FsPath}}, protocol: {{Protocol}}, IP: {{IP}} {{ErrorString}}",
|
||||
Subject: `Failed "{{.Event}}" from "{{.Name}}"`,
|
||||
Body: "Fs path {{.FsPath}}, protocol: {{.Protocol}}, IP: {{.IP}} {{.ErrorString}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -3941,7 +3941,7 @@ func TestEventRule(t *testing.T) {
|
|||
EnvVars: []dataprovider.KeyValue{
|
||||
{
|
||||
Key: "SFTPGO_ACTION_PATH",
|
||||
Value: "{{FsPath}}",
|
||||
Value: "{{.FsPath}}",
|
||||
},
|
||||
{
|
||||
Key: "CUSTOM_ENV_VAR",
|
||||
|
|
@ -4050,7 +4050,7 @@ func TestEventRule(t *testing.T) {
|
|||
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: New "download" from "%s"`, user.Username))
|
||||
}
|
||||
// test upload action command with arguments
|
||||
action1.Options.CmdConfig.Args = []string{"{{Event}}", "{{VirtualPath}}", "custom_arg"}
|
||||
action1.Options.CmdConfig.Args = []string{"{{.Event}}", "{{.VirtualPath}}", "custom_arg"}
|
||||
action1, _, err = httpdtest.UpdateEventAction(action1, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
uploadLogFilePath := filepath.Join(os.TempDir(), "upload.log")
|
||||
|
|
@ -4128,8 +4128,8 @@ func TestEventRuleStatues(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test6@example.com"},
|
||||
Subject: `New "{{Event}}" error`,
|
||||
Body: "{{ErrorString}}",
|
||||
Subject: `New "{{.Event}}" error`,
|
||||
Body: "{{.ErrorString}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -4241,7 +4241,7 @@ func TestEventRuleDisabledCommand(t *testing.T) {
|
|||
EnvVars: []dataprovider.KeyValue{
|
||||
{
|
||||
Key: "SFTPGO_OBJECT_DATA",
|
||||
Value: "{{ObjectData}}",
|
||||
Value: "{{.ObjectData}}",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -4253,8 +4253,8 @@ func TestEventRuleDisabledCommand(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test3@example.com"},
|
||||
Subject: `New "{{Event}}" from "{{Name}}"`,
|
||||
Body: "Object name: {{ObjectName}} object type: {{ObjectType}} Data: {{ObjectData}}",
|
||||
Subject: `New "{{.Event}}" from "{{.Name}}"`,
|
||||
Body: "Object name: {{.ObjectName}} object type: {{.ObjectType}} Data: {{.ObjectData}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -4265,8 +4265,8 @@ func TestEventRuleDisabledCommand(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"failure@example.com"},
|
||||
Subject: `Failed "{{Event}}" from "{{Name}}"`,
|
||||
Body: "Object name: {{ObjectName}} object type: {{ObjectType}}, IP: {{IP}}",
|
||||
Subject: `Failed "{{.Event}}" from "{{.Name}}"`,
|
||||
Body: "Object name: {{.ObjectName}} object type: {{.ObjectType}}, IP: {{.IP}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -4390,7 +4390,7 @@ func TestEventRuleProviderEvents(t *testing.T) {
|
|||
EnvVars: []dataprovider.KeyValue{
|
||||
{
|
||||
Key: "SFTPGO_OBJECT_DATA",
|
||||
Value: "{{ObjectData}}",
|
||||
Value: "{{.ObjectData}}",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -4402,8 +4402,8 @@ func TestEventRuleProviderEvents(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test3@example.com"},
|
||||
Subject: `New "{{Event}}" from "{{Name}}"`,
|
||||
Body: "Object name: {{ObjectName}} object type: {{ObjectType}} Data: {{ObjectData}}",
|
||||
Subject: `New "{{.Event}}" from "{{.Name}}"`,
|
||||
Body: "Object name: {{.ObjectName}} object type: {{.ObjectType}} Data: {{.ObjectData}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -4414,8 +4414,8 @@ func TestEventRuleProviderEvents(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"failure@example.com"},
|
||||
Subject: `Failed "{{Event}}" from "{{Name}}"`,
|
||||
Body: "Object name: {{ObjectName}} object type: {{ObjectType}}, IP: {{IP}}",
|
||||
Subject: `Failed "{{.Event}}" from "{{.Name}}"`,
|
||||
Body: "Object name: {{.ObjectName}} object type: {{.ObjectType}}, IP: {{.IP}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -4561,8 +4561,8 @@ func TestEventRuleFsActions(t *testing.T) {
|
|||
Renames: []dataprovider.RenameConfig{
|
||||
{
|
||||
KeyValue: dataprovider.KeyValue{
|
||||
Key: "/{{VirtualDirPath}}/{{ObjectName}}",
|
||||
Value: "/{{ObjectName}}_renamed",
|
||||
Key: "/{{.VirtualDirPath}}/{{.ObjectName}}",
|
||||
Value: "/{{.ObjectName}}_renamed",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -4575,7 +4575,7 @@ func TestEventRuleFsActions(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
FsConfig: dataprovider.EventActionFilesystemConfig{
|
||||
Type: dataprovider.FilesystemActionDelete,
|
||||
Deletes: []string{"/{{ObjectName}}_renamed"},
|
||||
Deletes: []string{"/{{.ObjectName}}_renamed"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -4593,7 +4593,7 @@ func TestEventRuleFsActions(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
FsConfig: dataprovider.EventActionFilesystemConfig{
|
||||
Type: dataprovider.FilesystemActionExist,
|
||||
Exist: []string{"/{{VirtualPath}}"},
|
||||
Exist: []string{"/{{.VirtualPath}}"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -4831,8 +4831,8 @@ func TestEventActionObjectBaseName(t *testing.T) {
|
|||
Renames: []dataprovider.RenameConfig{
|
||||
{
|
||||
KeyValue: dataprovider.KeyValue{
|
||||
Key: "/{{VirtualDirPath}}/{{ObjectName}}",
|
||||
Value: "/{{ObjectBaseName}}",
|
||||
Key: "/{{.VirtualDirPath}}/{{.ObjectName}}",
|
||||
Value: "/{{.ObjectBaseName}}",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -4911,8 +4911,8 @@ func TestUploadEventRule(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test1@example.com"},
|
||||
Subject: `New "{{Event}}" from "{{Name}}" status {{StatusString}}`,
|
||||
Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}} Data: {{ObjectData}} {{ErrorString}}",
|
||||
Subject: `New "{{.Event}}" from "{{.Name}}" status {{.StatusString}}`,
|
||||
Body: "Fs path {{.FsPath}}, size: {{.FileSize}}, protocol: {{.Protocol}}, IP: {{.IP}} Data: {{.ObjectData}} {{.ErrorString}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -5047,8 +5047,8 @@ func TestEventRulePreDelete(t *testing.T) {
|
|||
Renames: []dataprovider.RenameConfig{
|
||||
{
|
||||
KeyValue: dataprovider.KeyValue{
|
||||
Key: "/{{VirtualPath}}",
|
||||
Value: fmt.Sprintf("/%s/{{VirtualPath}}", movePath),
|
||||
Key: "/{{.VirtualPath}}",
|
||||
Value: fmt.Sprintf("/%s/{{.VirtualPath}}", movePath),
|
||||
},
|
||||
UpdateModTime: true,
|
||||
},
|
||||
|
|
@ -5410,7 +5410,7 @@ func TestFsActionCopy(t *testing.T) {
|
|||
Type: dataprovider.FilesystemActionCopy,
|
||||
Copy: []dataprovider.KeyValue{
|
||||
{
|
||||
Key: "/{{VirtualPath}}/",
|
||||
Key: "/{{.VirtualPath}}/",
|
||||
Value: "/dircopy/",
|
||||
},
|
||||
},
|
||||
|
|
@ -5492,8 +5492,8 @@ func TestEventFsActionsGroupFilters(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"example@example.net"},
|
||||
Subject: `New "{{Event}}" from "{{Name}}" status {{StatusString}}`,
|
||||
Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}} {{ErrorString}}",
|
||||
Subject: `New "{{.Event}}" from "{{.Name}}" status {{.StatusString}}`,
|
||||
Body: "Fs path {{.FsPath}}, size: {{.FileSize}}, protocol: {{.Protocol}}, IP: {{.IP}} {{.ErrorString}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -5623,8 +5623,8 @@ func TestEventProviderActionGroupFilters(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"example@example.net"},
|
||||
Subject: `New "{{Event}}" from "{{Name}}"`,
|
||||
Body: "IP: {{IP}}",
|
||||
Subject: `New "{{.Event}}" from "{{.Name}}"`,
|
||||
Body: "IP: {{.IP}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -5759,9 +5759,9 @@ func TestBackupAsAttachment(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test@example.com"},
|
||||
Subject: `"{{Event}} {{StatusString}}"`,
|
||||
Body: "Domain: {{Name}}",
|
||||
Attachments: []string{"/{{VirtualPath}}"},
|
||||
Subject: `"{{.Event}} {{.StatusString}}"`,
|
||||
Body: "Domain: {{.Name}}",
|
||||
Attachments: []string{"/{{.VirtualPath}}"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -5840,11 +5840,11 @@ func TestEventActionHTTPMultipart(t *testing.T) {
|
|||
Value: "application/json",
|
||||
},
|
||||
},
|
||||
Body: `{"FilePath": "{{VirtualPath}}"}`,
|
||||
Body: `{"FilePath": "{{.VirtualPath}}"}`,
|
||||
},
|
||||
{
|
||||
Name: "file",
|
||||
Filepath: "/{{VirtualPath}}",
|
||||
Filepath: "/{{.VirtualPath}}",
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -5920,8 +5920,8 @@ func TestEventActionCompress(t *testing.T) {
|
|||
FsConfig: dataprovider.EventActionFilesystemConfig{
|
||||
Type: dataprovider.FilesystemActionCompress,
|
||||
Compress: dataprovider.EventActionFsCompress{
|
||||
Name: "/{{VirtualPath}}.zip",
|
||||
Paths: []string{"/{{VirtualPath}}"},
|
||||
Name: "/{{.VirtualPath}}.zip",
|
||||
Paths: []string{"/{{.VirtualPath}}"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -6091,7 +6091,7 @@ func TestEventActionCompressQuotaErrors(t *testing.T) {
|
|||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test@example.com"},
|
||||
Subject: `"Compress failed"`,
|
||||
Body: "Error: {{ErrorString}}",
|
||||
Body: "Error: {{.ErrorString}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -6235,8 +6235,8 @@ func TestEventActionCompressQuotaFolder(t *testing.T) {
|
|||
FsConfig: dataprovider.EventActionFilesystemConfig{
|
||||
Type: dataprovider.FilesystemActionCompress,
|
||||
Compress: dataprovider.EventActionFsCompress{
|
||||
Name: "/{{VirtualPath}}.zip",
|
||||
Paths: []string{"/{{VirtualPath}}", testDir},
|
||||
Name: "/{{.VirtualPath}}.zip",
|
||||
Paths: []string{"/{{.VirtualPath}}", testDir},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -6361,8 +6361,8 @@ func TestEventActionCompressErrors(t *testing.T) {
|
|||
FsConfig: dataprovider.EventActionFilesystemConfig{
|
||||
Type: dataprovider.FilesystemActionCompress,
|
||||
Compress: dataprovider.EventActionFsCompress{
|
||||
Name: "/{{VirtualPath}}.zip",
|
||||
Paths: []string{"/{{VirtualPath}}.zip"}, // cannot compress itself
|
||||
Name: "/{{.VirtualPath}}.zip",
|
||||
Paths: []string{"/{{.VirtualPath}}.zip"}, // cannot compress itself
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -6424,7 +6424,7 @@ func TestEventActionCompressErrors(t *testing.T) {
|
|||
// try to overwrite a directory
|
||||
testDir := "/adir"
|
||||
action1.Options.FsConfig.Compress.Name = testDir
|
||||
action1.Options.FsConfig.Compress.Paths = []string{"/{{VirtualPath}}"}
|
||||
action1.Options.FsConfig.Compress.Paths = []string{"/{{.VirtualPath}}"}
|
||||
_, _, err = httpdtest.UpdateEventAction(action1, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
conn, client, err = getSftpClient(user)
|
||||
|
|
@ -6469,8 +6469,8 @@ func TestEventActionEmailAttachments(t *testing.T) {
|
|||
FsConfig: dataprovider.EventActionFilesystemConfig{
|
||||
Type: dataprovider.FilesystemActionCompress,
|
||||
Compress: dataprovider.EventActionFsCompress{
|
||||
Name: "/archive/{{VirtualPath}}.zip",
|
||||
Paths: []string{"/{{VirtualPath}}"},
|
||||
Name: "/archive/{{.VirtualPath}}.zip",
|
||||
Paths: []string{"/{{.VirtualPath}}"},
|
||||
},
|
||||
},
|
||||
},
|
||||
|
|
@ -6483,9 +6483,9 @@ func TestEventActionEmailAttachments(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test@example.com"},
|
||||
Subject: `"{{Event}}" from "{{Name}}"`,
|
||||
Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}} {{EscapedVirtualPath}}",
|
||||
Attachments: []string{"/archive/{{VirtualPath}}.zip"},
|
||||
Subject: `"{{.Event}}" from "{{.Name}}"`,
|
||||
Body: "Fs path {{.FsPath}}, size: {{.FileSize}}, protocol: {{.Protocol}}, IP: {{.IP}} {{.EscapedVirtualPath}}",
|
||||
Attachments: []string{"/archive/{{.VirtualPath}}.zip"},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -6604,8 +6604,8 @@ func TestEventActionsRetentionReports(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test@example.com"},
|
||||
Subject: `"{{Event}}" from "{{Name}}"`,
|
||||
Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}}",
|
||||
Subject: `"{{.Event}}" from "{{.Name}}"`,
|
||||
Body: "Fs path {{.FsPath}}, size: {{.FileSize}}, protocol: {{.Protocol}}, IP: {{.IP}}",
|
||||
Attachments: []string{dataprovider.RetentionReportPlaceHolder},
|
||||
},
|
||||
},
|
||||
|
|
@ -6832,8 +6832,8 @@ func TestEventRuleFirstUploadDownloadActions(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test@example.com"},
|
||||
Subject: `"{{Event}}" from "{{Name}}"`,
|
||||
Body: "Fs path {{FsPath}}, size: {{FileSize}}, protocol: {{Protocol}}, IP: {{IP}}",
|
||||
Subject: `"{{.Event}}" from "{{.Name}}"`,
|
||||
Body: "Fs path {{.FsPath}}, size: {{.FileSize}}, protocol: {{.Protocol}}, IP: {{.IP}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -6964,9 +6964,9 @@ func TestEventRuleRenameEvent(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test@example.com"},
|
||||
Subject: `"{{Event}}" from "{{Name}}"`,
|
||||
Subject: `"{{.Event}}" from "{{.Name}}"`,
|
||||
ContentType: 1,
|
||||
Body: `<p>Fs path {{FsPath}}, Target path "{{VirtualTargetDirPath}}/{{TargetName}}", size: {{FileSize}}</p>`,
|
||||
Body: `<p>Fs path {{.FsPath}}, Name: {{.Name}}, Target path "{{.VirtualTargetDirPath}}/{{.TargetName}}", size: {{.FileSize}}</p>`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -6991,7 +6991,9 @@ func TestEventRuleRenameEvent(t *testing.T) {
|
|||
rule1, _, err := httpdtest.AddEventRule(r1, http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
|
||||
user, _, err := httpdtest.AddUser(getTestUser(), http.StatusCreated)
|
||||
u := getTestUser()
|
||||
u.Username = "test <html > chars"
|
||||
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
conn, client, err := getSftpClient(user)
|
||||
if assert.NoError(t, err) {
|
||||
|
|
@ -7015,6 +7017,7 @@ func TestEventRuleRenameEvent(t *testing.T) {
|
|||
assert.Contains(t, email.Data, fmt.Sprintf(`Subject: "rename" from "%s"`, user.Username))
|
||||
assert.Contains(t, email.Data, "Content-Type: text/html")
|
||||
assert.Contains(t, email.Data, fmt.Sprintf("Target path %q", path.Join("/subdir", testFileName)))
|
||||
assert.Contains(t, email.Data, "Name: test <html > chars,")
|
||||
}
|
||||
|
||||
_, err = httpdtest.RemoveEventRule(rule1, http.StatusOK)
|
||||
|
|
@ -7045,9 +7048,9 @@ func TestEventRuleIDPLogin(t *testing.T) {
|
|||
username := `test_"idp_"login`
|
||||
custom1 := `cust"oa"1`
|
||||
u := map[string]any{
|
||||
"username": "{{Name}}",
|
||||
"username": "{{.Name}}",
|
||||
"status": 1,
|
||||
"home_dir": filepath.Join(os.TempDir(), "{{IDPFieldcustom1}}"),
|
||||
"home_dir": filepath.Join(os.TempDir(), "{{.IDPFieldcustom1}}"),
|
||||
"permissions": map[string][]string{
|
||||
"/": {dataprovider.PermAny},
|
||||
},
|
||||
|
|
@ -7055,7 +7058,7 @@ func TestEventRuleIDPLogin(t *testing.T) {
|
|||
userTmpl, err := json.Marshal(u)
|
||||
require.NoError(t, err)
|
||||
a := map[string]any{
|
||||
"username": "{{Name}}",
|
||||
"username": "{{.Name}}",
|
||||
"status": 1,
|
||||
"permissions": []string{dataprovider.PermAdminAny},
|
||||
}
|
||||
|
|
@ -7081,8 +7084,8 @@ func TestEventRuleIDPLogin(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test@example.com"},
|
||||
Subject: `"{{Event}} {{StatusString}}"`,
|
||||
Body: "{{Name}} Custom field: {{IDPFieldcustom1}}",
|
||||
Subject: `"{{.Event}} {{.StatusString}}"`,
|
||||
Body: "{{.Name}} Custom field: {{.IDPFieldcustom1}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -7327,8 +7330,8 @@ func TestEventRuleEmailField(t *testing.T) {
|
|||
Type: dataprovider.ActionTypeEmail,
|
||||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"{{Email}}"},
|
||||
Subject: `"{{Event}}" from "{{Name}}"`,
|
||||
Recipients: []string{"{{.Email}}"},
|
||||
Subject: `"{{.Event}}" from "{{.Name}}"`,
|
||||
Body: "Sample email body",
|
||||
},
|
||||
},
|
||||
|
|
@ -7342,7 +7345,7 @@ func TestEventRuleEmailField(t *testing.T) {
|
|||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"failure@example.com"},
|
||||
Subject: `"Failure`,
|
||||
Body: "{{ErrorString}}",
|
||||
Body: "{{.ErrorString}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -7473,9 +7476,9 @@ func TestEventRuleCertificate(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test@example.com"},
|
||||
Subject: `"{{Event}} {{StatusString}}"`,
|
||||
Subject: `"{{.Event}} {{.StatusString}}"`,
|
||||
ContentType: 0,
|
||||
Body: "Domain: {{Name}} Timestamp: {{Timestamp}} {{ErrorString}} Date time: {{DateTime}}",
|
||||
Body: "Domain: {{.Name}} Timestamp: {{.Timestamp}} {{.ErrorString}} Date time: {{.DateTime}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -7613,8 +7616,8 @@ func TestEventRuleIPBlocked(t *testing.T) {
|
|||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"test3@example.com", "test4@example.com"},
|
||||
Subject: `New "{{Event}}"`,
|
||||
Body: "IP: {{IP}} Timestamp: {{Timestamp}}",
|
||||
Subject: `New "{{.Event}}"`,
|
||||
Body: "IP: {{.IP}} Timestamp: {{.Timestamp}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
|
|||
|
|
@ -35,7 +35,7 @@ var (
|
|||
)
|
||||
|
||||
// BaseTransfer contains protocols common transfer details for an upload or a download.
|
||||
type BaseTransfer struct { //nolint:maligned
|
||||
type BaseTransfer struct {
|
||||
ID int64
|
||||
BytesSent atomic.Int64
|
||||
BytesReceived atomic.Int64
|
||||
|
|
|
|||
|
|
@ -24,6 +24,7 @@ import (
|
|||
"strconv"
|
||||
"strings"
|
||||
|
||||
kmsplugin "github.com/sftpgo/sdk/plugin/kms"
|
||||
"github.com/spf13/viper"
|
||||
"github.com/subosito/gotenv"
|
||||
|
||||
|
|
@ -99,26 +100,27 @@ var (
|
|||
DisableWWWAuthHeader: false,
|
||||
}
|
||||
defaultHTTPDBinding = httpd.Binding{
|
||||
Address: "",
|
||||
Port: 8080,
|
||||
EnableWebAdmin: true,
|
||||
EnableWebClient: true,
|
||||
EnableRESTAPI: true,
|
||||
EnabledLoginMethods: 0,
|
||||
EnableHTTPS: false,
|
||||
CertificateFile: "",
|
||||
CertificateKeyFile: "",
|
||||
MinTLSVersion: 12,
|
||||
ClientAuthType: 0,
|
||||
TLSCipherSuites: nil,
|
||||
Protocols: nil,
|
||||
ProxyMode: 0,
|
||||
ProxyAllowed: nil,
|
||||
ClientIPProxyHeader: "",
|
||||
ClientIPHeaderDepth: 0,
|
||||
HideLoginURL: 0,
|
||||
RenderOpenAPI: true,
|
||||
Languages: []string{"en"},
|
||||
Address: "",
|
||||
Port: 8080,
|
||||
EnableWebAdmin: true,
|
||||
EnableWebClient: true,
|
||||
EnableRESTAPI: true,
|
||||
EnabledLoginMethods: 0,
|
||||
DisabledLoginMethods: 0,
|
||||
EnableHTTPS: false,
|
||||
CertificateFile: "",
|
||||
CertificateKeyFile: "",
|
||||
MinTLSVersion: 12,
|
||||
ClientAuthType: 0,
|
||||
TLSCipherSuites: nil,
|
||||
Protocols: nil,
|
||||
ProxyMode: 0,
|
||||
ProxyAllowed: nil,
|
||||
ClientIPProxyHeader: "",
|
||||
ClientIPHeaderDepth: 0,
|
||||
HideLoginURL: 0,
|
||||
RenderOpenAPI: true,
|
||||
Languages: []string{"en"},
|
||||
OIDC: httpd.OIDC{
|
||||
ClientID: "",
|
||||
ClientSecret: "",
|
||||
|
|
@ -134,21 +136,23 @@ var (
|
|||
Debug: false,
|
||||
},
|
||||
Security: httpd.SecurityConf{
|
||||
Enabled: false,
|
||||
AllowedHosts: nil,
|
||||
AllowedHostsAreRegex: false,
|
||||
HostsProxyHeaders: nil,
|
||||
HTTPSRedirect: false,
|
||||
HTTPSHost: "",
|
||||
HTTPSProxyHeaders: nil,
|
||||
STSSeconds: 0,
|
||||
STSIncludeSubdomains: false,
|
||||
STSPreload: false,
|
||||
ContentTypeNosniff: false,
|
||||
ContentSecurityPolicy: "",
|
||||
PermissionsPolicy: "",
|
||||
CrossOriginOpenerPolicy: "",
|
||||
CacheControl: "",
|
||||
Enabled: false,
|
||||
AllowedHosts: nil,
|
||||
AllowedHostsAreRegex: false,
|
||||
HostsProxyHeaders: nil,
|
||||
HTTPSRedirect: false,
|
||||
HTTPSHost: "",
|
||||
HTTPSProxyHeaders: nil,
|
||||
STSSeconds: 0,
|
||||
STSIncludeSubdomains: false,
|
||||
STSPreload: false,
|
||||
ContentTypeNosniff: false,
|
||||
ContentSecurityPolicy: "",
|
||||
PermissionsPolicy: "",
|
||||
CrossOriginOpenerPolicy: "",
|
||||
CrossOriginResourcePolicy: "",
|
||||
CrossOriginEmbedderPolicy: "",
|
||||
CacheControl: "",
|
||||
},
|
||||
Branding: httpd.Branding{},
|
||||
}
|
||||
|
|
@ -585,6 +589,16 @@ func SetPluginsConfig(config []plugin.Config) {
|
|||
globalConf.PluginsConfig = config
|
||||
}
|
||||
|
||||
// HasKMSPlugin returns true if at least one KMS plugin is configured.
|
||||
func HasKMSPlugin() bool {
|
||||
for _, c := range globalConf.PluginsConfig {
|
||||
if c.Type == kmsplugin.PluginName {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// GetMFAConfig returns multi-factor authentication config
|
||||
func GetMFAConfig() mfa.Config {
|
||||
return globalConf.MFAConfig
|
||||
|
|
@ -1565,9 +1579,27 @@ func getHTTPDSecurityConfFromEnv(idx int) (httpd.SecurityConf, bool) { //nolint:
|
|||
isSet = true
|
||||
}
|
||||
|
||||
crossOriginOpenedPolicy, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__SECURITY__CROSS_ORIGIN_OPENER_POLICY", idx))
|
||||
crossOriginOpenerPolicy, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__SECURITY__CROSS_ORIGIN_OPENER_POLICY", idx))
|
||||
if ok {
|
||||
result.CrossOriginOpenerPolicy = crossOriginOpenedPolicy
|
||||
result.CrossOriginOpenerPolicy = crossOriginOpenerPolicy
|
||||
isSet = true
|
||||
}
|
||||
|
||||
crossOriginResourcePolicy, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__SECURITY__CROSS_ORIGIN_RESOURCE_POLICY", idx))
|
||||
if ok {
|
||||
result.CrossOriginResourcePolicy = crossOriginResourcePolicy
|
||||
isSet = true
|
||||
}
|
||||
|
||||
crossOriginEmbedderPolicy, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__SECURITY__CROSS_ORIGIN_EMBEDDER_POLICY", idx))
|
||||
if ok {
|
||||
result.CrossOriginEmbedderPolicy = crossOriginEmbedderPolicy
|
||||
isSet = true
|
||||
}
|
||||
|
||||
referredPolicy, ok := os.LookupEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__SECURITY__REFERRER_POLICY", idx))
|
||||
if ok {
|
||||
result.ReferrerPolicy = referredPolicy
|
||||
isSet = true
|
||||
}
|
||||
|
||||
|
|
@ -1854,6 +1886,12 @@ func getHTTPDBindingFromEnv(idx int) { //nolint:gocyclo
|
|||
isSet = true
|
||||
}
|
||||
|
||||
disabledLoginMethods, ok := lookupIntFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__DISABLED_LOGIN_METHODS", idx), 32)
|
||||
if ok {
|
||||
binding.DisabledLoginMethods = int(disabledLoginMethods)
|
||||
isSet = true
|
||||
}
|
||||
|
||||
renderOpenAPI, ok := lookupBoolFromEnv(fmt.Sprintf("SFTPGO_HTTPD__BINDINGS__%v__RENDER_OPENAPI", idx))
|
||||
if ok {
|
||||
binding.RenderOpenAPI = renderOpenAPI
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build darwin
|
||||
// +build darwin
|
||||
|
||||
package config
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !linux && !darwin
|
||||
// +build !linux,!darwin
|
||||
|
||||
package config
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package config
|
||||
|
||||
|
|
|
|||
|
|
@ -343,6 +343,18 @@ func TestSetGetConfig(t *testing.T) {
|
|||
if assert.Len(t, config.GetPluginsConfig(), 1) {
|
||||
assert.Equal(t, pluginConf[0].Type, config.GetPluginsConfig()[0].Type)
|
||||
}
|
||||
assert.False(t, config.HasKMSPlugin())
|
||||
pluginConf = []plugin.Config{
|
||||
{
|
||||
Type: "notifier",
|
||||
},
|
||||
{
|
||||
Type: "kms",
|
||||
},
|
||||
}
|
||||
config.SetPluginsConfig(pluginConf)
|
||||
assert.Len(t, config.GetPluginsConfig(), 2)
|
||||
assert.True(t, config.HasKMSPlugin())
|
||||
}
|
||||
|
||||
func TestServiceToStart(t *testing.T) {
|
||||
|
|
@ -528,7 +540,7 @@ func TestOverrideSliceValues(t *testing.T) {
|
|||
|
||||
c = make(map[string]any)
|
||||
c["httpd"] = httpd.Conf{
|
||||
Bindings: []httpd.Binding{},
|
||||
Bindings: nil,
|
||||
}
|
||||
jsonConf, err = json.Marshal(c)
|
||||
assert.NoError(t, err)
|
||||
|
|
@ -1192,6 +1204,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
|||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__ENABLE_WEB_CLIENT", "0")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__ENABLE_REST_API", "0")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__ENABLED_LOGIN_METHODS", "3")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__DISABLED_LOGIN_METHODS", "12")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__RENDER_OPENAPI", "0")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__LANGUAGES", "en,es")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__ENABLE_HTTPS", "1 ")
|
||||
|
|
@ -1230,7 +1243,10 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
|||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CONTENT_SECURITY_POLICY", "script-src $NONCE")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__PERMISSIONS_POLICY", "fullscreen=(), geolocation=()")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CROSS_ORIGIN_OPENER_POLICY", "same-origin")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CROSS_ORIGIN_RESOURCE_POLICY", "same-site")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CROSS_ORIGIN_EMBEDDER_POLICY", "require-corp")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CACHE_CONTROL", "private")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__REFERRER_POLICY", "no-referrer")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__EXTRA_CSS__0__PATH", "path1")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__EXTRA_CSS__1__PATH", "path2")
|
||||
os.Setenv("SFTPGO_HTTPD__BINDINGS__2__BRANDING__WEB_ADMIN__FAVICON_PATH", "favicon.ico")
|
||||
|
|
@ -1261,6 +1277,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
|||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__ENABLE_WEB_CLIENT")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__ENABLE_REST_API")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__ENABLED_LOGIN_METHODS")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__DISABLED_LOGIN_METHODS")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__RENDER_OPENAPI")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__LANGUAGES")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__CLIENT_AUTH_TYPE")
|
||||
|
|
@ -1297,7 +1314,10 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
|||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CONTENT_SECURITY_POLICY")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__PERMISSIONS_POLICY")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CROSS_ORIGIN_OPENER_POLICY")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CROSS_ORIGIN_RESOURCE_POLICY")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CROSS_ORIGIN_EMBEDDER_POLICY")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__CACHE_CONTROL")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__SECURITY__REFERRER_POLICY")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__EXTRA_CSS__0__PATH")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__EXTRA_CSS__1__PATH")
|
||||
os.Unsetenv("SFTPGO_HTTPD__BINDINGS__2__BRANDING__WEB_ADMIN__FAVICON_PATH")
|
||||
|
|
@ -1323,6 +1343,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
|||
require.True(t, bindings[0].EnableWebClient)
|
||||
require.True(t, bindings[0].EnableRESTAPI)
|
||||
require.Equal(t, 0, bindings[0].EnabledLoginMethods)
|
||||
require.Equal(t, 0, bindings[0].DisabledLoginMethods)
|
||||
require.True(t, bindings[0].RenderOpenAPI)
|
||||
require.Len(t, bindings[0].Languages, 1)
|
||||
assert.Contains(t, bindings[0].Languages, "en")
|
||||
|
|
@ -1336,6 +1357,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
|||
require.Len(t, bindings[0].OIDC.Scopes, 3)
|
||||
require.False(t, bindings[0].OIDC.InsecureSkipSignatureCheck)
|
||||
require.False(t, bindings[0].OIDC.Debug)
|
||||
require.Empty(t, bindings[0].Security.ReferrerPolicy)
|
||||
require.Equal(t, 8000, bindings[1].Port)
|
||||
require.Equal(t, "127.0.0.1", bindings[1].Address)
|
||||
require.False(t, bindings[1].EnableHTTPS)
|
||||
|
|
@ -1344,6 +1366,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
|||
require.True(t, bindings[1].EnableWebClient)
|
||||
require.True(t, bindings[1].EnableRESTAPI)
|
||||
require.Equal(t, 0, bindings[1].EnabledLoginMethods)
|
||||
require.Equal(t, 0, bindings[1].DisabledLoginMethods)
|
||||
require.True(t, bindings[1].RenderOpenAPI)
|
||||
require.Len(t, bindings[1].Languages, 1)
|
||||
assert.Contains(t, bindings[1].Languages, "en")
|
||||
|
|
@ -1366,6 +1389,7 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
|||
require.False(t, bindings[2].EnableWebClient)
|
||||
require.False(t, bindings[2].EnableRESTAPI)
|
||||
require.Equal(t, 3, bindings[2].EnabledLoginMethods)
|
||||
require.Equal(t, 12, bindings[2].DisabledLoginMethods)
|
||||
require.False(t, bindings[2].RenderOpenAPI)
|
||||
require.Len(t, bindings[2].Languages, 2)
|
||||
assert.Contains(t, bindings[2].Languages, "en")
|
||||
|
|
@ -1417,7 +1441,10 @@ func TestHTTPDBindingsFromEnv(t *testing.T) {
|
|||
require.Equal(t, "script-src $NONCE", bindings[2].Security.ContentSecurityPolicy)
|
||||
require.Equal(t, "fullscreen=(), geolocation=()", bindings[2].Security.PermissionsPolicy)
|
||||
require.Equal(t, "same-origin", bindings[2].Security.CrossOriginOpenerPolicy)
|
||||
require.Equal(t, "same-site", bindings[2].Security.CrossOriginResourcePolicy)
|
||||
require.Equal(t, "require-corp", bindings[2].Security.CrossOriginEmbedderPolicy)
|
||||
require.Equal(t, "private", bindings[2].Security.CacheControl)
|
||||
require.Equal(t, "no-referrer", bindings[2].Security.ReferrerPolicy)
|
||||
require.Equal(t, "favicon.ico", bindings[2].Branding.WebAdmin.FaviconPath)
|
||||
require.Equal(t, "logo.png", bindings[2].Branding.WebClient.LogoPath)
|
||||
require.Equal(t, "disclaimer", bindings[2].Branding.WebClient.DisclaimerName)
|
||||
|
|
|
|||
|
|
@ -366,6 +366,7 @@ func (a *Admin) validateGroups() error {
|
|||
|
||||
func (a *Admin) validate() error {
|
||||
a.SetEmptySecretsIfNil()
|
||||
a.Password = strings.TrimSpace(a.Password)
|
||||
if a.Username == "" {
|
||||
return util.NewI18nError(util.NewValidationError("username is mandatory"), util.I18nErrorUsernameRequired)
|
||||
}
|
||||
|
|
@ -481,7 +482,7 @@ func (a *Admin) checkUserAndPass(password, ip string) error {
|
|||
if err := a.CanLogin(ip); err != nil {
|
||||
return err
|
||||
}
|
||||
if a.Password == "" || password == "" {
|
||||
if a.Password == "" || strings.TrimSpace(password) == "" {
|
||||
return errors.New("credentials cannot be null or empty")
|
||||
}
|
||||
match, err := a.CheckPassword(password)
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !nobolt
|
||||
// +build !nobolt
|
||||
|
||||
package dataprovider
|
||||
|
||||
|
|
@ -31,6 +30,7 @@ import (
|
|||
"time"
|
||||
|
||||
bolt "go.etcd.io/bbolt"
|
||||
bolterrors "go.etcd.io/bbolt/errors"
|
||||
|
||||
"github.com/drakkan/sftpgo/v2/internal/logger"
|
||||
"github.com/drakkan/sftpgo/v2/internal/util"
|
||||
|
|
@ -39,7 +39,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
boltDatabaseVersion = 29
|
||||
boltDatabaseVersion = 32
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -2134,11 +2134,11 @@ func (p *BoltProvider) addSharedSession(_ Session) error {
|
|||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (p *BoltProvider) deleteSharedSession(_ string) error {
|
||||
func (p *BoltProvider) deleteSharedSession(_ string, _ SessionType) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (p *BoltProvider) getSharedSession(_ string) (Session, error) {
|
||||
func (p *BoltProvider) getSharedSession(_ string, _ SessionType) (Session, error) {
|
||||
return Session{}, ErrNotImplemented
|
||||
}
|
||||
|
||||
|
|
@ -3185,6 +3185,13 @@ func (p *BoltProvider) migrateDatabase() error {
|
|||
providerLog(logger.LevelError, "%v", err)
|
||||
logger.ErrorToConsole("%v", err)
|
||||
return err
|
||||
case version == 29, version == 30, version == 31:
|
||||
logger.InfoToConsole("updating database schema version: %d -> 32", version)
|
||||
providerLog(logger.LevelInfo, "updating database schema version: %d -> 32", version)
|
||||
if err := updateEventActions(); err != nil {
|
||||
return err
|
||||
}
|
||||
return updateBoltDatabaseVersion(p.dbHandle, 32)
|
||||
default:
|
||||
if version > boltDatabaseVersion {
|
||||
providerLog(logger.LevelError, "database schema version %d is newer than the supported one: %d", version,
|
||||
|
|
@ -3206,6 +3213,15 @@ func (p *BoltProvider) revertDatabase(targetVersion int) error { //nolint:gocycl
|
|||
return errors.New("current version match target version, nothing to do")
|
||||
}
|
||||
switch dbVersion.Version {
|
||||
case 30, 31, 32:
|
||||
logger.InfoToConsole("downgrading database schema version: %d -> 29", dbVersion.Version)
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: %d -> 29", dbVersion.Version)
|
||||
if dbVersion.Version == 32 {
|
||||
if err := restoreEventActions(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
return updateBoltDatabaseVersion(p.dbHandle, 29)
|
||||
default:
|
||||
return fmt.Errorf("database schema version not handled: %v", dbVersion.Version)
|
||||
}
|
||||
|
|
@ -3215,7 +3231,7 @@ func (p *BoltProvider) resetDatabase() error {
|
|||
return p.dbHandle.Update(func(tx *bolt.Tx) error {
|
||||
for _, bucketName := range boltBuckets {
|
||||
err := tx.DeleteBucket(bucketName)
|
||||
if err != nil && !errors.Is(err, bolt.ErrBucketNotFound) {
|
||||
if err != nil && !errors.Is(err, bolterrors.ErrBucketNotFound) {
|
||||
return fmt.Errorf("unable to remove bucket %v: %w", bucketName, err)
|
||||
}
|
||||
}
|
||||
|
|
@ -3946,7 +3962,7 @@ func getBoltDatabaseVersion(dbHandle *bolt.DB) (schemaVersion, error) {
|
|||
return dbVersion, err
|
||||
}
|
||||
|
||||
/*func updateBoltDatabaseVersion(dbHandle *bolt.DB, version int) error {
|
||||
func updateBoltDatabaseVersion(dbHandle *bolt.DB, version int) error {
|
||||
err := dbHandle.Update(func(tx *bolt.Tx) error {
|
||||
bucket := tx.Bucket(dbVersionBucket)
|
||||
if bucket == nil {
|
||||
|
|
@ -3962,4 +3978,4 @@ func getBoltDatabaseVersion(dbHandle *bolt.DB) (schemaVersion, error) {
|
|||
return bucket.Put(dbVersionKey, buf)
|
||||
})
|
||||
return err
|
||||
}*/
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build nobolt
|
||||
// +build nobolt
|
||||
|
||||
package dataprovider
|
||||
|
||||
|
|
|
|||
|
|
@ -27,6 +27,7 @@ import (
|
|||
"crypto/sha512"
|
||||
"crypto/subtle"
|
||||
"crypto/x509"
|
||||
"database/sql"
|
||||
"encoding/base64"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
|
|
@ -90,7 +91,7 @@ const (
|
|||
CockroachDataProviderName = "cockroachdb"
|
||||
// DumpVersion defines the version for the dump.
|
||||
// For restore/load we support the current version and the previous one
|
||||
DumpVersion = 16
|
||||
DumpVersion = 17
|
||||
|
||||
argonPwdPrefix = "$argon2id$"
|
||||
bcryptPwdPrefix = "$2a$"
|
||||
|
|
@ -824,8 +825,8 @@ type Provider interface {
|
|||
cleanupActiveTransfers(before time.Time) error
|
||||
getActiveTransfers(from time.Time) ([]ActiveTransfer, error)
|
||||
addSharedSession(session Session) error
|
||||
deleteSharedSession(key string) error
|
||||
getSharedSession(key string) (Session, error)
|
||||
deleteSharedSession(key string, sessionType SessionType) error
|
||||
getSharedSession(key string, sessionType SessionType) (Session, error)
|
||||
cleanupSharedSessions(sessionType SessionType, before int64) error
|
||||
getEventActions(limit, offset int, order string, minimal bool) ([]BaseEventAction, error)
|
||||
dumpEventActions() ([]BaseEventAction, error)
|
||||
|
|
@ -2244,8 +2245,8 @@ func AddSharedSession(session Session) error {
|
|||
}
|
||||
|
||||
// DeleteSharedSession deletes the session with the specified key
|
||||
func DeleteSharedSession(key string) error {
|
||||
err := provider.deleteSharedSession(key)
|
||||
func DeleteSharedSession(key string, sessionType SessionType) error {
|
||||
err := provider.deleteSharedSession(key, sessionType)
|
||||
if err != nil {
|
||||
providerLog(logger.LevelError, "unable to add shared session, key %q, err: %v", key, err)
|
||||
}
|
||||
|
|
@ -2253,8 +2254,8 @@ func DeleteSharedSession(key string) error {
|
|||
}
|
||||
|
||||
// GetSharedSession retrieves the session with the specified key
|
||||
func GetSharedSession(key string) (Session, error) {
|
||||
return provider.getSharedSession(key)
|
||||
func GetSharedSession(key string, sessionType SessionType) (Session, error) {
|
||||
return provider.getSharedSession(key, sessionType)
|
||||
}
|
||||
|
||||
// CleanupSharedSessions removes the shared session with the specified type and
|
||||
|
|
@ -2557,6 +2558,17 @@ func DumpData(scopes []string) (BackupData, error) {
|
|||
func ParseDumpData(data []byte) (BackupData, error) {
|
||||
var dump BackupData
|
||||
err := json.Unmarshal(data, &dump)
|
||||
if err != nil {
|
||||
return dump, err
|
||||
}
|
||||
if dump.Version < 17 {
|
||||
providerLog(logger.LevelInfo, "updating placeholders for actions restored from dump version %d", dump.Version)
|
||||
eventActions, err := updateEventActionPlaceholders(dump.EventActions)
|
||||
if err != nil {
|
||||
return dump, fmt.Errorf("unable to update event action placeholders for dump version %d: %w", dump.Version, err)
|
||||
}
|
||||
dump.EventActions = eventActions
|
||||
}
|
||||
return dump, err
|
||||
}
|
||||
|
||||
|
|
@ -3525,7 +3537,7 @@ func checkUserAndPass(user *User, password, ip, protocol string) (User, error) {
|
|||
if err != nil {
|
||||
return *user, ErrInvalidCredentials
|
||||
}
|
||||
if user.Password == "" || password == "" {
|
||||
if user.Password == "" || strings.TrimSpace(password) == "" {
|
||||
return *user, errors.New("credentials cannot be null or empty")
|
||||
}
|
||||
if !user.Filters.Hooks.CheckPasswordDisabled {
|
||||
|
|
@ -3700,7 +3712,8 @@ func comparePbkdf2PasswordAndHash(password, hashedPassword string) (bool, error)
|
|||
}
|
||||
|
||||
func getSSLMode() string {
|
||||
if config.Driver == PGSQLDataProviderName || config.Driver == CockroachDataProviderName {
|
||||
switch config.Driver {
|
||||
case PGSQLDataProviderName, CockroachDataProviderName:
|
||||
switch config.SSLMode {
|
||||
case 0:
|
||||
return "disable"
|
||||
|
|
@ -3715,7 +3728,7 @@ func getSSLMode() string {
|
|||
case 5:
|
||||
return "allow"
|
||||
}
|
||||
} else if config.Driver == MySQLDataProviderName {
|
||||
case MySQLDataProviderName:
|
||||
if config.requireCustomTLSForMySQL() {
|
||||
return "custom"
|
||||
}
|
||||
|
|
@ -4242,18 +4255,19 @@ func executePreLoginHook(username, loginMethod, ip, protocol string, oidcTokenFi
|
|||
u.Filters.TOTPConfig = totpConfig
|
||||
u.Filters.RecoveryCodes = recoveryCodes
|
||||
err = provider.updateUser(&u)
|
||||
if err == nil {
|
||||
webDAVUsersCache.swap(&u, "")
|
||||
}
|
||||
}
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
providerLog(logger.LevelDebug, "user %q added/updated from pre-login hook response, id: %d", username, userID)
|
||||
if userID == 0 {
|
||||
return provider.userExists(username, "")
|
||||
user, err := provider.userExists(username, "")
|
||||
if err != nil {
|
||||
return u, err
|
||||
}
|
||||
return u, nil
|
||||
providerLog(logger.LevelDebug, "user %q added/updated from pre-login hook response, id: %d", username, userID)
|
||||
if userID > 0 {
|
||||
webDAVUsersCache.swap(&user, "")
|
||||
}
|
||||
return user, nil
|
||||
}
|
||||
|
||||
// ExecutePostLoginHook executes the post login hook if defined
|
||||
|
|
@ -4671,6 +4685,176 @@ func isExternalAuthConfigured(loginMethod string) bool {
|
|||
}
|
||||
}
|
||||
|
||||
func replaceTemplateVars(input string) string {
|
||||
var result strings.Builder
|
||||
i := 0
|
||||
for i < len(input) {
|
||||
if i+2 <= len(input) && input[i:i+2] == "{{" {
|
||||
if i+2 < len(input) {
|
||||
nextChar := input[i+2]
|
||||
if nextChar == ' ' || nextChar == '.' || nextChar == '-' {
|
||||
// Don't replace if followed by space, dot or minus.
|
||||
result.WriteString("{{")
|
||||
i += 2
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
// Find the closing "}}"
|
||||
closing := strings.Index(input[i:], "}}")
|
||||
if closing != -1 {
|
||||
// Replace with {{. only if it's a proper template variable.
|
||||
result.WriteString("{{.")
|
||||
result.WriteString(input[i+2 : i+closing])
|
||||
result.WriteString("}}")
|
||||
i += closing + 2
|
||||
continue
|
||||
}
|
||||
}
|
||||
result.WriteByte(input[i])
|
||||
i++
|
||||
}
|
||||
return result.String()
|
||||
}
|
||||
|
||||
func restoreTemplateVars(input string) string {
|
||||
var result strings.Builder
|
||||
i := 0
|
||||
|
||||
for i < len(input) {
|
||||
if i+3 <= len(input) && input[i:i+3] == "{{." {
|
||||
if i+3 < len(input) {
|
||||
nextChar := input[i+3]
|
||||
if nextChar == ' ' || nextChar == '.' || nextChar == '-' {
|
||||
// Don't change if it's a space, dot, or minus
|
||||
result.WriteString("{{.")
|
||||
i += 3
|
||||
continue
|
||||
}
|
||||
}
|
||||
// Find the closing "}}"
|
||||
closing := strings.Index(input[i:], "}}")
|
||||
if closing != -1 {
|
||||
// Strip the dot and write the rest
|
||||
result.WriteString("{{")
|
||||
result.WriteString(input[i+3 : i+closing])
|
||||
result.WriteString("}}")
|
||||
i += closing + 2
|
||||
continue
|
||||
}
|
||||
}
|
||||
|
||||
result.WriteByte(input[i])
|
||||
i++
|
||||
}
|
||||
|
||||
return result.String()
|
||||
}
|
||||
|
||||
func updateEventActionPlaceholders(actions []BaseEventAction) ([]BaseEventAction, error) {
|
||||
var result []BaseEventAction
|
||||
|
||||
for _, action := range actions {
|
||||
options, err := json.Marshal(action.Options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
convertedOptions := replaceTemplateVars(string(options))
|
||||
var opts BaseEventActionOptions
|
||||
err = json.Unmarshal([]byte(convertedOptions), &opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
action.Options = opts
|
||||
result = append(result, action)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func restoreEventActionsPlaceholders(actions []BaseEventAction) ([]BaseEventAction, error) {
|
||||
var result []BaseEventAction
|
||||
|
||||
for _, action := range actions {
|
||||
options, err := json.Marshal(action.Options)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
convertedOptions := restoreTemplateVars(string(options))
|
||||
var opts BaseEventActionOptions
|
||||
err = json.Unmarshal([]byte(convertedOptions), &opts)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
action.Options = opts
|
||||
result = append(result, action)
|
||||
}
|
||||
|
||||
return result, nil
|
||||
}
|
||||
|
||||
func updateEventActions() error {
|
||||
actions, err := provider.dumpEventActions()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
convertedActions, err := updateEventActionPlaceholders(actions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, action := range convertedActions {
|
||||
providerLog(logger.LevelInfo, "updating placeholders for event action %q", action.Name)
|
||||
if err := provider.updateEventAction(&action); err != nil {
|
||||
return fmt.Errorf("unable to save updated event action %q: %w", action.Name, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func restoreEventActions() error {
|
||||
actions, err := provider.dumpEventActions()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
convertedActions, err := restoreEventActionsPlaceholders(actions)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
for _, action := range convertedActions {
|
||||
providerLog(logger.LevelInfo, "restoring placeholders for event action %q", action.Name)
|
||||
if err := provider.updateEventAction(&action); err != nil {
|
||||
return fmt.Errorf("unable to save updated event action %q: %w", action.Name, err)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func updateSQLDatabaseFrom31To32(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database data version: 31 -> 32")
|
||||
providerLog(logger.LevelInfo, "updating database data version: 31 -> 32")
|
||||
|
||||
if err := updateEventActions(); err != nil {
|
||||
return err
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), longSQLQueryTimeout)
|
||||
defer cancel()
|
||||
|
||||
return sqlCommonUpdateDatabaseVersion(ctx, dbHandle, 32)
|
||||
}
|
||||
|
||||
func downgradeSQLDatabaseFrom32To31(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database data version: 32 -> 31")
|
||||
providerLog(logger.LevelInfo, "downgrading database data version: 32 -> 31")
|
||||
|
||||
if err := restoreEventActions(); err != nil {
|
||||
return err
|
||||
}
|
||||
ctx, cancel := context.WithTimeout(context.Background(), longSQLQueryTimeout)
|
||||
defer cancel()
|
||||
|
||||
return sqlCommonUpdateDatabaseVersion(ctx, dbHandle, 31)
|
||||
}
|
||||
|
||||
func getConfigPath(name, configDir string) string {
|
||||
if !util.IsFileInputValid(name) {
|
||||
return ""
|
||||
|
|
|
|||
|
|
@ -418,6 +418,10 @@ func (l *IPList) IsListed(ip, protocol string) (bool, int, error) {
|
|||
l.mu.RLock()
|
||||
defer l.mu.RUnlock()
|
||||
|
||||
if l.Ranges.Len() == 0 {
|
||||
return false, 0, nil
|
||||
}
|
||||
|
||||
parsedIP := net.ParseIP(ip)
|
||||
if parsedIP == nil {
|
||||
return false, 0, fmt.Errorf("invalid IP %s", ip)
|
||||
|
|
|
|||
|
|
@ -2117,11 +2117,11 @@ func (p *MemoryProvider) addSharedSession(_ Session) error {
|
|||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (p *MemoryProvider) deleteSharedSession(_ string) error {
|
||||
func (p *MemoryProvider) deleteSharedSession(_ string, _ SessionType) error {
|
||||
return ErrNotImplemented
|
||||
}
|
||||
|
||||
func (p *MemoryProvider) getSharedSession(_ string) (Session, error) {
|
||||
func (p *MemoryProvider) getSharedSession(_ string, _ SessionType) (Session, error) {
|
||||
return Session{}, ErrNotImplemented
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !nomysql
|
||||
// +build !nomysql
|
||||
|
||||
package dataprovider
|
||||
|
||||
|
|
@ -194,6 +193,18 @@ const (
|
|||
"CREATE INDEX `{{prefix}}ip_lists_deleted_at_idx` ON `{{ip_lists}}` (`deleted_at`);" +
|
||||
"CREATE INDEX `{{prefix}}ip_lists_first_last_idx` ON `{{ip_lists}}` (`first`, `last`);" +
|
||||
"INSERT INTO {{schema_version}} (version) VALUES (29);"
|
||||
mysqlV30SQL = "ALTER TABLE `{{shares}}` ADD COLUMN `options` longtext NULL;"
|
||||
mysqlV30DownSQL = "ALTER TABLE `{{shares}}` DROP COLUMN `options`;"
|
||||
mysqlV31SQL = "DROP TABLE IF EXISTS `{{shared_sessions}}` CASCADE;" +
|
||||
"CREATE TABLE `{{shared_sessions}}` (`key` varchar(128) NOT NULL, `type` integer NOT NULL, `data` longtext NOT NULL, " +
|
||||
"`timestamp` bigint NOT NULL, PRIMARY KEY (`key`, `type`));" +
|
||||
"CREATE INDEX `{{prefix}}shared_sessions_type_idx` ON `{{shared_sessions}}` (`type`);" +
|
||||
"CREATE INDEX `{{prefix}}shared_sessions_timestamp_idx` ON `{{shared_sessions}}` (`timestamp`);"
|
||||
mysqlV31DownSQL = "DROP TABLE IF EXISTS `{{shared_sessions}}` CASCADE;" +
|
||||
"CREATE TABLE `{{shared_sessions}}` (`key` varchar(128) NOT NULL PRIMARY KEY, " +
|
||||
"`data` longtext NOT NULL, `type` integer NOT NULL, `timestamp` bigint NOT NULL);" +
|
||||
"CREATE INDEX `{{prefix}}shared_sessions_type_idx` ON `{{shared_sessions}}` (`type`);" +
|
||||
"CREATE INDEX `{{prefix}}shared_sessions_timestamp_idx` ON `{{shared_sessions}}` (`timestamp`);"
|
||||
)
|
||||
|
||||
// MySQLProvider defines the auth provider for MySQL/MariaDB database
|
||||
|
|
@ -587,12 +598,12 @@ func (p *MySQLProvider) addSharedSession(session Session) error {
|
|||
return sqlCommonAddSession(session, p.dbHandle)
|
||||
}
|
||||
|
||||
func (p *MySQLProvider) deleteSharedSession(key string) error {
|
||||
return sqlCommonDeleteSession(key, p.dbHandle)
|
||||
func (p *MySQLProvider) deleteSharedSession(key string, sessionType SessionType) error {
|
||||
return sqlCommonDeleteSession(key, sessionType, p.dbHandle)
|
||||
}
|
||||
|
||||
func (p *MySQLProvider) getSharedSession(key string) (Session, error) {
|
||||
return sqlCommonGetSession(key, p.dbHandle)
|
||||
func (p *MySQLProvider) getSharedSession(key string, sessionType SessionType) (Session, error) {
|
||||
return sqlCommonGetSession(key, sessionType, p.dbHandle)
|
||||
}
|
||||
|
||||
func (p *MySQLProvider) cleanupSharedSessions(sessionType SessionType, before int64) error {
|
||||
|
|
@ -802,6 +813,12 @@ func (p *MySQLProvider) migrateDatabase() error {
|
|||
providerLog(logger.LevelError, "%v", err)
|
||||
logger.ErrorToConsole("%v", err)
|
||||
return err
|
||||
case version == 29:
|
||||
return updateMySQLDatabaseFromV29(p.dbHandle)
|
||||
case version == 30:
|
||||
return updateMySQLDatabaseFromV30(p.dbHandle)
|
||||
case version == 31:
|
||||
return updateMySQLDatabaseFromV31(p.dbHandle)
|
||||
default:
|
||||
if version > sqlDatabaseVersion {
|
||||
providerLog(logger.LevelError, "database schema version %d is newer than the supported one: %d", version,
|
||||
|
|
@ -824,6 +841,12 @@ func (p *MySQLProvider) revertDatabase(targetVersion int) error {
|
|||
}
|
||||
|
||||
switch dbVersion.Version {
|
||||
case 30:
|
||||
return downgradeMySQLDatabaseFromV30(p.dbHandle)
|
||||
case 31:
|
||||
return downgradeMySQLDatabaseFromV31(p.dbHandle)
|
||||
case 32:
|
||||
return downgradeMySQLDatabaseFromV32(p.dbHandle)
|
||||
default:
|
||||
return fmt.Errorf("database schema version not handled: %d", dbVersion.Version)
|
||||
}
|
||||
|
|
@ -861,3 +884,73 @@ func (p *MySQLProvider) normalizeError(err error, fieldType int) error {
|
|||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func updateMySQLDatabaseFromV29(dbHandle *sql.DB) error {
|
||||
if err := updateMySQLDatabaseFrom29To30(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return updateMySQLDatabaseFromV30(dbHandle)
|
||||
}
|
||||
|
||||
func updateMySQLDatabaseFromV30(dbHandle *sql.DB) error {
|
||||
if err := updateMySQLDatabaseFrom30To31(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return updateMySQLDatabaseFromV31(dbHandle)
|
||||
}
|
||||
|
||||
func updateMySQLDatabaseFromV31(dbHandle *sql.DB) error {
|
||||
return updateSQLDatabaseFrom31To32(dbHandle)
|
||||
}
|
||||
|
||||
func downgradeMySQLDatabaseFromV30(dbHandle *sql.DB) error {
|
||||
return downgradeMySQLDatabaseFrom30To29(dbHandle)
|
||||
}
|
||||
|
||||
func downgradeMySQLDatabaseFromV31(dbHandle *sql.DB) error {
|
||||
if err := downgradeMySQLDatabaseFrom31To30(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return downgradeMySQLDatabaseFromV30(dbHandle)
|
||||
}
|
||||
|
||||
func downgradeMySQLDatabaseFromV32(dbHandle *sql.DB) error {
|
||||
if err := downgradeSQLDatabaseFrom32To31(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return downgradeMySQLDatabaseFromV31(dbHandle)
|
||||
}
|
||||
|
||||
func updateMySQLDatabaseFrom29To30(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 29 -> 30")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 29 -> 30")
|
||||
|
||||
sql := strings.ReplaceAll(mysqlV30SQL, "{{shares}}", sqlTableShares)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, strings.Split(sql, ";"), 30, true)
|
||||
}
|
||||
|
||||
func downgradeMySQLDatabaseFrom30To29(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 30 -> 29")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 30 -> 29")
|
||||
|
||||
sql := strings.ReplaceAll(mysqlV30DownSQL, "{{shares}}", sqlTableShares)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, strings.Split(sql, ";"), 29, false)
|
||||
}
|
||||
|
||||
func updateMySQLDatabaseFrom30To31(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 30 -> 31")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 30 -> 31")
|
||||
|
||||
sql := strings.ReplaceAll(mysqlV31SQL, "{{shared_sessions}}", sqlTableSharedSessions)
|
||||
sql = strings.ReplaceAll(sql, "{{prefix}}", config.SQLTablesPrefix)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, strings.Split(sql, ";"), 31, true)
|
||||
}
|
||||
|
||||
func downgradeMySQLDatabaseFrom31To30(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 31 -> 30")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 31 -> 30")
|
||||
|
||||
sql := strings.ReplaceAll(mysqlV31DownSQL, "{{shared_sessions}}", sqlTableSharedSessions)
|
||||
sql = strings.ReplaceAll(sql, "{{prefix}}", config.SQLTablesPrefix)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, strings.Split(sql, ";"), 30, false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build nomysql
|
||||
// +build nomysql
|
||||
|
||||
package dataprovider
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !nopgsql
|
||||
// +build !nopgsql
|
||||
|
||||
package dataprovider
|
||||
|
||||
|
|
@ -210,6 +209,19 @@ INSERT INTO {{schema_version}} (version) VALUES (29);
|
|||
`
|
||||
// not supported in CockroachDB
|
||||
ipListsLikeIndex = `CREATE INDEX "{{prefix}}ip_lists_ipornet_like_idx" ON "{{ip_lists}}" ("ipornet" varchar_pattern_ops);`
|
||||
pgsqlV30SQL = `ALTER TABLE "{{shares}}" ADD COLUMN "options" text NULL;`
|
||||
pgsqlV30DownSQL = `ALTER TABLE "{{shares}}" DROP COLUMN "options" CASCADE;`
|
||||
pgsqlV31SQL = `DROP TABLE "{{shared_sessions}}";
|
||||
CREATE TABLE "{{shared_sessions}}" ("key" varchar(128) NOT NULL, "type" integer NOT NULL,
|
||||
"data" text NOT NULL, "timestamp" bigint NOT NULL, PRIMARY KEY ("key", "type"));
|
||||
CREATE INDEX "{{prefix}}shared_sessions_type_idx" ON "{{shared_sessions}}" ("type");
|
||||
CREATE INDEX "{{prefix}}shared_sessions_timestamp_idx" ON "{{shared_sessions}}" ("timestamp");
|
||||
`
|
||||
pgsqlV31DownSQL = `DROP TABLE "{{shared_sessions}}" CASCADE;
|
||||
CREATE TABLE "{{shared_sessions}}" ("key" varchar(128) NOT NULL PRIMARY KEY,
|
||||
"data" text NOT NULL, "type" integer NOT NULL, "timestamp" bigint NOT NULL);
|
||||
CREATE INDEX "{{prefix}}shared_sessions_type_idx" ON "{{shared_sessions}}" ("type");
|
||||
CREATE INDEX "{{prefix}}shared_sessions_timestamp_idx" ON "{{shared_sessions}}" ("timestamp");`
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
@ -605,12 +617,12 @@ func (p *PGSQLProvider) addSharedSession(session Session) error {
|
|||
return sqlCommonAddSession(session, p.dbHandle)
|
||||
}
|
||||
|
||||
func (p *PGSQLProvider) deleteSharedSession(key string) error {
|
||||
return sqlCommonDeleteSession(key, p.dbHandle)
|
||||
func (p *PGSQLProvider) deleteSharedSession(key string, sessionType SessionType) error {
|
||||
return sqlCommonDeleteSession(key, sessionType, p.dbHandle)
|
||||
}
|
||||
|
||||
func (p *PGSQLProvider) getSharedSession(key string) (Session, error) {
|
||||
return sqlCommonGetSession(key, p.dbHandle)
|
||||
func (p *PGSQLProvider) getSharedSession(key string, sessionType SessionType) (Session, error) {
|
||||
return sqlCommonGetSession(key, sessionType, p.dbHandle)
|
||||
}
|
||||
|
||||
func (p *PGSQLProvider) cleanupSharedSessions(sessionType SessionType, before int64) error {
|
||||
|
|
@ -826,6 +838,12 @@ func (p *PGSQLProvider) migrateDatabase() error { //nolint:dupl
|
|||
providerLog(logger.LevelError, "%v", err)
|
||||
logger.ErrorToConsole("%v", err)
|
||||
return err
|
||||
case version == 29:
|
||||
return updatePGSQLDatabaseFromV29(p.dbHandle)
|
||||
case version == 30:
|
||||
return updatePGSQLDatabaseFromV30(p.dbHandle)
|
||||
case version == 31:
|
||||
return updatePGSQLDatabaseFromV31(p.dbHandle)
|
||||
default:
|
||||
if version > sqlDatabaseVersion {
|
||||
providerLog(logger.LevelError, "database schema version %d is newer than the supported one: %d", version,
|
||||
|
|
@ -848,6 +866,12 @@ func (p *PGSQLProvider) revertDatabase(targetVersion int) error {
|
|||
}
|
||||
|
||||
switch dbVersion.Version {
|
||||
case 30:
|
||||
return downgradePGSQLDatabaseFromV30(p.dbHandle)
|
||||
case 31:
|
||||
return downgradePGSQLDatabaseFromV31(p.dbHandle)
|
||||
case 32:
|
||||
return downgradePGSQLDatabaseFromV32(p.dbHandle)
|
||||
default:
|
||||
return fmt.Errorf("database schema version not handled: %d", dbVersion.Version)
|
||||
}
|
||||
|
|
@ -885,3 +909,73 @@ func (p *PGSQLProvider) normalizeError(err error, fieldType int) error {
|
|||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func updatePGSQLDatabaseFromV29(dbHandle *sql.DB) error {
|
||||
if err := updatePGSQLDatabaseFrom29To30(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return updatePGSQLDatabaseFromV30(dbHandle)
|
||||
}
|
||||
|
||||
func updatePGSQLDatabaseFromV30(dbHandle *sql.DB) error {
|
||||
if err := updatePGSQLDatabaseFrom30To31(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return updatePGSQLDatabaseFromV31(dbHandle)
|
||||
}
|
||||
|
||||
func updatePGSQLDatabaseFromV31(dbHandle *sql.DB) error {
|
||||
return updateSQLDatabaseFrom31To32(dbHandle)
|
||||
}
|
||||
|
||||
func downgradePGSQLDatabaseFromV30(dbHandle *sql.DB) error {
|
||||
return downgradePGSQLDatabaseFrom30To29(dbHandle)
|
||||
}
|
||||
|
||||
func downgradePGSQLDatabaseFromV31(dbHandle *sql.DB) error {
|
||||
if err := downgradePGSQLDatabaseFrom31To30(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return downgradePGSQLDatabaseFromV30(dbHandle)
|
||||
}
|
||||
|
||||
func downgradePGSQLDatabaseFromV32(dbHandle *sql.DB) error {
|
||||
if err := downgradeSQLDatabaseFrom32To31(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return downgradePGSQLDatabaseFromV31(dbHandle)
|
||||
}
|
||||
|
||||
func updatePGSQLDatabaseFrom29To30(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 29 -> 30")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 29 -> 30")
|
||||
|
||||
sql := strings.ReplaceAll(pgsqlV30SQL, "{{shares}}", sqlTableShares)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 30, true)
|
||||
}
|
||||
|
||||
func downgradePGSQLDatabaseFrom30To29(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 30 -> 29")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 30 -> 29")
|
||||
|
||||
sql := strings.ReplaceAll(pgsqlV30DownSQL, "{{shares}}", sqlTableShares)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 29, false)
|
||||
}
|
||||
|
||||
func updatePGSQLDatabaseFrom30To31(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 30 -> 31")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 30 -> 31")
|
||||
|
||||
sql := strings.ReplaceAll(pgsqlV31SQL, "{{shared_sessions}}", sqlTableSharedSessions)
|
||||
sql = strings.ReplaceAll(sql, "{{prefix}}", config.SQLTablesPrefix)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 31, true)
|
||||
}
|
||||
|
||||
func downgradePGSQLDatabaseFrom31To30(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 31 -> 30")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 31 -> 30")
|
||||
|
||||
sql := strings.ReplaceAll(pgsqlV31DownSQL, "{{shared_sessions}}", sqlTableSharedSessions)
|
||||
sql = strings.ReplaceAll(sql, "{{prefix}}", config.SQLTablesPrefix)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 30, false)
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build nopgsql
|
||||
// +build nopgsql
|
||||
|
||||
package dataprovider
|
||||
|
||||
|
|
|
|||
|
|
@ -36,7 +36,7 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
sqlDatabaseVersion = 29
|
||||
sqlDatabaseVersion = 32
|
||||
defaultSQLQueryTimeout = 10 * time.Second
|
||||
longSQLQueryTimeout = 60 * time.Second
|
||||
)
|
||||
|
|
@ -3265,14 +3265,14 @@ func sqlCommonAddSession(session Session, dbHandle *sql.DB) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func sqlCommonGetSession(key string, dbHandle sqlQuerier) (Session, error) {
|
||||
func sqlCommonGetSession(key string, sessionType SessionType, dbHandle sqlQuerier) (Session, error) {
|
||||
var session Session
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
|
||||
defer cancel()
|
||||
|
||||
q := getSessionQuery()
|
||||
var data []byte // type hint, some driver will use string instead of []byte if the type is any
|
||||
err := dbHandle.QueryRowContext(ctx, q, key).Scan(&session.Key, &data, &session.Type, &session.Timestamp)
|
||||
err := dbHandle.QueryRowContext(ctx, q, key, sessionType).Scan(&session.Key, &data, &session.Type, &session.Timestamp)
|
||||
if err != nil {
|
||||
if errors.Is(err, sql.ErrNoRows) {
|
||||
return session, util.NewRecordNotFoundError(err.Error())
|
||||
|
|
@ -3283,12 +3283,12 @@ func sqlCommonGetSession(key string, dbHandle sqlQuerier) (Session, error) {
|
|||
return session, nil
|
||||
}
|
||||
|
||||
func sqlCommonDeleteSession(key string, dbHandle *sql.DB) error {
|
||||
func sqlCommonDeleteSession(key string, sessionType SessionType, dbHandle *sql.DB) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), defaultSQLQueryTimeout)
|
||||
defer cancel()
|
||||
|
||||
q := getDeleteSessionQuery()
|
||||
res, err := dbHandle.ExecContext(ctx, q, key)
|
||||
res, err := dbHandle.ExecContext(ctx, q, key, sessionType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !nosqlite && cgo
|
||||
// +build !nosqlite,cgo
|
||||
|
||||
package dataprovider
|
||||
|
||||
|
|
@ -24,6 +23,7 @@ import (
|
|||
"errors"
|
||||
"fmt"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/mattn/go-sqlite3"
|
||||
|
|
@ -179,6 +179,20 @@ CREATE INDEX "{{prefix}}ip_lists_ip_updated_at_idx" ON "{{ip_lists}}" ("updated_
|
|||
CREATE INDEX "{{prefix}}ip_lists_ip_deleted_at_idx" ON "{{ip_lists}}" ("deleted_at");
|
||||
CREATE INDEX "{{prefix}}ip_lists_first_last_idx" ON "{{ip_lists}}" ("first", "last");
|
||||
INSERT INTO {{schema_version}} (version) VALUES (29);
|
||||
`
|
||||
sqliteV30SQL = `ALTER TABLE "{{shares}}" ADD COLUMN "options" text NULL;`
|
||||
sqliteV30DownSQL = `ALTER TABLE "{{shares}}" DROP COLUMN "options";`
|
||||
sqliteV31SQL = `DROP TABLE "{{shared_sessions}}";
|
||||
CREATE TABLE "{{shared_sessions}}" ("key" varchar(128) NOT NULL, "type" integer NOT NULL,
|
||||
"data" text NOT NULL, "timestamp" bigint NOT NULL, PRIMARY KEY ("key", "type"));
|
||||
CREATE INDEX "{{prefix}}shared_sessions_type_idx" ON "{{shared_sessions}}" ("type");
|
||||
CREATE INDEX "{{prefix}}shared_sessions_timestamp_idx" ON "{{shared_sessions}}" ("timestamp");
|
||||
`
|
||||
sqliteV31DownSQL = `DROP TABLE "{{shared_sessions}}";
|
||||
CREATE TABLE "{{shared_sessions}}" ("key" varchar(128) NOT NULL PRIMARY KEY, "data" text NOT NULL,
|
||||
"type" integer NOT NULL, "timestamp" bigint NOT NULL);
|
||||
CREATE INDEX "{{prefix}}shared_sessions_type_idx" ON "{{shared_sessions}}" ("type");
|
||||
CREATE INDEX "{{prefix}}shared_sessions_timestamp_idx" ON "{{shared_sessions}}" ("timestamp");
|
||||
`
|
||||
)
|
||||
|
||||
|
|
@ -508,12 +522,12 @@ func (p *SQLiteProvider) addSharedSession(session Session) error {
|
|||
return sqlCommonAddSession(session, p.dbHandle)
|
||||
}
|
||||
|
||||
func (p *SQLiteProvider) deleteSharedSession(key string) error {
|
||||
return sqlCommonDeleteSession(key, p.dbHandle)
|
||||
func (p *SQLiteProvider) deleteSharedSession(key string, sessionType SessionType) error {
|
||||
return sqlCommonDeleteSession(key, sessionType, p.dbHandle)
|
||||
}
|
||||
|
||||
func (p *SQLiteProvider) getSharedSession(key string) (Session, error) {
|
||||
return sqlCommonGetSession(key, p.dbHandle)
|
||||
func (p *SQLiteProvider) getSharedSession(key string, sessionType SessionType) (Session, error) {
|
||||
return sqlCommonGetSession(key, sessionType, p.dbHandle)
|
||||
}
|
||||
|
||||
func (p *SQLiteProvider) cleanupSharedSessions(sessionType SessionType, before int64) error {
|
||||
|
|
@ -722,6 +736,12 @@ func (p *SQLiteProvider) migrateDatabase() error { //nolint:dupl
|
|||
providerLog(logger.LevelError, "%v", err)
|
||||
logger.ErrorToConsole("%v", err)
|
||||
return err
|
||||
case version == 29:
|
||||
return updateSQLiteDatabaseFromV29(p.dbHandle)
|
||||
case version == 30:
|
||||
return updateSQLiteDatabaseFromV30(p.dbHandle)
|
||||
case version == 31:
|
||||
return updateSQLiteDatabaseFromV31(p.dbHandle)
|
||||
default:
|
||||
if version > sqlDatabaseVersion {
|
||||
providerLog(logger.LevelError, "database schema version %d is newer than the supported one: %d", version,
|
||||
|
|
@ -744,6 +764,12 @@ func (p *SQLiteProvider) revertDatabase(targetVersion int) error {
|
|||
}
|
||||
|
||||
switch dbVersion.Version {
|
||||
case 30:
|
||||
return downgradeSQLiteDatabaseFromV30(p.dbHandle)
|
||||
case 31:
|
||||
return downgradeSQLiteDatabaseFromV31(p.dbHandle)
|
||||
case 32:
|
||||
return downgradeSQLiteDatabaseFromV32(p.dbHandle)
|
||||
default:
|
||||
return fmt.Errorf("database schema version not handled: %d", dbVersion.Version)
|
||||
}
|
||||
|
|
@ -789,6 +815,76 @@ func executePragmaOptimize(dbHandle *sql.DB) error {
|
|||
return err
|
||||
}
|
||||
|
||||
func updateSQLiteDatabaseFromV29(dbHandle *sql.DB) error {
|
||||
if err := updateSQLiteDatabaseFrom29To30(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return updateSQLiteDatabaseFromV30(dbHandle)
|
||||
}
|
||||
|
||||
func updateSQLiteDatabaseFromV30(dbHandle *sql.DB) error {
|
||||
if err := updateSQLiteDatabaseFrom30To31(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return updateSQLiteDatabaseFromV31(dbHandle)
|
||||
}
|
||||
|
||||
func updateSQLiteDatabaseFromV31(dbHandle *sql.DB) error {
|
||||
return updateSQLDatabaseFrom31To32(dbHandle)
|
||||
}
|
||||
|
||||
func downgradeSQLiteDatabaseFromV30(dbHandle *sql.DB) error {
|
||||
return downgradeSQLiteDatabaseFrom30To29(dbHandle)
|
||||
}
|
||||
|
||||
func downgradeSQLiteDatabaseFromV31(dbHandle *sql.DB) error {
|
||||
if err := downgradeSQLiteDatabaseFrom31To30(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return downgradeSQLiteDatabaseFromV30(dbHandle)
|
||||
}
|
||||
|
||||
func downgradeSQLiteDatabaseFromV32(dbHandle *sql.DB) error {
|
||||
if err := downgradeSQLDatabaseFrom32To31(dbHandle); err != nil {
|
||||
return err
|
||||
}
|
||||
return downgradeSQLiteDatabaseFromV31(dbHandle)
|
||||
}
|
||||
|
||||
func updateSQLiteDatabaseFrom29To30(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 29 -> 30")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 29 -> 30")
|
||||
|
||||
sql := strings.ReplaceAll(sqliteV30SQL, "{{shares}}", sqlTableShares)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 30, true)
|
||||
}
|
||||
|
||||
func downgradeSQLiteDatabaseFrom30To29(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 30 -> 29")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 30 -> 29")
|
||||
|
||||
sql := strings.ReplaceAll(sqliteV30DownSQL, "{{shares}}", sqlTableShares)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 29, false)
|
||||
}
|
||||
|
||||
func updateSQLiteDatabaseFrom30To31(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("updating database schema version: 30 -> 31")
|
||||
providerLog(logger.LevelInfo, "updating database schema version: 30 -> 31")
|
||||
|
||||
sql := strings.ReplaceAll(sqliteV31SQL, "{{shared_sessions}}", sqlTableSharedSessions)
|
||||
sql = strings.ReplaceAll(sql, "{{prefix}}", config.SQLTablesPrefix)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 31, true)
|
||||
}
|
||||
|
||||
func downgradeSQLiteDatabaseFrom31To30(dbHandle *sql.DB) error {
|
||||
logger.InfoToConsole("downgrading database schema version: 31 -> 30")
|
||||
providerLog(logger.LevelInfo, "downgrading database schema version: 31 -> 30")
|
||||
|
||||
sql := strings.ReplaceAll(sqliteV31DownSQL, "{{shared_sessions}}", sqlTableSharedSessions)
|
||||
sql = strings.ReplaceAll(sql, "{{prefix}}", config.SQLTablesPrefix)
|
||||
return sqlCommonExecSQLAndUpdateDBVersion(dbHandle, []string{sql}, 30, false)
|
||||
}
|
||||
|
||||
/*func setPragmaFK(dbHandle *sql.DB, value string) error {
|
||||
ctx, cancel := context.WithTimeout(context.Background(), longSQLQueryTimeout)
|
||||
defer cancel()
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build nosqlite || !cgo
|
||||
// +build nosqlite !cgo
|
||||
|
||||
package dataprovider
|
||||
|
||||
|
|
|
|||
|
|
@ -81,25 +81,27 @@ func getAddSessionQuery() string {
|
|||
"ON DUPLICATE KEY UPDATE `data`=VALUES(`data`), `timestamp`=VALUES(`timestamp`)",
|
||||
sqlTableSharedSessions, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
|
||||
}
|
||||
return fmt.Sprintf(`INSERT INTO %s (key,data,type,timestamp) VALUES (%s,%s,%s,%s) ON CONFLICT(key) DO UPDATE SET data=
|
||||
return fmt.Sprintf(`INSERT INTO %s (key,data,type,timestamp) VALUES (%s,%s,%s,%s) ON CONFLICT(key,type) DO UPDATE SET data=
|
||||
EXCLUDED.data, timestamp=EXCLUDED.timestamp`,
|
||||
sqlTableSharedSessions, sqlPlaceholders[0], sqlPlaceholders[1], sqlPlaceholders[2], sqlPlaceholders[3])
|
||||
}
|
||||
|
||||
func getDeleteSessionQuery() string {
|
||||
if config.Driver == MySQLDataProviderName {
|
||||
return fmt.Sprintf("DELETE FROM %s WHERE `key` = %s", sqlTableSharedSessions, sqlPlaceholders[0])
|
||||
return fmt.Sprintf("DELETE FROM %s WHERE `key` = %s AND `type` = %s",
|
||||
sqlTableSharedSessions, sqlPlaceholders[0], sqlPlaceholders[1])
|
||||
}
|
||||
return fmt.Sprintf(`DELETE FROM %s WHERE key = %s`, sqlTableSharedSessions, sqlPlaceholders[0])
|
||||
return fmt.Sprintf(`DELETE FROM %s WHERE key = %s AND type = %s`,
|
||||
sqlTableSharedSessions, sqlPlaceholders[0], sqlPlaceholders[1])
|
||||
}
|
||||
|
||||
func getSessionQuery() string {
|
||||
if config.Driver == MySQLDataProviderName {
|
||||
return fmt.Sprintf("SELECT `key`,`data`,`type`,`timestamp` FROM %s WHERE `key` = %s", sqlTableSharedSessions,
|
||||
sqlPlaceholders[0])
|
||||
return fmt.Sprintf("SELECT `key`,`data`,`type`,`timestamp` FROM %s WHERE `key` = %s AND `type` = %s",
|
||||
sqlTableSharedSessions, sqlPlaceholders[0], sqlPlaceholders[1])
|
||||
}
|
||||
return fmt.Sprintf(`SELECT key,data,type,timestamp FROM %s WHERE key = %s`, sqlTableSharedSessions,
|
||||
sqlPlaceholders[0])
|
||||
return fmt.Sprintf(`SELECT key,data,type,timestamp FROM %s WHERE key = %s AND type = %s`,
|
||||
sqlTableSharedSessions, sqlPlaceholders[0], sqlPlaceholders[1])
|
||||
}
|
||||
|
||||
func getCleanupSessionsQuery() string {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build unixcrypt && cgo
|
||||
// +build unixcrypt,cgo
|
||||
|
||||
package dataprovider
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !unixcrypt || !cgo
|
||||
// +build !unixcrypt !cgo
|
||||
|
||||
package dataprovider
|
||||
|
||||
|
|
|
|||
|
|
@ -640,6 +640,8 @@ func TestBasicFTPHandling(t *testing.T) {
|
|||
}
|
||||
err = ftpUploadFile(testFilePath, testFileName, testFileSize, client, 0)
|
||||
assert.NoError(t, err)
|
||||
_, err = client.FileSize(path.Join("/", testDir))
|
||||
assert.Error(t, err)
|
||||
size, err := client.FileSize(path.Join("/", testDir, testFileName))
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, testFileSize, size)
|
||||
|
|
|
|||
|
|
@ -287,7 +287,7 @@ func (c *Connection) RemoveDir(name string) error {
|
|||
func (c *Connection) Symlink(oldname, newname string) error {
|
||||
c.UpdateLastActivity()
|
||||
|
||||
return c.BaseConnection.CreateSymlink(oldname, newname)
|
||||
return c.CreateSymlink(oldname, newname)
|
||||
}
|
||||
|
||||
// ReadDir implements ClientDriverExtensionFilelist
|
||||
|
|
|
|||
|
|
@ -136,7 +136,7 @@ func (t *transfer) closeIO() error {
|
|||
} else if t.reader != nil {
|
||||
err = t.reader.Close()
|
||||
if metadater, ok := t.reader.(vfs.Metadater); ok {
|
||||
t.BaseTransfer.SetMetadata(metadater.Metadata())
|
||||
t.SetMetadata(metadater.Metadata())
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ func testSMTPConfig(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
}
|
||||
if req.AuthType == 3 {
|
||||
if err := req.Config.OAuth2.Validate(); err != nil {
|
||||
if err := req.OAuth2.Validate(); err != nil {
|
||||
sendAPIResponse(w, r, err, "", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
|
@ -106,10 +106,10 @@ func (s *httpdServer) handleSMTPOAuth2TokenRequestPost(w http.ResponseWriter, r
|
|||
}
|
||||
configs.SetNilsToEmpty()
|
||||
if err := configs.SMTP.TryDecrypt(); err == nil {
|
||||
req.OAuth2Config.ClientSecret = configs.SMTP.OAuth2.ClientSecret.GetPayload()
|
||||
req.ClientSecret = configs.SMTP.OAuth2.ClientSecret.GetPayload()
|
||||
}
|
||||
}
|
||||
cfg := req.OAuth2Config.GetOAuth2()
|
||||
cfg := req.GetOAuth2()
|
||||
cfg.RedirectURL = req.BaseRedirectURL + webOAuth2RedirectPath
|
||||
clientSecret := kms.NewPlainSecret(cfg.ClientSecret)
|
||||
clientSecret.SetAdditionalData(xid.New().String())
|
||||
|
|
|
|||
|
|
@ -68,8 +68,8 @@ func getCommonSearchParamsFromRequest(r *http.Request) (eventsearcher.CommonSear
|
|||
}
|
||||
c.EndTimestamp = ts
|
||||
}
|
||||
c.Username = r.URL.Query().Get("username")
|
||||
c.IP = r.URL.Query().Get("ip")
|
||||
c.Username = strings.TrimSpace(r.URL.Query().Get("username"))
|
||||
c.IP = strings.TrimSpace(r.URL.Query().Get("ip"))
|
||||
c.InstanceIDs = getCommaSeparatedQueryParam(r, "instance_ids")
|
||||
c.FromID = r.URL.Query().Get("from_id")
|
||||
|
||||
|
|
@ -93,9 +93,9 @@ func getFsSearchParamsFromRequest(r *http.Request) (eventsearcher.FsEventSearch,
|
|||
s.FsProvider = val
|
||||
}
|
||||
s.Actions = getCommaSeparatedQueryParam(r, "actions")
|
||||
s.SSHCmd = r.URL.Query().Get("ssh_cmd")
|
||||
s.Bucket = r.URL.Query().Get("bucket")
|
||||
s.Endpoint = r.URL.Query().Get("endpoint")
|
||||
s.SSHCmd = strings.TrimSpace(r.URL.Query().Get("ssh_cmd"))
|
||||
s.Bucket = strings.TrimSpace(r.URL.Query().Get("bucket"))
|
||||
s.Endpoint = strings.TrimSpace(r.URL.Query().Get("endpoint"))
|
||||
s.Protocols = getCommaSeparatedQueryParam(r, "protocols")
|
||||
statuses := getCommaSeparatedQueryParam(r, "statuses")
|
||||
for _, status := range statuses {
|
||||
|
|
@ -117,7 +117,7 @@ func getProviderSearchParamsFromRequest(r *http.Request) (eventsearcher.Provider
|
|||
return s, err
|
||||
}
|
||||
s.Actions = getCommaSeparatedQueryParam(r, "actions")
|
||||
s.ObjectName = r.URL.Query().Get("object_name")
|
||||
s.ObjectName = strings.TrimSpace(r.URL.Query().Get("object_name"))
|
||||
s.ObjectTypes = getCommaSeparatedQueryParam(r, "object_types")
|
||||
return s, nil
|
||||
}
|
||||
|
|
|
|||
|
|
@ -49,7 +49,7 @@ func getUserConnection(w http.ResponseWriter, r *http.Request) (*Connection, err
|
|||
connID := xid.New().String()
|
||||
protocol := getProtocolFromRequest(r)
|
||||
connectionID := fmt.Sprintf("%v_%v", protocol, connID)
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false, false); err != nil {
|
||||
sendAPIResponse(w, r, err, http.StatusText(http.StatusForbidden), http.StatusForbidden)
|
||||
return nil, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -507,7 +507,6 @@ func (s *httpdServer) checkPublicShare(w http.ResponseWriter, r *http.Request, v
|
|||
if share.Password != "" {
|
||||
if isWebClient {
|
||||
if err := s.checkWebClientShareCredentials(w, r, &share); err != nil {
|
||||
handleDefenderEventLoginFailed(ipAddr, err) //nolint:errcheck
|
||||
return share, nil, dataprovider.ErrInvalidCredentials
|
||||
}
|
||||
} else {
|
||||
|
|
|
|||
|
|
@ -732,7 +732,7 @@ func updateLoginMetrics(user *dataprovider.User, loginMethod, ip string, err err
|
|||
dataprovider.ExecutePostLoginHook(user, loginMethod, ip, protocol, err)
|
||||
}
|
||||
|
||||
func checkHTTPClientUser(user *dataprovider.User, r *http.Request, connectionID string, checkSessions bool) error {
|
||||
func checkHTTPClientUser(user *dataprovider.User, r *http.Request, connectionID string, checkSessions, isOIDCLogin bool) error {
|
||||
if slices.Contains(user.Filters.DeniedProtocols, common.ProtocolHTTP) {
|
||||
logger.Info(logSender, connectionID, "cannot login user %q, protocol HTTP is not allowed", user.Username)
|
||||
return util.NewI18nError(
|
||||
|
|
@ -740,7 +740,7 @@ func checkHTTPClientUser(user *dataprovider.User, r *http.Request, connectionID
|
|||
util.I18nErrorProtocolForbidden,
|
||||
)
|
||||
}
|
||||
if !isLoggedInWithOIDC(r) && !user.IsLoginMethodAllowed(dataprovider.LoginMethodPassword, common.ProtocolHTTP) {
|
||||
if !isLoggedInWithOIDC(r) && !isOIDCLogin && !user.IsLoginMethodAllowed(dataprovider.LoginMethodPassword, common.ProtocolHTTP) {
|
||||
logger.Info(logSender, connectionID, "cannot login user %q, password login method is not allowed", user.Username)
|
||||
return util.NewI18nError(
|
||||
fmt.Errorf("login method password is not allowed for user %q", user.Username),
|
||||
|
|
@ -784,7 +784,7 @@ func getActiveUser(username string, r *http.Request) (dataprovider.User, error)
|
|||
if err := user.CheckLoginConditions(); err != nil {
|
||||
return user, util.NewRecordNotFoundError(fmt.Sprintf("user %q cannot login: %v", username, err))
|
||||
}
|
||||
if err := checkHTTPClientUser(&user, r, xid.New().String(), false); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, xid.New().String(), false, false); err != nil {
|
||||
return user, util.NewRecordNotFoundError(fmt.Sprintf("user %q cannot login: %v", username, err))
|
||||
}
|
||||
return user, nil
|
||||
|
|
|
|||
|
|
@ -96,8 +96,8 @@ func updateTokensDuration(api, cookie, share int) {
|
|||
if isTokenDurationValid(share) {
|
||||
shareTokenDuration = time.Duration(share) * time.Minute
|
||||
}
|
||||
logger.Debug(logSender, "", "API token duration %s, cookie token duration %s, cookie refresh threshold %s, share token duration %s",
|
||||
apiTokenDuration, cookieTokenDuration, cookieRefreshThreshold, shareTokenDuration)
|
||||
logger.Debug(logSender, "", "API token duration %s, cookie token duration %s, cookie refresh threshold %s, share token duration %s, csrf token duration %s",
|
||||
apiTokenDuration, cookieTokenDuration, cookieRefreshThreshold, shareTokenDuration, csrfTokenDuration)
|
||||
}
|
||||
|
||||
func getTokenDuration(audience tokenAudience) time.Duration {
|
||||
|
|
|
|||
|
|
@ -126,7 +126,7 @@ func (f *httpdFile) closeIO() error {
|
|||
} else if f.reader != nil {
|
||||
err = f.reader.Close()
|
||||
if metadater, ok := f.reader.(vfs.Metadater); ok {
|
||||
f.BaseTransfer.SetMetadata(metadater.Metadata())
|
||||
f.SetMetadata(metadater.Metadata())
|
||||
}
|
||||
}
|
||||
return err
|
||||
|
|
|
|||
|
|
@ -414,11 +414,17 @@ type SecurityConf struct {
|
|||
ContentSecurityPolicy string `json:"content_security_policy" mapstructure:"content_security_policy"`
|
||||
// PermissionsPolicy allows to set the Permissions-Policy header value. Default is "".
|
||||
PermissionsPolicy string `json:"permissions_policy" mapstructure:"permissions_policy"`
|
||||
// CrossOriginOpenerPolicy allows to set the `Cross-Origin-Opener-Policy` header value. Default is "".
|
||||
// CrossOriginOpenerPolicy allows to set the Cross-Origin-Opener-Policy header value. Default is "".
|
||||
CrossOriginOpenerPolicy string `json:"cross_origin_opener_policy" mapstructure:"cross_origin_opener_policy"`
|
||||
// CacheControl allow to set the Cache-Control header value.
|
||||
// CrossOriginResourcePolicy allows to set the Cross-Origin-Resource-Policy header value. Default is "".
|
||||
CrossOriginResourcePolicy string `json:"cross_origin_resource_policy" mapstructure:"cross_origin_resource_policy"`
|
||||
// CrossOriginEmbedderPolicy allows to set the Cross-Origin-Embedder-Policy header value. Default is "".
|
||||
CrossOriginEmbedderPolicy string `json:"cross_origin_embedder_policy" mapstructure:"cross_origin_embedder_policy"`
|
||||
// CacheControl allows to set the Cache-Control header value.
|
||||
CacheControl string `json:"cache_control" mapstructure:"cache_control"`
|
||||
proxyHeaders []string
|
||||
// ReferrerPolicy allows to set the Referrer-Policy header values.
|
||||
ReferrerPolicy string `json:"referrer_policy" mapstructure:"referrer_policy"`
|
||||
proxyHeaders []string
|
||||
}
|
||||
|
||||
func (s *SecurityConf) updateProxyHeaders() {
|
||||
|
|
@ -561,7 +567,21 @@ type Binding struct {
|
|||
//
|
||||
// You can combine the values. For example 3 means that you can only login using OIDC on
|
||||
// both WebClient and WebAdmin UI.
|
||||
// Deprecated because it is not extensible, use DisabledLoginMethods
|
||||
EnabledLoginMethods int `json:"enabled_login_methods" mapstructure:"enabled_login_methods"`
|
||||
// Defines the login methods disabled for the WebAdmin and WebClient UIs:
|
||||
//
|
||||
// - 1 means OIDC for the WebAdmin UI
|
||||
// - 2 means OIDC for the WebClient UI
|
||||
// - 4 means login form for the WebAdmin UI
|
||||
// - 8 means login form for the WebClient UI
|
||||
// - 16 means basic auth for admin REST API
|
||||
// - 32 means basic auth for user REST API
|
||||
// - 64 means API key auth for admins
|
||||
// - 128 means API key auth for users
|
||||
// You can combine the values. For example 12 means that you can only login using OIDC on
|
||||
// both WebClient and WebAdmin UI.
|
||||
DisabledLoginMethods int `json:"disabled_login_methods" mapstructure:"disabled_login_methods"`
|
||||
// you also need to provide a certificate for enabling HTTPS
|
||||
EnableHTTPS bool `json:"enable_https" mapstructure:"enable_https"`
|
||||
// Certificate and matching private key for this specific binding, if empty the global
|
||||
|
|
@ -683,45 +703,76 @@ func (b *Binding) IsValid() bool {
|
|||
|
||||
func (b *Binding) isWebAdminOIDCLoginDisabled() bool {
|
||||
if b.EnableWebAdmin {
|
||||
if b.EnabledLoginMethods == 0 {
|
||||
return false
|
||||
}
|
||||
return b.EnabledLoginMethods&1 == 0
|
||||
return b.DisabledLoginMethods&1 != 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *Binding) isWebClientOIDCLoginDisabled() bool {
|
||||
if b.EnableWebClient {
|
||||
if b.EnabledLoginMethods == 0 {
|
||||
return false
|
||||
}
|
||||
return b.EnabledLoginMethods&2 == 0
|
||||
return b.DisabledLoginMethods&2 != 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *Binding) isWebAdminLoginFormDisabled() bool {
|
||||
if b.EnableWebAdmin {
|
||||
if b.EnabledLoginMethods == 0 {
|
||||
return false
|
||||
}
|
||||
return b.EnabledLoginMethods&4 == 0
|
||||
return b.DisabledLoginMethods&4 != 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *Binding) isWebClientLoginFormDisabled() bool {
|
||||
if b.EnableWebClient {
|
||||
if b.EnabledLoginMethods == 0 {
|
||||
return false
|
||||
}
|
||||
return b.EnabledLoginMethods&8 == 0
|
||||
return b.DisabledLoginMethods&8 != 0
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (b *Binding) isAdminTokenEndpointDisabled() bool {
|
||||
return b.DisabledLoginMethods&16 != 0
|
||||
}
|
||||
|
||||
func (b *Binding) isUserTokenEndpointDisabled() bool {
|
||||
return b.DisabledLoginMethods&32 != 0
|
||||
}
|
||||
|
||||
func (b *Binding) isAdminAPIKeyAuthDisabled() bool {
|
||||
return b.DisabledLoginMethods&64 != 0
|
||||
}
|
||||
|
||||
func (b *Binding) isUserAPIKeyAuthDisabled() bool {
|
||||
return b.DisabledLoginMethods&128 != 0
|
||||
}
|
||||
|
||||
func (b *Binding) hasLoginForAPI() bool {
|
||||
return !b.isAdminTokenEndpointDisabled() || !b.isUserTokenEndpointDisabled() ||
|
||||
!b.isAdminAPIKeyAuthDisabled() || !b.isUserAPIKeyAuthDisabled()
|
||||
}
|
||||
|
||||
// convertLoginMethods checks if the deprecated EnabledLoginMethods is set and
|
||||
// convert the value to DisabledLoginMethods.
|
||||
func (b *Binding) convertLoginMethods() {
|
||||
if b.DisabledLoginMethods > 0 || b.EnabledLoginMethods == 0 {
|
||||
// DisabledLoginMethods already in use or EnabledLoginMethods not set.
|
||||
return
|
||||
}
|
||||
if b.EnabledLoginMethods&1 == 0 {
|
||||
b.DisabledLoginMethods++
|
||||
}
|
||||
if b.EnabledLoginMethods&2 == 0 {
|
||||
b.DisabledLoginMethods += 2
|
||||
}
|
||||
if b.EnabledLoginMethods&4 == 0 {
|
||||
b.DisabledLoginMethods += 4
|
||||
}
|
||||
if b.EnabledLoginMethods&8 == 0 {
|
||||
b.DisabledLoginMethods += 8
|
||||
}
|
||||
}
|
||||
|
||||
func (b *Binding) checkLoginMethods() error {
|
||||
b.convertLoginMethods()
|
||||
if b.isWebAdminLoginFormDisabled() && b.isWebAdminOIDCLoginDisabled() {
|
||||
return errors.New("no login method available for WebAdmin UI")
|
||||
}
|
||||
|
|
@ -738,6 +789,9 @@ func (b *Binding) checkLoginMethods() error {
|
|||
return errors.New("no login method available for WebClient UI")
|
||||
}
|
||||
}
|
||||
if b.EnableRESTAPI && !b.hasLoginForAPI() {
|
||||
return errors.New("no login method available for REST API")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -578,27 +578,28 @@ func TestInitialization(t *testing.T) {
|
|||
httpdConf.Bindings[0].OIDC = httpd.OIDC{}
|
||||
httpdConf.Bindings[0].EnableWebClient = true
|
||||
httpdConf.Bindings[0].EnableWebAdmin = true
|
||||
httpdConf.Bindings[0].EnabledLoginMethods = 1
|
||||
httpdConf.Bindings[0].EnableRESTAPI = true
|
||||
httpdConf.Bindings[0].DisabledLoginMethods = 14
|
||||
err = httpdConf.Initialize(configDir, isShared)
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "no login method available for WebAdmin UI")
|
||||
}
|
||||
httpdConf.Bindings[0].EnabledLoginMethods = 2
|
||||
httpdConf.Bindings[0].DisabledLoginMethods = 13
|
||||
err = httpdConf.Initialize(configDir, isShared)
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "no login method available for WebAdmin UI")
|
||||
}
|
||||
httpdConf.Bindings[0].EnabledLoginMethods = 6
|
||||
httpdConf.Bindings[0].DisabledLoginMethods = 9
|
||||
err = httpdConf.Initialize(configDir, isShared)
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "no login method available for WebClient UI")
|
||||
}
|
||||
httpdConf.Bindings[0].EnabledLoginMethods = 4
|
||||
httpdConf.Bindings[0].DisabledLoginMethods = 11
|
||||
err = httpdConf.Initialize(configDir, isShared)
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "no login method available for WebClient UI")
|
||||
}
|
||||
httpdConf.Bindings[0].EnabledLoginMethods = 3
|
||||
httpdConf.Bindings[0].DisabledLoginMethods = 12
|
||||
err = httpdConf.Initialize(configDir, isShared)
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "no login method available for WebAdmin UI")
|
||||
|
|
@ -608,6 +609,12 @@ func TestInitialization(t *testing.T) {
|
|||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "no login method available for WebClient UI")
|
||||
}
|
||||
httpdConf.Bindings[0].EnableWebClient = false
|
||||
httpdConf.Bindings[0].DisabledLoginMethods = 240
|
||||
err = httpdConf.Initialize(configDir, isShared)
|
||||
if assert.Error(t, err) {
|
||||
assert.Contains(t, err.Error(), "no login method available for REST API")
|
||||
}
|
||||
err = dataprovider.Close()
|
||||
assert.NoError(t, err)
|
||||
err = httpdConf.Initialize(configDir, isShared)
|
||||
|
|
@ -621,6 +628,72 @@ func TestInitialization(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestMigrateEventActionPlaceholders(t *testing.T) {
|
||||
if config.GetProviderConf().Driver == dataprovider.MemoryDataProviderName {
|
||||
t.Skip("this test is not supported with the memory provider")
|
||||
}
|
||||
// Add some event actions using the old placeholders syntax
|
||||
a1 := dataprovider.BaseEventAction{
|
||||
Name: xid.New().String(),
|
||||
Type: dataprovider.ActionTypeEmail,
|
||||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"failure@example.com"},
|
||||
Subject: `Failed "{{Event}}" from "{{Name}}"`,
|
||||
Body: "Object name: {{ObjectName}} object type: {{ObjectType}}, IP: {{IP}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
a2 := dataprovider.BaseEventAction{
|
||||
Name: xid.New().String(),
|
||||
Type: dataprovider.ActionTypeFilesystem,
|
||||
Options: dataprovider.BaseEventActionOptions{
|
||||
FsConfig: dataprovider.EventActionFilesystemConfig{
|
||||
Type: dataprovider.FilesystemActionRename,
|
||||
Renames: []dataprovider.RenameConfig{
|
||||
{
|
||||
KeyValue: dataprovider.KeyValue{
|
||||
Key: "/{{VirtualDirPath}}/{{ObjectName}}",
|
||||
Value: "/{{ObjectName}}_renamed",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
action1, _, err := httpdtest.AddEventAction(a1, http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
action2, _, err := httpdtest.AddEventAction(a2, http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
// Revert the database to the previous version.
|
||||
err = dataprovider.Close()
|
||||
assert.NoError(t, err)
|
||||
err = config.LoadConfig(configDir, "")
|
||||
assert.NoError(t, err)
|
||||
providerConf := config.GetProviderConf()
|
||||
err = dataprovider.RevertDatabase(providerConf, configDir, 29)
|
||||
assert.NoError(t, err)
|
||||
// Close and initialize.
|
||||
err = dataprovider.Close()
|
||||
assert.NoError(t, err)
|
||||
err = dataprovider.Initialize(providerConf, configDir, true)
|
||||
assert.NoError(t, err)
|
||||
// Check that actions are migrated.
|
||||
action1Get, _, err := httpdtest.GetEventActionByName(action1.Name, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
action2Get, _, err := httpdtest.GetEventActionByName(action2.Name, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `Failed "{{.Event}}" from "{{.Name}}"`, action1Get.Options.EmailConfig.Subject)
|
||||
assert.Equal(t, `Object name: {{.ObjectName}} object type: {{.ObjectType}}, IP: {{.IP}}`, action1Get.Options.EmailConfig.Body)
|
||||
assert.Equal(t, `/{{.VirtualDirPath}}/{{.ObjectName}}`, action2Get.Options.FsConfig.Renames[0].Key)
|
||||
assert.Equal(t, `/{{.ObjectName}}_renamed`, action2Get.Options.FsConfig.Renames[0].Value)
|
||||
// Clenup.
|
||||
_, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveEventAction(action2, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestBasicUserHandling(t *testing.T) {
|
||||
u := getTestUser()
|
||||
u.Email = "user@user.com"
|
||||
|
|
@ -1357,19 +1430,19 @@ func TestGroupSettingsOverride(t *testing.T) {
|
|||
switch f.Name {
|
||||
case folderName1:
|
||||
assert.Equal(t, mappedPath1, f.MappedPath)
|
||||
assert.Equal(t, 3, f.BaseVirtualFolder.FsConfig.OSConfig.ReadBufferSize)
|
||||
assert.Equal(t, 5, f.BaseVirtualFolder.FsConfig.OSConfig.WriteBufferSize)
|
||||
assert.Equal(t, 3, f.FsConfig.OSConfig.ReadBufferSize)
|
||||
assert.Equal(t, 5, f.FsConfig.OSConfig.WriteBufferSize)
|
||||
assert.True(t, slices.Contains([]string{"/vdir1", "/vdir2"}, f.VirtualPath))
|
||||
case folderName2:
|
||||
assert.Equal(t, mappedPath2, f.MappedPath)
|
||||
assert.Equal(t, "/vdir3", f.VirtualPath)
|
||||
assert.Equal(t, 0, f.BaseVirtualFolder.FsConfig.OSConfig.ReadBufferSize)
|
||||
assert.Equal(t, 0, f.BaseVirtualFolder.FsConfig.OSConfig.WriteBufferSize)
|
||||
assert.Equal(t, 0, f.FsConfig.OSConfig.ReadBufferSize)
|
||||
assert.Equal(t, 0, f.FsConfig.OSConfig.WriteBufferSize)
|
||||
case folderName3:
|
||||
assert.Equal(t, mappedPath3, f.MappedPath)
|
||||
assert.Equal(t, "/vdir4", f.VirtualPath)
|
||||
assert.Equal(t, 1, f.BaseVirtualFolder.FsConfig.OSConfig.ReadBufferSize)
|
||||
assert.Equal(t, 2, f.BaseVirtualFolder.FsConfig.OSConfig.WriteBufferSize)
|
||||
assert.Equal(t, 1, f.FsConfig.OSConfig.ReadBufferSize)
|
||||
assert.Equal(t, 2, f.FsConfig.OSConfig.WriteBufferSize)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1856,9 +1929,9 @@ func TestBasicActionRulesHandling(t *testing.T) {
|
|||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"email@example.com"},
|
||||
Bcc: []string{"bcc@example.com"},
|
||||
Subject: "Event: {{Event}}",
|
||||
Subject: "Event: {{.Event}}",
|
||||
Body: "test mail body",
|
||||
Attachments: []string{"/{{VirtualPath}}"},
|
||||
Attachments: []string{"/{{.VirtualPath}}"},
|
||||
},
|
||||
}
|
||||
|
||||
|
|
@ -1896,7 +1969,7 @@ func TestBasicActionRulesHandling(t *testing.T) {
|
|||
Value: "b",
|
||||
},
|
||||
},
|
||||
Body: `{"event":"{{Event}}","name":"{{Name}}"}`,
|
||||
Body: `{"event":"{{.Event}}","name":"{{.Name}}"}`,
|
||||
},
|
||||
}
|
||||
action, _, err = httpdtest.UpdateEventAction(a, http.StatusOK)
|
||||
|
|
@ -4879,9 +4952,6 @@ func TestAddUserInvalidFsConfig(t *testing.T) {
|
|||
u.FsConfig.AzBlobConfig.AccountName = "name"
|
||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||
assert.NoError(t, err)
|
||||
u.FsConfig.AzBlobConfig.Container = "container"
|
||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||
assert.NoError(t, err)
|
||||
u.FsConfig.AzBlobConfig.AccountKey = kms.NewSecret(sdkkms.SecretStatusRedacted, "key", "", "")
|
||||
u.FsConfig.AzBlobConfig.KeyPrefix = "/amedir/subdir/"
|
||||
_, _, err = httpdtest.AddUser(u, http.StatusBadRequest)
|
||||
|
|
@ -6838,6 +6908,57 @@ func TestAdminGenerateRecoveryCodesSaveError(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestAdminCredentialsWithSpaces(t *testing.T) {
|
||||
a := getTestAdmin()
|
||||
a.Username = xid.New().String()
|
||||
a.Password = " " + xid.New().String() + " "
|
||||
admin, _, err := httpdtest.AddAdmin(a, http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
// For admins the password is always trimmed.
|
||||
_, err = getJWTAPITokenFromTestServer(a.Username, a.Password)
|
||||
assert.Error(t, err)
|
||||
_, err = getJWTAPITokenFromTestServer(a.Username, strings.TrimSpace(a.Password))
|
||||
assert.NoError(t, err)
|
||||
// The password sent from the WebAdmin UI is automatically trimmed
|
||||
_, err = getJWTWebToken(a.Username, a.Password)
|
||||
assert.NoError(t, err)
|
||||
_, err = getJWTWebToken(a.Username, strings.TrimSpace(a.Password))
|
||||
assert.NoError(t, err)
|
||||
|
||||
_, err = httpdtest.RemoveAdmin(admin, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestUserCredentialsWithSpaces(t *testing.T) {
|
||||
u := getTestUser()
|
||||
u.Password = " " + xid.New().String() + " "
|
||||
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
// For users the password is not trimmed
|
||||
_, err = getJWTAPIUserTokenFromTestServer(u.Username, u.Password)
|
||||
assert.NoError(t, err)
|
||||
_, err = getJWTAPIUserTokenFromTestServer(u.Username, strings.TrimSpace(u.Password))
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = getJWTWebClientTokenFromTestServer(u.Username, u.Password)
|
||||
assert.NoError(t, err)
|
||||
_, err = getJWTWebClientTokenFromTestServer(u.Username, strings.TrimSpace(u.Password))
|
||||
assert.Error(t, err)
|
||||
|
||||
user.Password = u.Password
|
||||
conn, sftpClient, err := getSftpClient(user)
|
||||
if assert.NoError(t, err) {
|
||||
conn.Close()
|
||||
sftpClient.Close()
|
||||
}
|
||||
user.Password = strings.TrimSpace(u.Password)
|
||||
_, _, err = getSftpClient(user)
|
||||
assert.Error(t, err)
|
||||
|
||||
_, err = httpdtest.RemoveUser(user, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestNamingRules(t *testing.T) {
|
||||
smtpCfg := smtp.Config{
|
||||
Host: "127.0.0.1",
|
||||
|
|
@ -8358,7 +8479,7 @@ func TestLoaddata(t *testing.T) {
|
|||
Timeout: 10,
|
||||
SkipTLSVerify: true,
|
||||
Method: http.MethodPost,
|
||||
Body: `{"event":"{{Event}}","name":"{{Name}}"}`,
|
||||
Body: `{"event":"{{.Event}}","name":"{{.Name}}"}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -8604,6 +8725,85 @@ func TestLoaddata(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestLoaddataConvertActions(t *testing.T) {
|
||||
a1 := dataprovider.BaseEventAction{
|
||||
Name: xid.New().String(),
|
||||
Type: dataprovider.ActionTypeEmail,
|
||||
Options: dataprovider.BaseEventActionOptions{
|
||||
EmailConfig: dataprovider.EventActionEmailConfig{
|
||||
Recipients: []string{"failure@example.com"},
|
||||
Subject: `Failed "{{Event}}" from "{{Name}}"`,
|
||||
Body: "Object name: {{ObjectName}} object type: {{ObjectType}}, IP: {{IP}}",
|
||||
},
|
||||
},
|
||||
}
|
||||
a2 := dataprovider.BaseEventAction{
|
||||
Name: xid.New().String(),
|
||||
Type: dataprovider.ActionTypeFilesystem,
|
||||
Options: dataprovider.BaseEventActionOptions{
|
||||
FsConfig: dataprovider.EventActionFilesystemConfig{
|
||||
Type: dataprovider.FilesystemActionRename,
|
||||
Renames: []dataprovider.RenameConfig{
|
||||
{
|
||||
KeyValue: dataprovider.KeyValue{
|
||||
Key: "/{{VirtualDirPath}}/{{ObjectName}}",
|
||||
Value: "/{{ObjectName}}_renamed",
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
backupData := dataprovider.BackupData{
|
||||
EventActions: []dataprovider.BaseEventAction{a1, a2},
|
||||
Version: 16,
|
||||
}
|
||||
backupContent, err := json.Marshal(backupData)
|
||||
assert.NoError(t, err)
|
||||
backupFilePath := filepath.Join(backupsPath, "backup.json")
|
||||
err = os.WriteFile(backupFilePath, backupContent, os.ModePerm)
|
||||
assert.NoError(t, err)
|
||||
_, resp, err := httpdtest.Loaddata(backupFilePath, "1", "2", http.StatusOK)
|
||||
assert.NoError(t, err, string(resp))
|
||||
// Check that actions are migrated.
|
||||
action1, _, err := httpdtest.GetEventActionByName(a1.Name, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
action2, _, err := httpdtest.GetEventActionByName(a2.Name, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `Failed "{{.Event}}" from "{{.Name}}"`, action1.Options.EmailConfig.Subject)
|
||||
assert.Equal(t, `Object name: {{.ObjectName}} object type: {{.ObjectType}}, IP: {{.IP}}`, action1.Options.EmailConfig.Body)
|
||||
assert.Equal(t, `/{{.VirtualDirPath}}/{{.ObjectName}}`, action2.Options.FsConfig.Renames[0].Key)
|
||||
assert.Equal(t, `/{{.ObjectName}}_renamed`, action2.Options.FsConfig.Renames[0].Value)
|
||||
// If we restore a backup from the current version actions are not migrated.
|
||||
backupData = dataprovider.BackupData{
|
||||
EventActions: []dataprovider.BaseEventAction{a1, a2},
|
||||
Version: dataprovider.DumpVersion,
|
||||
}
|
||||
backupContent, err = json.Marshal(backupData)
|
||||
assert.NoError(t, err)
|
||||
backupFilePath = filepath.Join(backupsPath, "backup.json")
|
||||
err = os.WriteFile(backupFilePath, backupContent, os.ModePerm)
|
||||
assert.NoError(t, err)
|
||||
_, resp, err = httpdtest.Loaddata(backupFilePath, "1", "2", http.StatusOK)
|
||||
assert.NoError(t, err, string(resp))
|
||||
action1, _, err = httpdtest.GetEventActionByName(a1.Name, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
action2, _, err = httpdtest.GetEventActionByName(a2.Name, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, `Failed "{{Event}}" from "{{Name}}"`, action1.Options.EmailConfig.Subject)
|
||||
assert.Equal(t, `Object name: {{ObjectName}} object type: {{ObjectType}}, IP: {{IP}}`, action1.Options.EmailConfig.Body)
|
||||
assert.Equal(t, `/{{VirtualDirPath}}/{{ObjectName}}`, action2.Options.FsConfig.Renames[0].Key)
|
||||
assert.Equal(t, `/{{ObjectName}}_renamed`, action2.Options.FsConfig.Renames[0].Value)
|
||||
// Cleanup.
|
||||
_, err = httpdtest.RemoveEventAction(action1, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveEventAction(action2, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
actions, _, err := httpdtest.GetEventActions(0, 0, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
assert.Len(t, actions, 0)
|
||||
}
|
||||
|
||||
func TestLoaddataMode(t *testing.T) {
|
||||
err := dataprovider.UpdateConfigs(nil, "", "", "")
|
||||
assert.NoError(t, err)
|
||||
|
|
@ -8661,7 +8861,7 @@ func TestLoaddataMode(t *testing.T) {
|
|||
Timeout: 10,
|
||||
SkipTLSVerify: true,
|
||||
Method: http.MethodPost,
|
||||
Body: `{"event":"{{Event}}","name":"{{Name}}"}`,
|
||||
Body: `{"event":"{{.Event}}","name":"{{.Name}}"}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -20874,13 +21074,6 @@ func TestWebAdminBasicMock(t *testing.T) {
|
|||
assert.Contains(t, rr.Body.String(), util.I18nError500Message)
|
||||
|
||||
form.Set("default_users_expiration", "10")
|
||||
req, _ = http.NewRequest(http.MethodPost, webAdminPath, bytes.NewBuffer([]byte(form.Encode())))
|
||||
req.RemoteAddr = defaultRemoteAddr
|
||||
req.Header.Set("Content-Type", "application/x-www-form-urlencoded")
|
||||
setJWTCookieForReq(req, token)
|
||||
rr = executeRequest(req)
|
||||
checkResponseCode(t, http.StatusOK, rr)
|
||||
|
||||
form.Set("password", admin.Password)
|
||||
req, _ = http.NewRequest(http.MethodPost, webAdminPath, bytes.NewBuffer([]byte(form.Encode())))
|
||||
req.RemoteAddr = defaultRemoteAddr
|
||||
|
|
@ -23834,7 +24027,7 @@ func TestWebEventAction(t *testing.T) {
|
|||
Value: "value1",
|
||||
},
|
||||
},
|
||||
Body: `{"event":"{{Event}}","name":"{{Name}}"}`,
|
||||
Body: `{"event":"{{.Event}}","name":"{{.Name}}"}`,
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -23953,12 +24146,12 @@ func TestWebEventAction(t *testing.T) {
|
|||
form.Del("http_headers[0][http_header_key]")
|
||||
form.Del("http_headers[0][http_header_val]")
|
||||
form.Set("multipart_body[0][http_part_name]", "part1")
|
||||
form.Set("multipart_body[0][http_part_file]", "{{VirtualPath}}")
|
||||
form.Set("multipart_body[0][http_part_file]", "{{.VirtualPath}}")
|
||||
form.Set("multipart_body[0][http_part_body]", "")
|
||||
form.Set("multipart_body[0][http_part_headers]", "X-MyHeader: a:b,c")
|
||||
form.Set("multipart_body[12][http_part_name]", "part2")
|
||||
form.Set("multipart_body[12][http_part_headers]", "Content-Type:application/json \r\n")
|
||||
form.Set("multipart_body[12][http_part_body]", "{{ObjectData}}")
|
||||
form.Set("multipart_body[12][http_part_body]", "{{.ObjectData}}")
|
||||
req, err = http.NewRequest(http.MethodPost, path.Join(webAdminEventActionPath, action.Name),
|
||||
bytes.NewBuffer([]byte(form.Encode())))
|
||||
assert.NoError(t, err)
|
||||
|
|
@ -23975,12 +24168,12 @@ func TestWebEventAction(t *testing.T) {
|
|||
assert.Equal(t, 0, dbAction.Options.HTTPConfig.Timeout)
|
||||
if assert.Len(t, dbAction.Options.HTTPConfig.Parts, 2) {
|
||||
assert.Equal(t, "part1", dbAction.Options.HTTPConfig.Parts[0].Name)
|
||||
assert.Equal(t, "/{{VirtualPath}}", dbAction.Options.HTTPConfig.Parts[0].Filepath)
|
||||
assert.Equal(t, "/{{.VirtualPath}}", dbAction.Options.HTTPConfig.Parts[0].Filepath)
|
||||
assert.Empty(t, dbAction.Options.HTTPConfig.Parts[0].Body)
|
||||
assert.Equal(t, "X-MyHeader", dbAction.Options.HTTPConfig.Parts[0].Headers[0].Key)
|
||||
assert.Equal(t, "a:b,c", dbAction.Options.HTTPConfig.Parts[0].Headers[0].Value)
|
||||
assert.Equal(t, "part2", dbAction.Options.HTTPConfig.Parts[1].Name)
|
||||
assert.Equal(t, "{{ObjectData}}", dbAction.Options.HTTPConfig.Parts[1].Body)
|
||||
assert.Equal(t, "{{.ObjectData}}", dbAction.Options.HTTPConfig.Parts[1].Body)
|
||||
assert.Empty(t, dbAction.Options.HTTPConfig.Parts[1].Filepath)
|
||||
assert.Equal(t, "Content-Type", dbAction.Options.HTTPConfig.Parts[1].Headers[0].Key)
|
||||
assert.Equal(t, "application/json", dbAction.Options.HTTPConfig.Parts[1].Headers[0].Value)
|
||||
|
|
|
|||
|
|
@ -2395,10 +2395,59 @@ func TestDbTokenManager(t *testing.T) {
|
|||
dbTokenManager.Cleanup()
|
||||
isInvalidated = dbTokenManager.Get(testToken)
|
||||
assert.True(t, isInvalidated)
|
||||
err := dataprovider.DeleteSharedSession(key)
|
||||
err := dataprovider.DeleteSharedSession(key, dataprovider.SessionTypeInvalidToken)
|
||||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestDatabaseSharedSessions(t *testing.T) {
|
||||
if !isSharedProviderSupported() {
|
||||
t.Skip("this test it is not available with this provider")
|
||||
}
|
||||
session1 := dataprovider.Session{
|
||||
Key: "1",
|
||||
Data: map[string]string{"a": "b"},
|
||||
Type: dataprovider.SessionTypeOIDCAuth,
|
||||
Timestamp: 10,
|
||||
}
|
||||
err := dataprovider.AddSharedSession(session1)
|
||||
assert.NoError(t, err)
|
||||
// Adding another session with the same key but a different type should work
|
||||
session2 := session1
|
||||
session2.Type = dataprovider.SessionTypeOIDCToken
|
||||
err = dataprovider.AddSharedSession(session2)
|
||||
assert.NoError(t, err)
|
||||
err = dataprovider.DeleteSharedSession(session1.Key, dataprovider.SessionTypeInvalidToken)
|
||||
assert.ErrorIs(t, err, util.ErrNotFound)
|
||||
_, err = dataprovider.GetSharedSession(session1.Key, dataprovider.SessionTypeResetCode)
|
||||
assert.ErrorIs(t, err, util.ErrNotFound)
|
||||
session1Get, err := dataprovider.GetSharedSession(session1.Key, dataprovider.SessionTypeOIDCAuth)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, session1.Timestamp, session1Get.Timestamp)
|
||||
var stored map[string]string
|
||||
err = json.Unmarshal(session1Get.Data.([]byte), &stored)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, session1.Data, stored)
|
||||
session1.Timestamp = 20
|
||||
session1.Data = map[string]string{"c": "d"}
|
||||
err = dataprovider.AddSharedSession(session1)
|
||||
assert.NoError(t, err)
|
||||
session1Get, err = dataprovider.GetSharedSession(session1.Key, dataprovider.SessionTypeOIDCAuth)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, session1.Timestamp, session1Get.Timestamp)
|
||||
stored = make(map[string]string)
|
||||
err = json.Unmarshal(session1Get.Data.([]byte), &stored)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, session1.Data, stored)
|
||||
err = dataprovider.DeleteSharedSession(session1.Key, dataprovider.SessionTypeOIDCAuth)
|
||||
assert.NoError(t, err)
|
||||
err = dataprovider.DeleteSharedSession(session2.Key, dataprovider.SessionTypeOIDCToken)
|
||||
assert.NoError(t, err)
|
||||
_, err = dataprovider.GetSharedSession(session1.Key, dataprovider.SessionTypeOIDCAuth)
|
||||
assert.ErrorIs(t, err, util.ErrNotFound)
|
||||
_, err = dataprovider.GetSharedSession(session2.Key, dataprovider.SessionTypeOIDCToken)
|
||||
assert.ErrorIs(t, err, util.ErrNotFound)
|
||||
}
|
||||
|
||||
func TestAllowedProxyUnixDomainSocket(t *testing.T) {
|
||||
b := Binding{
|
||||
Address: filepath.Join(os.TempDir(), "sock"),
|
||||
|
|
@ -3389,11 +3438,15 @@ func TestSecureMiddlewareIntegration(t *testing.T) {
|
|||
Value: "https",
|
||||
},
|
||||
},
|
||||
STSSeconds: 31536000,
|
||||
STSIncludeSubdomains: true,
|
||||
STSPreload: true,
|
||||
ContentTypeNosniff: true,
|
||||
CacheControl: "private",
|
||||
STSSeconds: 31536000,
|
||||
STSIncludeSubdomains: true,
|
||||
STSPreload: true,
|
||||
ContentTypeNosniff: true,
|
||||
CacheControl: "private",
|
||||
CrossOriginOpenerPolicy: "same-origin",
|
||||
CrossOriginResourcePolicy: "same-site",
|
||||
CrossOriginEmbedderPolicy: "require-corp",
|
||||
ReferrerPolicy: "no-referrer",
|
||||
},
|
||||
},
|
||||
enableWebAdmin: true,
|
||||
|
|
@ -3448,6 +3501,10 @@ func TestSecureMiddlewareIntegration(t *testing.T) {
|
|||
assert.NotEmpty(t, r.Header.Get(forwardedHostHeader))
|
||||
assert.Equal(t, "max-age=31536000; includeSubDomains; preload", rr.Header().Get("Strict-Transport-Security"))
|
||||
assert.Equal(t, "nosniff", rr.Header().Get("X-Content-Type-Options"))
|
||||
assert.Equal(t, "require-corp", rr.Header().Get("Cross-Origin-Embedder-Policy"))
|
||||
assert.Equal(t, "same-origin", rr.Header().Get("Cross-Origin-Opener-Policy"))
|
||||
assert.Equal(t, "same-site", rr.Header().Get("Cross-Origin-Resource-Policy"))
|
||||
assert.Equal(t, "no-referrer", rr.Header().Get("Referrer-Policy"))
|
||||
|
||||
server.binding.Security.Enabled = false
|
||||
server.binding.Security.updateProxyHeaders()
|
||||
|
|
@ -3893,6 +3950,116 @@ func TestHTTPSRedirect(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
}
|
||||
|
||||
func TestDisabledAdminLoginMethods(t *testing.T) {
|
||||
server := httpdServer{
|
||||
binding: Binding{
|
||||
Address: "",
|
||||
Port: 8080,
|
||||
EnableWebAdmin: true,
|
||||
EnableWebClient: true,
|
||||
EnableRESTAPI: true,
|
||||
DisabledLoginMethods: 20,
|
||||
},
|
||||
enableWebAdmin: true,
|
||||
enableWebClient: true,
|
||||
enableRESTAPI: true,
|
||||
}
|
||||
server.initializeRouter()
|
||||
testServer := httptest.NewServer(server.router)
|
||||
defer testServer.Close()
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, tokenPath, nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodPost, path.Join(adminPath, defaultAdminUsername, "forgot-password"), nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodPost, path.Join(adminPath, defaultAdminUsername, "reset-password"), nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodPost, webAdminLoginPath, nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusMethodNotAllowed, rr.Code)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodPost, webAdminResetPwdPath, nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodPost, webAdminForgotPwdPath, nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||
}
|
||||
|
||||
func TestDisabledUserLoginMethods(t *testing.T) {
|
||||
server := httpdServer{
|
||||
binding: Binding{
|
||||
Address: "",
|
||||
Port: 8080,
|
||||
EnableWebAdmin: true,
|
||||
EnableWebClient: true,
|
||||
EnableRESTAPI: true,
|
||||
DisabledLoginMethods: 40,
|
||||
},
|
||||
enableWebAdmin: true,
|
||||
enableWebClient: true,
|
||||
enableRESTAPI: true,
|
||||
}
|
||||
server.initializeRouter()
|
||||
testServer := httptest.NewServer(server.router)
|
||||
defer testServer.Close()
|
||||
|
||||
rr := httptest.NewRecorder()
|
||||
req, err := http.NewRequest(http.MethodGet, userTokenPath, nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodPost, userPath+"/user/forgot-password", nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodPost, userPath+"/user/reset-password", nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodPost, webClientLoginPath, nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusMethodNotAllowed, rr.Code)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodPost, webClientResetPwdPath, nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||
|
||||
rr = httptest.NewRecorder()
|
||||
req, err = http.NewRequest(http.MethodPost, webClientForgotPwdPath, nil)
|
||||
require.NoError(t, err)
|
||||
testServer.Config.Handler.ServeHTTP(rr, req)
|
||||
assert.Equal(t, http.StatusNotFound, rr.Code)
|
||||
}
|
||||
|
||||
func TestGetLogEventString(t *testing.T) {
|
||||
assert.Equal(t, "Login failed", getLogEventString(notifier.LogEventTypeLoginFailed))
|
||||
assert.Equal(t, "Login with non-existent user", getLogEventString(notifier.LogEventTypeLoginNoUser))
|
||||
|
|
@ -4060,6 +4227,39 @@ func TestI18NErrors(t *testing.T) {
|
|||
assert.Equal(t, `{"a":"b"}`, errI18n.Args())
|
||||
}
|
||||
|
||||
func TestConvertEnabledLoginMethods(t *testing.T) {
|
||||
b := Binding{
|
||||
EnabledLoginMethods: 0,
|
||||
DisabledLoginMethods: 1,
|
||||
}
|
||||
b.convertLoginMethods()
|
||||
assert.Equal(t, 1, b.DisabledLoginMethods)
|
||||
b.DisabledLoginMethods = 0
|
||||
b.EnabledLoginMethods = 1
|
||||
b.convertLoginMethods()
|
||||
assert.Equal(t, 14, b.DisabledLoginMethods)
|
||||
b.DisabledLoginMethods = 0
|
||||
b.EnabledLoginMethods = 2
|
||||
b.convertLoginMethods()
|
||||
assert.Equal(t, 13, b.DisabledLoginMethods)
|
||||
b.DisabledLoginMethods = 0
|
||||
b.EnabledLoginMethods = 3
|
||||
b.convertLoginMethods()
|
||||
assert.Equal(t, 12, b.DisabledLoginMethods)
|
||||
b.DisabledLoginMethods = 0
|
||||
b.EnabledLoginMethods = 4
|
||||
b.convertLoginMethods()
|
||||
assert.Equal(t, 11, b.DisabledLoginMethods)
|
||||
b.DisabledLoginMethods = 0
|
||||
b.EnabledLoginMethods = 7
|
||||
b.convertLoginMethods()
|
||||
assert.Equal(t, 8, b.DisabledLoginMethods)
|
||||
b.DisabledLoginMethods = 0
|
||||
b.EnabledLoginMethods = 15
|
||||
b.convertLoginMethods()
|
||||
assert.Equal(t, 0, b.DisabledLoginMethods)
|
||||
}
|
||||
|
||||
func getCSRFTokenFromBody(body io.Reader) (string, error) {
|
||||
doc, err := html.Parse(body)
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -417,7 +417,7 @@ func checkAPIKeyAuth(tokenAuth *jwtauth.JWTAuth, scope dataprovider.APIKeyScope)
|
|||
k, err := dataprovider.APIKeyExists(keyID)
|
||||
if err != nil {
|
||||
handleDefenderEventLoginFailed(util.GetIPFromRemoteAddress(r.RemoteAddr), util.NewRecordNotFoundError("invalid api key")) //nolint:errcheck
|
||||
logger.Debug(logSender, "invalid api key %q: %v", apiKey, err)
|
||||
logger.Debug(logSender, "", "invalid api key %q: %v", apiKey, err)
|
||||
sendAPIResponse(w, r, errors.New("the provided api key is not valid"), "", http.StatusBadRequest)
|
||||
return
|
||||
}
|
||||
|
|
@ -551,7 +551,7 @@ func authenticateUserWithAPIKey(username, keyID string, tokenAuth *jwtauth.JWTAu
|
|||
return err
|
||||
}
|
||||
connectionID := fmt.Sprintf("%v_%v", protocol, xid.New().String())
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, true); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, true, false); err != nil {
|
||||
updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, err, r)
|
||||
return err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -132,11 +132,11 @@ func (o *dbOAuth2Manager) addPendingAuth(pendingAuth oauth2PendingAuth) {
|
|||
}
|
||||
|
||||
func (o *dbOAuth2Manager) removePendingAuth(state string) {
|
||||
dataprovider.DeleteSharedSession(state) //nolint:errcheck
|
||||
dataprovider.DeleteSharedSession(state, dataprovider.SessionTypeOAuth2Auth) //nolint:errcheck
|
||||
}
|
||||
|
||||
func (o *dbOAuth2Manager) getPendingAuth(state string) (oauth2PendingAuth, error) {
|
||||
session, err := dataprovider.GetSharedSession(state)
|
||||
session, err := dataprovider.GetSharedSession(state, dataprovider.SessionTypeOAuth2Auth)
|
||||
if err != nil {
|
||||
return oauth2PendingAuth{}, errors.New("oauth2: unable to get the auth request for the specified state")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ func TestDbOAuth2Manager(t *testing.T) {
|
|||
a, err := m.getPendingAuth(auth.State)
|
||||
assert.NoError(t, err)
|
||||
assert.Equal(t, sdkkms.SecretStatusPlain, a.ClientSecret.GetStatus())
|
||||
session, err := dataprovider.GetSharedSession(auth.State)
|
||||
session, err := dataprovider.GetSharedSession(auth.State, dataprovider.SessionTypeOAuth2Auth)
|
||||
assert.NoError(t, err)
|
||||
authReq := oauth2PendingAuth{}
|
||||
err = json.Unmarshal(session.Data.([]byte), &authReq)
|
||||
|
|
@ -107,10 +107,10 @@ func TestDbOAuth2Manager(t *testing.T) {
|
|||
m.addPendingAuth(auth)
|
||||
_, err = m.getPendingAuth(auth.State)
|
||||
assert.Error(t, err)
|
||||
_, err = dataprovider.GetSharedSession(auth.State)
|
||||
_, err = dataprovider.GetSharedSession(auth.State, dataprovider.SessionTypeOAuth2Auth)
|
||||
assert.NoError(t, err)
|
||||
m.cleanup()
|
||||
_, err = dataprovider.GetSharedSession(auth.State)
|
||||
_, err = dataprovider.GetSharedSession(auth.State, dataprovider.SessionTypeOAuth2Auth)
|
||||
assert.Error(t, err)
|
||||
_, err = m.decodePendingAuthData("not a byte array")
|
||||
require.Error(t, err)
|
||||
|
|
@ -126,7 +126,7 @@ func TestDbOAuth2Manager(t *testing.T) {
|
|||
}
|
||||
auth.ClientSecret.SetStatus(sdkkms.SecretStatusSecretBox)
|
||||
m.addPendingAuth(auth)
|
||||
_, err = dataprovider.GetSharedSession(auth.State)
|
||||
_, err = dataprovider.GetSharedSession(auth.State, dataprovider.SessionTypeOAuth2Auth)
|
||||
assert.Error(t, err)
|
||||
asJSON, err := json.Marshal(auth)
|
||||
assert.NoError(t, err)
|
||||
|
|
|
|||
|
|
@ -396,7 +396,7 @@ func (t *oidcToken) refreshUser(r *http.Request) error {
|
|||
if err := user.CheckLoginConditions(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := checkHTTPClientUser(&user, r, xid.New().String(), true); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, xid.New().String(), true, false); err != nil {
|
||||
return err
|
||||
}
|
||||
t.Permissions = user.Filters.WebClient
|
||||
|
|
@ -460,7 +460,7 @@ func (t *oidcToken) getUser(r *http.Request) error {
|
|||
return err
|
||||
}
|
||||
connectionID := fmt.Sprintf("%s_%s", common.ProtocolOIDC, xid.New().String())
|
||||
if err := checkHTTPClientUser(user, r, connectionID, true); err != nil {
|
||||
if err := checkHTTPClientUser(user, r, connectionID, true, true); err != nil {
|
||||
updateLoginMetrics(user, dataprovider.LoginMethodIDP, ipAddr, err, r)
|
||||
return err
|
||||
}
|
||||
|
|
@ -553,7 +553,7 @@ func (s *httpdServer) oidcTokenAuthenticator(audience tokenAudience) func(next h
|
|||
}
|
||||
jwtTokenClaims := jwtTokenClaims{
|
||||
JwtID: token.Cookie,
|
||||
Username: token.Username,
|
||||
Username: dataprovider.ConvertName(token.Username),
|
||||
Permissions: token.Permissions,
|
||||
Role: token.TokenRole,
|
||||
HideUserPageSections: token.HideUserPageSections,
|
||||
|
|
|
|||
|
|
@ -906,7 +906,8 @@ func TestOIDCToken(t *testing.T) {
|
|||
},
|
||||
Filters: dataprovider.UserFilters{
|
||||
BaseUserFilters: sdk.BaseUserFilters{
|
||||
DeniedProtocols: []string{common.ProtocolHTTP},
|
||||
DeniedProtocols: []string{common.ProtocolHTTP},
|
||||
DeniedLoginMethods: []string{dataprovider.LoginMethodPassword},
|
||||
},
|
||||
},
|
||||
}
|
||||
|
|
@ -1181,18 +1182,18 @@ func TestOIDCEvMgrIntegration(t *testing.T) {
|
|||
// add a special chars to check json replacer
|
||||
username := `test_"oidc_eventmanager`
|
||||
u := map[string]any{
|
||||
"username": "{{Name}}",
|
||||
"username": "{{.Name}}",
|
||||
"status": 1,
|
||||
"home_dir": filepath.Join(os.TempDir(), "{{IDPFieldcustom1.sub}}"),
|
||||
"home_dir": filepath.Join(os.TempDir(), "{{.IDPFieldcustom1.sub}}"),
|
||||
"permissions": map[string][]string{
|
||||
"/": {dataprovider.PermAny},
|
||||
},
|
||||
"description": "{{IDPFieldcustom2}}",
|
||||
"description": "{{.IDPFieldcustom2}}",
|
||||
}
|
||||
userTmpl, err := json.Marshal(u)
|
||||
require.NoError(t, err)
|
||||
a := map[string]any{
|
||||
"username": "{{Name}}",
|
||||
"username": "{{.Name}}",
|
||||
"status": 1,
|
||||
"permissions": []string{dataprovider.PermAdminAny},
|
||||
}
|
||||
|
|
@ -1548,7 +1549,7 @@ func TestOIDCWithLoginFormsDisabled(t *testing.T) {
|
|||
|
||||
server := getTestOIDCServer()
|
||||
server.binding.OIDC.ImplicitRoles = true
|
||||
server.binding.EnabledLoginMethods = 3
|
||||
server.binding.DisabledLoginMethods = 12
|
||||
server.binding.EnableWebAdmin = true
|
||||
server.binding.EnableWebClient = true
|
||||
err := server.binding.OIDC.initialize()
|
||||
|
|
|
|||
|
|
@ -167,11 +167,11 @@ func (o *dbOIDCManager) addPendingAuth(pendingAuth oidcPendingAuth) {
|
|||
}
|
||||
|
||||
func (o *dbOIDCManager) removePendingAuth(state string) {
|
||||
dataprovider.DeleteSharedSession(state) //nolint:errcheck
|
||||
dataprovider.DeleteSharedSession(state, dataprovider.SessionTypeOIDCAuth) //nolint:errcheck
|
||||
}
|
||||
|
||||
func (o *dbOIDCManager) getPendingAuth(state string) (oidcPendingAuth, error) {
|
||||
session, err := dataprovider.GetSharedSession(state)
|
||||
session, err := dataprovider.GetSharedSession(state, dataprovider.SessionTypeOIDCAuth)
|
||||
if err != nil {
|
||||
return oidcPendingAuth{}, errors.New("oidc: unable to get the auth request for the specified state")
|
||||
}
|
||||
|
|
@ -204,7 +204,7 @@ func (o *dbOIDCManager) addToken(token oidcToken) {
|
|||
}
|
||||
|
||||
func (o *dbOIDCManager) removeToken(cookie string) {
|
||||
dataprovider.DeleteSharedSession(cookie) //nolint:errcheck
|
||||
dataprovider.DeleteSharedSession(cookie, dataprovider.SessionTypeOIDCToken) //nolint:errcheck
|
||||
}
|
||||
|
||||
func (o *dbOIDCManager) updateTokenUsage(token oidcToken) {
|
||||
|
|
@ -215,7 +215,7 @@ func (o *dbOIDCManager) updateTokenUsage(token oidcToken) {
|
|||
}
|
||||
|
||||
func (o *dbOIDCManager) getToken(cookie string) (oidcToken, error) {
|
||||
session, err := dataprovider.GetSharedSession(cookie)
|
||||
session, err := dataprovider.GetSharedSession(cookie, dataprovider.SessionTypeOIDCToken)
|
||||
if err != nil {
|
||||
return oidcToken{}, errors.New("oidc: unable to get the token for the specified session")
|
||||
}
|
||||
|
|
|
|||
|
|
@ -110,7 +110,7 @@ func (m *dbResetCodeManager) Add(code *resetCode) error {
|
|||
}
|
||||
|
||||
func (m *dbResetCodeManager) Get(code string) (*resetCode, error) {
|
||||
session, err := dataprovider.GetSharedSession(code)
|
||||
session, err := dataprovider.GetSharedSession(code, dataprovider.SessionTypeResetCode)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
|
@ -132,7 +132,7 @@ func (m *dbResetCodeManager) decodeData(data any) (*resetCode, error) {
|
|||
}
|
||||
|
||||
func (m *dbResetCodeManager) Delete(code string) error {
|
||||
return dataprovider.DeleteSharedSession(code)
|
||||
return dataprovider.DeleteSharedSession(code, dataprovider.SessionTypeResetCode)
|
||||
}
|
||||
|
||||
func (m *dbResetCodeManager) Cleanup() {
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !bundle
|
||||
// +build !bundle
|
||||
|
||||
package httpd
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build bundle
|
||||
// +build bundle
|
||||
|
||||
package httpd
|
||||
|
||||
|
|
|
|||
|
|
@ -244,7 +244,7 @@ func (s *httpdServer) handleWebClientLoginPost(w http.ResponseWriter, r *http.Re
|
|||
}
|
||||
protocol := common.ProtocolHTTP
|
||||
username := strings.TrimSpace(r.Form.Get("username"))
|
||||
password := strings.TrimSpace(r.Form.Get("password"))
|
||||
password := r.Form.Get("password")
|
||||
if username == "" || password == "" {
|
||||
updateLoginMetrics(&dataprovider.User{BaseUser: sdk.BaseUser{Username: username}},
|
||||
dataprovider.LoginMethodPassword, ipAddr, common.ErrNoCredentials, r)
|
||||
|
|
@ -273,7 +273,7 @@ func (s *httpdServer) handleWebClientLoginPost(w http.ResponseWriter, r *http.Re
|
|||
return
|
||||
}
|
||||
connectionID := fmt.Sprintf("%v_%v", protocol, xid.New().String())
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, true); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, true, false); err != nil {
|
||||
updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, err, r)
|
||||
s.renderClientLoginPage(w, r, util.NewI18nError(err, util.I18nError403Message))
|
||||
return
|
||||
|
|
@ -312,7 +312,7 @@ func (s *httpdServer) handleWebClientPasswordResetPost(w http.ResponseWriter, r
|
|||
return
|
||||
}
|
||||
connectionID := fmt.Sprintf("%v_%v", getProtocolFromRequest(r), xid.New().String())
|
||||
if err := checkHTTPClientUser(user, r, connectionID, true); err != nil {
|
||||
if err := checkHTTPClientUser(user, r, connectionID, true, false); err != nil {
|
||||
s.renderClientResetPwdPage(w, r, util.NewI18nError(err, util.I18nErrorLoginAfterReset))
|
||||
return
|
||||
}
|
||||
|
|
@ -840,7 +840,7 @@ func (s *httpdServer) getUserToken(w http.ResponseWriter, r *http.Request) {
|
|||
sendAPIResponse(w, r, nil, http.StatusText(http.StatusUnauthorized), http.StatusUnauthorized)
|
||||
return
|
||||
}
|
||||
if username == "" || password == "" {
|
||||
if username == "" || strings.TrimSpace(password) == "" {
|
||||
updateLoginMetrics(&dataprovider.User{BaseUser: sdk.BaseUser{Username: username}},
|
||||
dataprovider.LoginMethodPassword, ipAddr, common.ErrNoCredentials, r)
|
||||
w.Header().Set(common.HTTPAuthenticationHeader, basicRealm)
|
||||
|
|
@ -862,7 +862,7 @@ func (s *httpdServer) getUserToken(w http.ResponseWriter, r *http.Request) {
|
|||
return
|
||||
}
|
||||
connectionID := fmt.Sprintf("%v_%v", protocol, xid.New().String())
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, true); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, true, false); err != nil {
|
||||
updateLoginMetrics(&user, dataprovider.LoginMethodPassword, ipAddr, err, r)
|
||||
sendAPIResponse(w, r, err, http.StatusText(http.StatusForbidden), http.StatusForbidden)
|
||||
return
|
||||
|
|
@ -1039,7 +1039,7 @@ func (s *httpdServer) refreshClientToken(w http.ResponseWriter, r *http.Request,
|
|||
logger.Debug(logSender, "", "unable to refresh cookie for user %q: %v", user.Username, err)
|
||||
return
|
||||
}
|
||||
if err := checkHTTPClientUser(&user, r, xid.New().String(), true); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, xid.New().String(), true, false); err != nil {
|
||||
logger.Debug(logSender, "", "unable to refresh cookie for user %q: %v", user.Username, err)
|
||||
return
|
||||
}
|
||||
|
|
@ -1188,8 +1188,9 @@ func (s *httpdServer) badHostHandler(w http.ResponseWriter, r *http.Request) {
|
|||
break
|
||||
}
|
||||
}
|
||||
logger.Debug(logSender, "", "the host %q is not allowed", host)
|
||||
s.sendForbiddenResponse(w, r, util.NewI18nError(
|
||||
util.NewGenericError(fmt.Sprintf("The host %q is not allowed", host)),
|
||||
util.NewGenericError(http.StatusText(http.StatusForbidden)),
|
||||
util.I18nErrorConnectionForbidden,
|
||||
))
|
||||
}
|
||||
|
|
@ -1243,17 +1244,20 @@ func (s *httpdServer) initializeRouter() {
|
|||
s.router.Use(middleware.Recoverer)
|
||||
if s.binding.Security.Enabled {
|
||||
secureMiddleware := secure.New(secure.Options{
|
||||
AllowedHosts: s.binding.Security.AllowedHosts,
|
||||
AllowedHostsAreRegex: s.binding.Security.AllowedHostsAreRegex,
|
||||
HostsProxyHeaders: s.binding.Security.HostsProxyHeaders,
|
||||
SSLProxyHeaders: s.binding.Security.getHTTPSProxyHeaders(),
|
||||
STSSeconds: s.binding.Security.STSSeconds,
|
||||
STSIncludeSubdomains: s.binding.Security.STSIncludeSubdomains,
|
||||
STSPreload: s.binding.Security.STSPreload,
|
||||
ContentTypeNosniff: s.binding.Security.ContentTypeNosniff,
|
||||
ContentSecurityPolicy: s.binding.Security.ContentSecurityPolicy,
|
||||
PermissionsPolicy: s.binding.Security.PermissionsPolicy,
|
||||
CrossOriginOpenerPolicy: s.binding.Security.CrossOriginOpenerPolicy,
|
||||
AllowedHosts: s.binding.Security.AllowedHosts,
|
||||
AllowedHostsAreRegex: s.binding.Security.AllowedHostsAreRegex,
|
||||
HostsProxyHeaders: s.binding.Security.HostsProxyHeaders,
|
||||
SSLProxyHeaders: s.binding.Security.getHTTPSProxyHeaders(),
|
||||
STSSeconds: s.binding.Security.STSSeconds,
|
||||
STSIncludeSubdomains: s.binding.Security.STSIncludeSubdomains,
|
||||
STSPreload: s.binding.Security.STSPreload,
|
||||
ContentTypeNosniff: s.binding.Security.ContentTypeNosniff,
|
||||
ContentSecurityPolicy: s.binding.Security.ContentSecurityPolicy,
|
||||
PermissionsPolicy: s.binding.Security.PermissionsPolicy,
|
||||
CrossOriginOpenerPolicy: s.binding.Security.CrossOriginOpenerPolicy,
|
||||
CrossOriginResourcePolicy: s.binding.Security.CrossOriginResourcePolicy,
|
||||
CrossOriginEmbedderPolicy: s.binding.Security.CrossOriginEmbedderPolicy,
|
||||
ReferrerPolicy: s.binding.Security.ReferrerPolicy,
|
||||
})
|
||||
secureMiddleware.SetBadHostHandler(http.HandlerFunc(s.badHostHandler))
|
||||
if s.binding.Security.CacheControl == "private" {
|
||||
|
|
@ -1295,23 +1299,55 @@ func (s *httpdServer) initializeRouter() {
|
|||
}
|
||||
}
|
||||
|
||||
if s.enableRESTAPI {
|
||||
// share API available to external users
|
||||
s.router.Get(sharesPath+"/{id}", s.downloadFromShare) //nolint:goconst
|
||||
s.router.Post(sharesPath+"/{id}", s.uploadFilesToShare)
|
||||
s.router.Post(sharesPath+"/{id}/{name}", s.uploadFileToShare)
|
||||
s.router.With(compressor.Handler).Get(sharesPath+"/{id}/dirs", s.readBrowsableShareContents)
|
||||
s.router.Get(sharesPath+"/{id}/files", s.downloadBrowsableSharedFile)
|
||||
s.setupRESTAPIRoutes()
|
||||
|
||||
s.router.Get(tokenPath, s.getToken)
|
||||
s.router.Post(adminPath+"/{username}/forgot-password", forgotAdminPassword)
|
||||
s.router.Post(adminPath+"/{username}/reset-password", resetAdminPassword)
|
||||
s.router.Post(userPath+"/{username}/forgot-password", forgotUserPassword)
|
||||
s.router.Post(userPath+"/{username}/reset-password", resetUserPassword)
|
||||
if s.enableWebAdmin || s.enableWebClient {
|
||||
s.router.Group(func(router chi.Router) {
|
||||
router.Use(cleanCacheControlMiddleware)
|
||||
router.Use(compressor.Handler)
|
||||
serveStaticDir(router, webStaticFilesPath, s.staticFilesPath, true)
|
||||
})
|
||||
if s.binding.OIDC.isEnabled() {
|
||||
s.router.Get(webOIDCRedirectPath, s.handleOIDCRedirect)
|
||||
}
|
||||
if s.enableWebClient {
|
||||
s.router.Get(webRootPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
|
||||
s.redirectToWebPath(w, r, webClientLoginPath)
|
||||
})
|
||||
s.router.Get(webBasePath, func(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
|
||||
s.redirectToWebPath(w, r, webClientLoginPath)
|
||||
})
|
||||
} else {
|
||||
s.router.Get(webRootPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
|
||||
s.redirectToWebPath(w, r, webAdminLoginPath)
|
||||
})
|
||||
s.router.Get(webBasePath, func(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
|
||||
s.redirectToWebPath(w, r, webAdminLoginPath)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
s.setupWebClientRoutes()
|
||||
s.setupWebAdminRoutes()
|
||||
}
|
||||
|
||||
func (s *httpdServer) setupRESTAPIRoutes() {
|
||||
if s.enableRESTAPI {
|
||||
if !s.binding.isAdminTokenEndpointDisabled() {
|
||||
s.router.Get(tokenPath, s.getToken)
|
||||
s.router.Post(adminPath+"/{username}/forgot-password", forgotAdminPassword)
|
||||
s.router.Post(adminPath+"/{username}/reset-password", resetAdminPassword)
|
||||
}
|
||||
|
||||
s.router.Group(func(router chi.Router) {
|
||||
router.Use(checkNodeToken(s.tokenAuth))
|
||||
router.Use(checkAPIKeyAuth(s.tokenAuth, dataprovider.APIKeyScopeAdmin))
|
||||
if !s.binding.isAdminAPIKeyAuthDisabled() {
|
||||
router.Use(checkAPIKeyAuth(s.tokenAuth, dataprovider.APIKeyScopeAdmin))
|
||||
}
|
||||
router.Use(jwtauth.Verify(s.tokenAuth, jwtauth.TokenFromHeader))
|
||||
router.Use(jwtAuthenticatorAPI)
|
||||
|
||||
|
|
@ -1426,10 +1462,23 @@ func (s *httpdServer) initializeRouter() {
|
|||
})
|
||||
})
|
||||
|
||||
s.router.Get(userTokenPath, s.getUserToken)
|
||||
// share API available to external users
|
||||
s.router.Get(sharesPath+"/{id}", s.downloadFromShare)
|
||||
s.router.Post(sharesPath+"/{id}", s.uploadFilesToShare)
|
||||
s.router.Post(sharesPath+"/{id}/{name}", s.uploadFileToShare)
|
||||
s.router.With(compressor.Handler).Get(sharesPath+"/{id}/dirs", s.readBrowsableShareContents)
|
||||
s.router.Get(sharesPath+"/{id}/files", s.downloadBrowsableSharedFile)
|
||||
|
||||
if !s.binding.isUserTokenEndpointDisabled() {
|
||||
s.router.Get(userTokenPath, s.getUserToken)
|
||||
s.router.Post(userPath+"/{username}/forgot-password", forgotUserPassword)
|
||||
s.router.Post(userPath+"/{username}/reset-password", resetUserPassword)
|
||||
}
|
||||
|
||||
s.router.Group(func(router chi.Router) {
|
||||
router.Use(checkAPIKeyAuth(s.tokenAuth, dataprovider.APIKeyScopeUser))
|
||||
if !s.binding.isUserAPIKeyAuthDisabled() {
|
||||
router.Use(checkAPIKeyAuth(s.tokenAuth, dataprovider.APIKeyScopeUser))
|
||||
}
|
||||
router.Use(jwtauth.Verify(s.tokenAuth, jwtauth.TokenFromHeader))
|
||||
router.Use(jwtAuthenticatorAPIUser)
|
||||
|
||||
|
|
@ -1495,39 +1544,6 @@ func (s *httpdServer) initializeRouter() {
|
|||
})
|
||||
}
|
||||
}
|
||||
|
||||
if s.enableWebAdmin || s.enableWebClient {
|
||||
s.router.Group(func(router chi.Router) {
|
||||
router.Use(cleanCacheControlMiddleware)
|
||||
router.Use(compressor.Handler)
|
||||
serveStaticDir(router, webStaticFilesPath, s.staticFilesPath, true)
|
||||
})
|
||||
if s.binding.OIDC.isEnabled() {
|
||||
s.router.Get(webOIDCRedirectPath, s.handleOIDCRedirect)
|
||||
}
|
||||
if s.enableWebClient {
|
||||
s.router.Get(webRootPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
|
||||
s.redirectToWebPath(w, r, webClientLoginPath)
|
||||
})
|
||||
s.router.Get(webBasePath, func(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
|
||||
s.redirectToWebPath(w, r, webClientLoginPath)
|
||||
})
|
||||
} else {
|
||||
s.router.Get(webRootPath, func(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
|
||||
s.redirectToWebPath(w, r, webAdminLoginPath)
|
||||
})
|
||||
s.router.Get(webBasePath, func(w http.ResponseWriter, r *http.Request) {
|
||||
r.Body = http.MaxBytesReader(w, r.Body, maxRequestSize)
|
||||
s.redirectToWebPath(w, r, webAdminLoginPath)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
s.setupWebClientRoutes()
|
||||
s.setupWebAdminRoutes()
|
||||
}
|
||||
|
||||
func (s *httpdServer) setupWebClientRoutes() {
|
||||
|
|
|
|||
|
|
@ -86,7 +86,7 @@ func (m *dbTokenManager) Add(token string, expiresAt time.Time) {
|
|||
|
||||
func (m *dbTokenManager) Get(token string) bool {
|
||||
key := m.getKey(token)
|
||||
_, err := dataprovider.GetSharedSession(key)
|
||||
_, err := dataprovider.GetSharedSession(key, dataprovider.SessionTypeInvalidToken)
|
||||
return err == nil
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -27,23 +27,20 @@ import (
|
|||
)
|
||||
|
||||
const (
|
||||
pageMFATitle = "Two-factor authentication"
|
||||
pageTwoFactorTitle = "Two-Factor authentication"
|
||||
pageTwoFactorRecoveryTitle = "Two-Factor recovery"
|
||||
webDateTimeFormat = "2006-01-02 15:04:05" // YYYY-MM-DD HH:MM:SS
|
||||
redactedSecret = "[**redacted**]"
|
||||
csrfFormToken = "_form_token"
|
||||
csrfHeaderToken = "X-CSRF-TOKEN"
|
||||
templateCommonDir = "common"
|
||||
templateTwoFactor = "twofactor.html"
|
||||
templateTwoFactorRecovery = "twofactor-recovery.html"
|
||||
templateForgotPassword = "forgot-password.html"
|
||||
templateResetPassword = "reset-password.html"
|
||||
templateChangePwd = "changepassword.html"
|
||||
templateMessage = "message.html"
|
||||
templateCommonBase = "base.html"
|
||||
templateCommonBaseLogin = "baselogin.html"
|
||||
templateCommonLogin = "login.html"
|
||||
webDateTimeFormat = "2006-01-02 15:04:05" // YYYY-MM-DD HH:MM:SS
|
||||
redactedSecret = "[**redacted**]"
|
||||
csrfFormToken = "_form_token"
|
||||
csrfHeaderToken = "X-CSRF-TOKEN"
|
||||
templateCommonDir = "common"
|
||||
templateTwoFactor = "twofactor.html"
|
||||
templateTwoFactorRecovery = "twofactor-recovery.html"
|
||||
templateForgotPassword = "forgot-password.html"
|
||||
templateResetPassword = "reset-password.html"
|
||||
templateChangePwd = "changepassword.html"
|
||||
templateMessage = "message.html"
|
||||
templateCommonBase = "base.html"
|
||||
templateCommonBaseLogin = "baselogin.html"
|
||||
templateCommonLogin = "login.html"
|
||||
)
|
||||
|
||||
var (
|
||||
|
|
|
|||
|
|
@ -752,7 +752,7 @@ func (s *httpdServer) renderResetPwdPage(w http.ResponseWriter, r *http.Request,
|
|||
func (s *httpdServer) renderTwoFactorPage(w http.ResponseWriter, r *http.Request, err *util.I18nError) {
|
||||
data := twoFactorPage{
|
||||
commonBasePage: getCommonBasePage(r),
|
||||
Title: pageTwoFactorTitle,
|
||||
Title: util.I18n2FATitle,
|
||||
CurrentURL: webAdminTwoFactorPath,
|
||||
Error: err,
|
||||
CSRFToken: createCSRFToken(w, r, s.csrfTokenAuth, "", webBaseAdminPath),
|
||||
|
|
@ -766,7 +766,7 @@ func (s *httpdServer) renderTwoFactorPage(w http.ResponseWriter, r *http.Request
|
|||
func (s *httpdServer) renderTwoFactorRecoveryPage(w http.ResponseWriter, r *http.Request, err *util.I18nError) {
|
||||
data := twoFactorPage{
|
||||
commonBasePage: getCommonBasePage(r),
|
||||
Title: pageTwoFactorRecoveryTitle,
|
||||
Title: util.I18n2FATitle,
|
||||
CurrentURL: webAdminTwoFactorRecoveryPath,
|
||||
Error: err,
|
||||
CSRFToken: createCSRFToken(w, r, s.csrfTokenAuth, "", webBaseAdminPath),
|
||||
|
|
@ -778,7 +778,7 @@ func (s *httpdServer) renderTwoFactorRecoveryPage(w http.ResponseWriter, r *http
|
|||
|
||||
func (s *httpdServer) renderMFAPage(w http.ResponseWriter, r *http.Request) {
|
||||
data := mfaPage{
|
||||
basePage: s.getBasePageData(pageMFATitle, webAdminMFAPath, w, r),
|
||||
basePage: s.getBasePageData(util.I18n2FATitle, webAdminMFAPath, w, r),
|
||||
TOTPConfigs: mfa.GetAvailableTOTPConfigNames(),
|
||||
GenerateTOTPURL: webAdminTOTPGeneratePath,
|
||||
ValidateTOTPURL: webAdminTOTPValidatePath,
|
||||
|
|
@ -3111,7 +3111,11 @@ func (s *httpdServer) handleWebAddAdminPost(w http.ResponseWriter, r *http.Reque
|
|||
s.renderAddUpdateAdminPage(w, r, &admin, err, true)
|
||||
return
|
||||
}
|
||||
if admin.Password == "" && s.binding.isWebAdminLoginFormDisabled() {
|
||||
if admin.Password == "" {
|
||||
// Administrators can be used with OpenID Connect or for authentication
|
||||
// via API key, in these cases the password is not necessary, we create
|
||||
// a non-usable one. This feature is only useful for WebAdmin, in REST
|
||||
// API you can create an unusable password externally.
|
||||
admin.Password = util.GenerateUniqueID()
|
||||
}
|
||||
ipAddr := util.GetIPFromRemoteAddress(r.RemoteAddr)
|
||||
|
|
|
|||
|
|
@ -145,16 +145,18 @@ type filesPage struct {
|
|||
Error *util.I18nError
|
||||
Paths []dirMapping
|
||||
QuotaUsage *userQuotaUsage
|
||||
KeepAliveInterval int
|
||||
}
|
||||
|
||||
type shareLoginPage struct {
|
||||
commonBasePage
|
||||
CurrentURL string
|
||||
Error *util.I18nError
|
||||
CSRFToken string
|
||||
Title string
|
||||
Branding UIBranding
|
||||
Languages []string
|
||||
CurrentURL string
|
||||
Error *util.I18nError
|
||||
CSRFToken string
|
||||
Title string
|
||||
Branding UIBranding
|
||||
Languages []string
|
||||
CheckRedirect bool
|
||||
}
|
||||
|
||||
type shareDownloadPage struct {
|
||||
|
|
@ -598,6 +600,7 @@ func (s *httpdServer) renderShareLoginPage(w http.ResponseWriter, r *http.Reques
|
|||
CSRFToken: createCSRFToken(w, r, s.csrfTokenAuth, xid.New().String(), webBaseClientPath),
|
||||
Branding: s.binding.webClientBranding(),
|
||||
Languages: s.binding.languages(),
|
||||
CheckRedirect: false,
|
||||
}
|
||||
renderClientTemplate(w, templateShareLogin, data)
|
||||
}
|
||||
|
|
@ -642,7 +645,7 @@ func (s *httpdServer) renderClientNotFoundPage(w http.ResponseWriter, r *http.Re
|
|||
func (s *httpdServer) renderClientTwoFactorPage(w http.ResponseWriter, r *http.Request, err *util.I18nError) {
|
||||
data := twoFactorPage{
|
||||
commonBasePage: getCommonBasePage(r),
|
||||
Title: pageTwoFactorTitle,
|
||||
Title: util.I18n2FATitle,
|
||||
CurrentURL: webClientTwoFactorPath,
|
||||
Error: err,
|
||||
CSRFToken: createCSRFToken(w, r, s.csrfTokenAuth, "", webBaseClientPath),
|
||||
|
|
@ -659,7 +662,7 @@ func (s *httpdServer) renderClientTwoFactorPage(w http.ResponseWriter, r *http.R
|
|||
func (s *httpdServer) renderClientTwoFactorRecoveryPage(w http.ResponseWriter, r *http.Request, err *util.I18nError) {
|
||||
data := twoFactorPage{
|
||||
commonBasePage: getCommonBasePage(r),
|
||||
Title: pageTwoFactorRecoveryTitle,
|
||||
Title: util.I18n2FATitle,
|
||||
CurrentURL: webClientTwoFactorRecoveryPath,
|
||||
Error: err,
|
||||
CSRFToken: createCSRFToken(w, r, s.csrfTokenAuth, "", webBaseClientPath),
|
||||
|
|
@ -781,6 +784,7 @@ func (s *httpdServer) renderSharedFilesPage(w http.ResponseWriter, r *http.Reque
|
|||
CanCopy: false,
|
||||
Paths: getDirMapping(dirName, currentURL),
|
||||
QuotaUsage: newUserQuotaUsage(&dataprovider.User{}),
|
||||
KeepAliveInterval: int(cookieRefreshThreshold / time.Millisecond),
|
||||
}
|
||||
renderClientTemplate(w, templateClientFiles, data)
|
||||
}
|
||||
|
|
@ -837,6 +841,7 @@ func (s *httpdServer) renderFilesPage(w http.ResponseWriter, r *http.Request, di
|
|||
ShareUploadBaseURL: "",
|
||||
Paths: getDirMapping(dirName, webClientFilesPath),
|
||||
QuotaUsage: newUserQuotaUsage(user),
|
||||
KeepAliveInterval: int(cookieRefreshThreshold / time.Millisecond),
|
||||
}
|
||||
renderClientTemplate(w, templateClientFiles, data)
|
||||
}
|
||||
|
|
@ -897,7 +902,7 @@ func (s *httpdServer) handleWebClientDownloadZip(w http.ResponseWriter, r *http.
|
|||
connID := xid.New().String()
|
||||
protocol := getProtocolFromRequest(r)
|
||||
connectionID := fmt.Sprintf("%v_%v", protocol, connID)
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false, false); err != nil {
|
||||
s.renderClientForbiddenPage(w, r, err)
|
||||
return
|
||||
}
|
||||
|
|
@ -1187,7 +1192,7 @@ func (s *httpdServer) handleClientGetDirContents(w http.ResponseWriter, r *http.
|
|||
connID := xid.New().String()
|
||||
protocol := getProtocolFromRequest(r)
|
||||
connectionID := fmt.Sprintf("%s_%s", protocol, connID)
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false, false); err != nil {
|
||||
sendAPIResponse(w, r, err, getI18NErrorString(err, util.I18nErrorDirList403), http.StatusForbidden)
|
||||
return
|
||||
}
|
||||
|
|
@ -1276,7 +1281,7 @@ func (s *httpdServer) handleClientGetFiles(w http.ResponseWriter, r *http.Reques
|
|||
connID := xid.New().String()
|
||||
protocol := getProtocolFromRequest(r)
|
||||
connectionID := fmt.Sprintf("%v_%v", protocol, connID)
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false, false); err != nil {
|
||||
s.renderClientForbiddenPage(w, r, err)
|
||||
return
|
||||
}
|
||||
|
|
@ -1337,7 +1342,7 @@ func (s *httpdServer) handleClientEditFile(w http.ResponseWriter, r *http.Reques
|
|||
connID := xid.New().String()
|
||||
protocol := getProtocolFromRequest(r)
|
||||
connectionID := fmt.Sprintf("%v_%v", protocol, connID)
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false, false); err != nil {
|
||||
s.renderClientForbiddenPage(w, r, err)
|
||||
return
|
||||
}
|
||||
|
|
@ -1833,7 +1838,7 @@ func (s *httpdServer) handleClientGetPDF(w http.ResponseWriter, r *http.Request)
|
|||
connID := xid.New().String()
|
||||
protocol := getProtocolFromRequest(r)
|
||||
connectionID := fmt.Sprintf("%v_%v", protocol, connID)
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false); err != nil {
|
||||
if err := checkHTTPClientUser(&user, r, connectionID, false, false); err != nil {
|
||||
s.renderClientForbiddenPage(w, r, err)
|
||||
return
|
||||
}
|
||||
|
|
|
|||
|
|
@ -93,7 +93,7 @@ func (m *dbTaskManager) Add(data webTaskData) error {
|
|||
}
|
||||
|
||||
func (m *dbTaskManager) Get(ID string) (webTaskData, error) {
|
||||
sess, err := dataprovider.GetSharedSession(ID)
|
||||
sess, err := dataprovider.GetSharedSession(ID, dataprovider.SessionTypeWebTask)
|
||||
if err != nil {
|
||||
return webTaskData{}, err
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build linux
|
||||
// +build linux
|
||||
|
||||
package logger
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !linux
|
||||
// +build !linux
|
||||
|
||||
package logger
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !nometrics
|
||||
// +build !nometrics
|
||||
|
||||
// Package metric provides Prometheus metrics support
|
||||
package metric
|
||||
|
|
|
|||
|
|
@ -1,5 +1,18 @@
|
|||
// Copyright (C) 2019 Nicola Murino
|
||||
//
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU Affero General Public License as published
|
||||
// by the Free Software Foundation, version 3.
|
||||
//
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU Affero General Public License for more details.
|
||||
//
|
||||
// You should have received a copy of the GNU Affero General Public License
|
||||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build nometrics
|
||||
// +build nometrics
|
||||
|
||||
package metric
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build awscontainer
|
||||
// +build awscontainer
|
||||
|
||||
package service
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !awscontainer
|
||||
// +build !awscontainer
|
||||
|
||||
package service
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !noportable
|
||||
// +build !noportable
|
||||
|
||||
package service
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package service
|
||||
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package sftpd
|
||||
|
||||
|
|
|
|||
|
|
@ -831,7 +831,7 @@ func TestRsyncOptions(t *testing.T) {
|
|||
user := dataprovider.User{
|
||||
BaseUser: sdk.BaseUser{
|
||||
Permissions: permissions,
|
||||
HomeDir: os.TempDir(),
|
||||
HomeDir: filepath.Clean(os.TempDir()),
|
||||
},
|
||||
}
|
||||
conn := &Connection{
|
||||
|
|
@ -844,7 +844,7 @@ func TestRsyncOptions(t *testing.T) {
|
|||
}
|
||||
cmd, err := sshCmd.getSystemCommand()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, slices.Contains(cmd.cmd.Args, "--safe-links"),
|
||||
assert.Equal(t, []string{"rsync", "--server", "-vlogDtprze.iLsfxC", "--safe-links", ".", user.HomeDir + string(os.PathSeparator)}, cmd.cmd.Args,
|
||||
"--safe-links must be added if the user has the create symlinks permission")
|
||||
|
||||
permissions["/"] = []string{dataprovider.PermDownload, dataprovider.PermUpload, dataprovider.PermCreateDirs,
|
||||
|
|
@ -854,6 +854,12 @@ func TestRsyncOptions(t *testing.T) {
|
|||
conn = &Connection{
|
||||
BaseConnection: common.NewBaseConnection("", common.ProtocolSFTP, "", "", user),
|
||||
}
|
||||
sshCmd = sshCommand{
|
||||
command: "rsync",
|
||||
connection: conn,
|
||||
}
|
||||
_, err = sshCmd.getSystemCommand()
|
||||
assert.Error(t, err)
|
||||
sshCmd = sshCommand{
|
||||
command: "rsync",
|
||||
connection: conn,
|
||||
|
|
@ -861,8 +867,8 @@ func TestRsyncOptions(t *testing.T) {
|
|||
}
|
||||
cmd, err = sshCmd.getSystemCommand()
|
||||
assert.NoError(t, err)
|
||||
assert.True(t, slices.Contains(cmd.cmd.Args, "--munge-links"),
|
||||
"--munge-links must be added if the user has the create symlinks permission")
|
||||
assert.Equal(t, []string{"rsync", "--server", "-vlogDtprze.iLsfxC", "--munge-links", ".", user.HomeDir + string(os.PathSeparator)}, cmd.cmd.Args,
|
||||
"--munge-links must be added if the user hasn't the create symlinks permission")
|
||||
|
||||
sshCmd.connection.User.VirtualFolders = append(sshCmd.connection.User.VirtualFolders, vfs.VirtualFolder{
|
||||
BaseVirtualFolder: vfs.BaseVirtualFolder{
|
||||
|
|
@ -2241,3 +2247,43 @@ func TestAuthenticationErrors(t *testing.T) {
|
|||
assert.ErrorIs(t, err, sftpAuthError)
|
||||
assert.NotErrorIs(t, err, util.ErrNotFound)
|
||||
}
|
||||
|
||||
func TestRsyncArguments(t *testing.T) {
|
||||
assert.False(t, canAcceptRsyncArgs(nil))
|
||||
args := []string{"-e", "--server"}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "--sender", "-vlogDtpre.iLsfxCIvu", ".", "."}
|
||||
assert.True(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "--sender", "--server", "-vlogDtpre.iLsfxCIvu", ".", "."}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "..", "/"}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", ".", "/"}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "--sender", "-vlogDtpre.iLsfxCIvu", ".", "."}
|
||||
assert.True(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "--sender", "-vlogDtpre.iLsfxCIvu", "--delete", ".", "/"}
|
||||
assert.True(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "-vlogDtpre.iLsfxCIvu", "--delete", ".", "/"}
|
||||
assert.True(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "-vlogDtpre.iLsfxCIvu", "--delete", "/", ".", "/"}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "--sender", "-vlogDtpre.iLsfxCIvu", ".", "path1", "path2"}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "--sender", "-vlogDtpre.iLsfxCIvu", "."}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--sender", "-vlogDtpre.iLsfxCIvu", "--delete", ".", "/"}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "-vlogDtpre.", "--delete", ".", "/"}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "--sender", "-vlogDtpre.", "--delete", ".", "/"}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "--sender", "-e.iLsfxCIvu", ".", "/"}
|
||||
assert.True(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "-vlogDtpre.iLsfxCIvu", "--delete", "/"}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "-vlogDtpre.iLsfxCIvu", "--delete", "--safe-links"}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
args = []string{"--server", "-vlogDtpre.iLsfxCIvu", "--unsupported-option", ".", "/"}
|
||||
assert.False(t, canAcceptRsyncArgs(args))
|
||||
}
|
||||
|
|
|
|||
|
|
@ -13,7 +13,6 @@
|
|||
// along with this program. If not, see <https://www.gnu.org/licenses/>.
|
||||
|
||||
//go:build !windows
|
||||
// +build !windows
|
||||
|
||||
package sftpd
|
||||
|
||||
|
|
|
|||
|
|
@ -130,7 +130,7 @@ type Configuration struct {
|
|||
// preference order.
|
||||
KexAlgorithms []string `json:"kex_algorithms" mapstructure:"kex_algorithms"`
|
||||
// MinDHGroupExchangeKeySize defines the minimum key size to allow for the
|
||||
// key exchanges when using diffie-ellman-group-exchange-sha1 or sha256 key
|
||||
// key exchanges when using diffie-hellman-group-exchange-sha1 or sha256 key
|
||||
// exchange algorithms.
|
||||
MinDHGroupExchangeKeySize int `json:"min_dh_group_exchange_key_size" mapstructure:"min_dh_group_exchange_key_size"`
|
||||
// Ciphers specifies the ciphers allowed
|
||||
|
|
@ -327,7 +327,7 @@ func (c *Configuration) Initialize(configDir string) error {
|
|||
}
|
||||
|
||||
ssh.SetDHKexServerMinBits(uint32(c.MinDHGroupExchangeKeySize))
|
||||
logger.Debug(logSender, "", "minimum key size allowed for diffie-ellman-group-exchange: %d",
|
||||
logger.Debug(logSender, "", "minimum key size allowed for diffie-hellman-group-exchange: %d",
|
||||
ssh.GetDHKexServerMinBits())
|
||||
sftp.SetSFTPExtensions(sftpExtensions...) //nolint:errcheck // we configure valid SFTP Extensions so we cannot get an error
|
||||
sftp.MaxFilelist = 250
|
||||
|
|
@ -592,7 +592,7 @@ func (c *Configuration) AcceptInboundConnection(conn net.Conn, config *ssh.Serve
|
|||
conn.SetDeadline(time.Time{}) //nolint:errcheck
|
||||
go ssh.DiscardRequests(reqs)
|
||||
|
||||
defer conn.Close()
|
||||
defer sconn.Close()
|
||||
|
||||
var user dataprovider.User
|
||||
|
||||
|
|
@ -615,7 +615,7 @@ func (c *Configuration) AcceptInboundConnection(conn net.Conn, config *ssh.Serve
|
|||
|
||||
dataprovider.UpdateLastLogin(&user)
|
||||
|
||||
sshConnection := common.NewSSHConnection(connectionID, conn)
|
||||
sshConnection := common.NewSSHConnection(connectionID, sconn)
|
||||
common.Connections.AddSSHConnection(sshConnection)
|
||||
|
||||
defer common.Connections.RemoveSSHConnection(connectionID)
|
||||
|
|
@ -857,11 +857,12 @@ func (c *Configuration) generateDefaultHostKeys(configDir string) error {
|
|||
if _, err = os.Stat(autoFile); errors.Is(err, fs.ErrNotExist) {
|
||||
logger.Info(logSender, "", "No host keys configured and %q does not exist; try to create a new host key", autoFile)
|
||||
logger.InfoToConsole("No host keys configured and %q does not exist; try to create a new host key", autoFile)
|
||||
if k == defaultPrivateRSAKeyName {
|
||||
switch k {
|
||||
case defaultPrivateRSAKeyName:
|
||||
err = util.GenerateRSAKeys(autoFile)
|
||||
} else if k == defaultPrivateECDSAKeyName {
|
||||
case defaultPrivateECDSAKeyName:
|
||||
err = util.GenerateECDSAKeys(autoFile)
|
||||
} else {
|
||||
default:
|
||||
err = util.GenerateEd25519Keys(autoFile)
|
||||
}
|
||||
if err != nil {
|
||||
|
|
|
|||
|
|
@ -3011,13 +3011,46 @@ func TestPreLoginScript(t *testing.T) {
|
|||
err = dataprovider.Initialize(providerConf, configDir, true)
|
||||
assert.NoError(t, err)
|
||||
|
||||
mappedPath := filepath.Join(os.TempDir(), "vdir")
|
||||
folderName := filepath.Base(mappedPath)
|
||||
f := vfs.BaseVirtualFolder{
|
||||
Name: folderName,
|
||||
MappedPath: mappedPath,
|
||||
FsConfig: vfs.Filesystem{
|
||||
Provider: sdk.CryptedFilesystemProvider,
|
||||
CryptConfig: vfs.CryptFsConfig{
|
||||
Passphrase: kms.NewPlainSecret(defaultPassword),
|
||||
},
|
||||
},
|
||||
}
|
||||
_, _, err = httpdtest.AddFolder(f, http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
|
||||
folderMountPath := "/vpath"
|
||||
u.VirtualFolders = append(u.VirtualFolders, vfs.VirtualFolder{
|
||||
BaseVirtualFolder: vfs.BaseVirtualFolder{
|
||||
Name: folderName,
|
||||
},
|
||||
VirtualPath: folderMountPath,
|
||||
})
|
||||
user, _, err := httpdtest.AddUser(u, http.StatusCreated)
|
||||
assert.NoError(t, err)
|
||||
conn, client, err := getSftpClient(u, usePubKey)
|
||||
if assert.NoError(t, err) {
|
||||
defer conn.Close()
|
||||
defer client.Close()
|
||||
|
||||
assert.NoError(t, checkBasicSFTP(client))
|
||||
testFilePath := filepath.Join(homeBasePath, testFileName)
|
||||
testData := []byte("test data")
|
||||
err = os.WriteFile(testFilePath, testData, 0666)
|
||||
assert.NoError(t, err)
|
||||
err = sftpUploadFile(testFilePath, path.Join(folderMountPath, testFileName), int64(len(testData)), client)
|
||||
assert.NoError(t, err)
|
||||
info, err := os.Stat(filepath.Join(mappedPath, testFileName))
|
||||
if assert.NoError(t, err) {
|
||||
assert.Greater(t, info.Size(), int64(len(testData)))
|
||||
}
|
||||
}
|
||||
err = os.WriteFile(preLoginPath, getPreLoginScriptContent(user, true), os.ModePerm)
|
||||
assert.NoError(t, err)
|
||||
|
|
@ -3054,6 +3087,10 @@ func TestPreLoginScript(t *testing.T) {
|
|||
assert.NoError(t, err)
|
||||
err = os.RemoveAll(user.GetHomeDir())
|
||||
assert.NoError(t, err)
|
||||
_, err = httpdtest.RemoveFolder(vfs.BaseVirtualFolder{Name: folderName}, http.StatusOK)
|
||||
assert.NoError(t, err)
|
||||
err = os.RemoveAll(mappedPath)
|
||||
assert.NoError(t, err)
|
||||
err = dataprovider.Close()
|
||||
assert.NoError(t, err)
|
||||
err = config.LoadConfig(configDir, "")
|
||||
|
|
|
|||
Some files were not shown because too many files have changed in this diff Show more
Loading…
Add table
Add a link
Reference in a new issue