Compare commits

...

18 Commits

Author SHA1 Message Date
henrygd
3e73399b87 fix battery detection on newer macs (#1170) 2025-09-15 12:02:50 -04:00
Ryan W
e149366451 Fixing service name in helm chart and making default values unopinionated (#1166) 2025-09-13 12:09:36 -04:00
henrygd
8da1ded73e strip whitespace from TOKEN_FILE (#984) 2025-09-12 12:59:53 -04:00
henrygd
efa37b2312 web: extra check for valid system before adding (#1063) 2025-09-11 15:37:11 -04:00
henrygd
bcdb4c92b5 add freebsd to list of copyable commands 2025-09-11 15:07:37 -04:00
henrygd
a7d07310b6 Add AUTO_LOGIN environment variable for automatic login. (#399) 2025-09-11 14:01:09 -04:00
hank
8db87e5497 Update Crowdin configuration file 2025-09-11 12:45:43 -04:00
henrygd
e601a0d564 add TRUSTED_AUTH_HEADER for auth forwarding (#399) 2025-09-10 21:26:59 -04:00
Fankesyooni
07491108cd new zh-CN translations (#1160) 2025-09-10 13:34:17 -04:00
henrygd
42ab17de1f move i18n.yml to project root 2025-09-10 13:30:42 -04:00
henrygd
2d14174f61 update i18n.yml 2025-09-10 13:28:06 -04:00
henrygd
a19ccc9263 comments 2025-09-09 17:13:15 -04:00
henrygd
956880aa59 improve container filtering performance
- also a few instances of autoformat
2025-09-09 16:59:16 -04:00
henrygd
b2b54db409 update makefile with proper site src path 2025-09-09 15:41:15 -04:00
henrygd
32d5188eef path updates after reorganization 2025-09-09 13:53:36 -04:00
henrygd
46dab7f531 fix gitignore after reorganization 2025-09-09 13:51:46 -04:00
henrygd
c898a9ebbc update /src to /internal 2025-09-09 13:35:34 -04:00
henrygd
8a13b05c20 rename /src to /internal (sorry i'll fix the prs) 2025-09-09 13:29:07 -04:00
204 changed files with 433 additions and 182 deletions

View File

@@ -1,6 +1,6 @@
# Node.js dependencies
node_modules
src/site/node_modules
internalsite/node_modules
# Go build artifacts and binaries
build

View File

@@ -14,21 +14,21 @@ jobs:
include:
- image: henrygd/beszel
context: ./
dockerfile: ./src/dockerfile_hub
dockerfile: ./internal/dockerfile_hub
registry: docker.io
username_secret: DOCKERHUB_USERNAME
password_secret: DOCKERHUB_TOKEN
- image: henrygd/beszel-agent
context: ./
dockerfile: ./src/dockerfile_agent
dockerfile: ./internal/dockerfile_agent
registry: docker.io
username_secret: DOCKERHUB_USERNAME
password_secret: DOCKERHUB_TOKEN
- image: henrygd/beszel-agent-nvidia
context: ./
dockerfile: ./src/dockerfile_agent_nvidia
dockerfile: ./internal/dockerfile_agent_nvidia
platforms: linux/amd64
registry: docker.io
username_secret: DOCKERHUB_USERNAME
@@ -36,21 +36,21 @@ jobs:
- image: ghcr.io/${{ github.repository }}/beszel
context: ./
dockerfile: ./src/dockerfile_hub
dockerfile: ./internal/dockerfile_hub
registry: ghcr.io
username: ${{ github.actor }}
password_secret: GITHUB_TOKEN
- image: ghcr.io/${{ github.repository }}/beszel-agent
context: ./
dockerfile: ./src/dockerfile_agent
dockerfile: ./internal/dockerfile_agent
registry: ghcr.io
username: ${{ github.actor }}
password_secret: GITHUB_TOKEN
- image: ghcr.io/${{ github.repository }}/beszel-agent-nvidia
context: ./
dockerfile: ./src/dockerfile_agent_nvidia
dockerfile: ./internal/dockerfile_agent_nvidia
platforms: linux/amd64
registry: ghcr.io
username: ${{ github.actor }}
@@ -68,10 +68,10 @@ jobs:
uses: oven-sh/setup-bun@v2
- name: Install dependencies
run: bun install --no-save --cwd ./src/site
run: bun install --no-save --cwd ./internal/site
- name: Build site
run: bun run --cwd ./src/site build
run: bun run --cwd ./internal/site build
- name: Set up QEMU
uses: docker/setup-qemu-action@v3

View File

@@ -21,10 +21,10 @@ jobs:
uses: oven-sh/setup-bun@v2
- name: Install dependencies
run: bun install --no-save --cwd ./src/site
run: bun install --no-save --cwd ./internal/site
- name: Build site
run: bun run --cwd ./src/site build
run: bun run --cwd ./internal/site build
- name: Set up Go
uses: actions/setup-go@v5

6
.gitignore vendored
View File

@@ -8,13 +8,13 @@ beszel_data
beszel_data*
dist
*.exe
src/cmd/hub/hub
src/cmd/agent/agent
internal/cmd/hub/hub
internal/cmd/agent/agent
node_modules
build
*timestamp*
.swc
src/site/src/locales/**/*.ts
internal/site/src/locales/**/*.ts
*.bak
__debug_*
agent/lhm/obj

View File

@@ -9,7 +9,7 @@ before:
builds:
- id: beszel
binary: beszel
main: src/cmd/hub/hub.go
main: internal/cmd/hub/hub.go
env:
- CGO_ENABLED=0
goos:
@@ -22,7 +22,7 @@ builds:
- id: beszel-agent
binary: beszel-agent
main: src/cmd/agent/agent.go
main: internal/cmd/agent/agent.go
env:
- CGO_ENABLED=0
goos:

View File

@@ -26,11 +26,11 @@ tidy:
build-web-ui:
@if command -v bun >/dev/null 2>&1; then \
bun install --cwd ./src/site && \
bun run --cwd ./src/site build; \
bun install --cwd ./internal/site && \
bun run --cwd ./internal/site build; \
else \
npm install --prefix ./src/site && \
npm run --prefix ./src/site build; \
npm install --prefix ./internal/site && \
npm run --prefix ./internal/site build; \
fi
# Conditional .NET build - only for Windows
@@ -48,45 +48,45 @@ build-dotnet-conditional:
# Update build-agent to include conditional .NET build
build-agent: tidy build-dotnet-conditional
GOOS=$(OS) GOARCH=$(ARCH) go build -o ./build/beszel-agent_$(OS)_$(ARCH)$(EXE_EXT) -ldflags "-w -s" ./src/cmd/agent
GOOS=$(OS) GOARCH=$(ARCH) go build -o ./build/beszel-agent_$(OS)_$(ARCH)$(EXE_EXT) -ldflags "-w -s" ./internal/cmd/agent
build-hub: tidy $(if $(filter false,$(SKIP_WEB)),build-web-ui)
GOOS=$(OS) GOARCH=$(ARCH) go build -o ./build/beszel_$(OS)_$(ARCH)$(EXE_EXT) -ldflags "-w -s" ./src/cmd/hub
GOOS=$(OS) GOARCH=$(ARCH) go build -o ./build/beszel_$(OS)_$(ARCH)$(EXE_EXT) -ldflags "-w -s" ./internal/cmd/hub
build-hub-dev: tidy
mkdir -p ./src/site/dist && touch ./src/site/dist/index.html
GOOS=$(OS) GOARCH=$(ARCH) go build -tags development -o ./build/beszel-dev_$(OS)_$(ARCH)$(EXE_EXT) -ldflags "-w -s" ./src/cmd/hub
mkdir -p ./internal/site/dist && touch ./internal/site/dist/index.html
GOOS=$(OS) GOARCH=$(ARCH) go build -tags development -o ./build/beszel-dev_$(OS)_$(ARCH)$(EXE_EXT) -ldflags "-w -s" ./internal/cmd/hub
build: build-agent build-hub
generate-locales:
@if [ ! -f ./src/site/src/locales/en/en.ts ]; then \
@if [ ! -f ./internal/site/src/locales/en/en.ts ]; then \
echo "Generating locales..."; \
command -v bun >/dev/null 2>&1 && cd ./src/site && bun install && bun run sync || cd ./src/site && npm install && npm run sync; \
command -v bun >/dev/null 2>&1 && cd ./internal/site && bun install && bun run sync || cd ./internal/site && npm install && npm run sync; \
fi
dev-server: generate-locales
cd ./src/site
cd ./internal/site
@if command -v bun >/dev/null 2>&1; then \
cd ./src/site && bun run dev --host 0.0.0.0; \
cd ./internal/site && bun run dev --host 0.0.0.0; \
else \
cd ./src/site && npm run dev --host 0.0.0.0; \
cd ./internal/site && npm run dev --host 0.0.0.0; \
fi
dev-hub: export ENV=dev
dev-hub:
mkdir -p ./src/site/dist && touch ./src/site/dist/index.html
mkdir -p ./internal/site/dist && touch ./internal/site/dist/index.html
@if command -v entr >/dev/null 2>&1; then \
find ./src/cmd/hub/*.go ./src/{alerts,hub,records,users}/*.go | entr -r -s "cd ./src/cmd/hub && go run -tags development . serve --http 0.0.0.0:8090"; \
find ./internal/cmd/hub/*.go ./internal/{alerts,hub,records,users}/*.go | entr -r -s "cd ./internal/cmd/hub && go run -tags development . serve --http 0.0.0.0:8090"; \
else \
cd ./src/cmd/hub && go run -tags development . serve --http 0.0.0.0:8090; \
cd ./internal/cmd/hub && go run -tags development . serve --http 0.0.0.0:8090; \
fi
dev-agent:
@if command -v entr >/dev/null 2>&1; then \
find ./src/cmd/agent/*.go ./agent/*.go | entr -r go run github.com/henrygd/beszel/src/cmd/agent; \
find ./internal/cmd/agent/*.go ./agent/*.go | entr -r go run github.com/henrygd/beszel/internal/cmd/agent; \
else \
go run github.com/henrygd/beszel/src/cmd/agent; \
go run github.com/henrygd/beszel/internal/cmd/agent; \
fi
build-dotnet:

View File

@@ -1,4 +1,7 @@
// Package agent handles the agent's SSH server and system stats collection.
// Package agent implements the Beszel monitoring agent that collects and serves system metrics.
//
// The agent runs on monitored systems and communicates collected data
// to the Beszel hub for centralized monitoring and alerting.
package agent
import (
@@ -13,7 +16,7 @@ import (
"github.com/gliderlabs/ssh"
"github.com/henrygd/beszel"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/shirou/gopsutil/v4/host"
gossh "golang.org/x/crypto/ssh"
)

View File

@@ -3,7 +3,7 @@ package agent
import (
"time"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
)
// Not thread safe since we only access from gatherStats which is already locked

View File

@@ -8,7 +8,7 @@ import (
"testing/synctest"
"time"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

View File

@@ -20,9 +20,8 @@ func HasReadableBattery() bool {
}
haveCheckedBattery = true
bat, err := battery.Get(0)
if err == nil && bat != nil {
systemHasBattery = true
} else {
systemHasBattery = err == nil && bat != nil && bat.Design != 0 && bat.Full != 0
if !systemHasBattery {
slog.Debug("No battery found", "err", err)
}
return systemHasBattery

View File

@@ -14,7 +14,7 @@ import (
"time"
"github.com/henrygd/beszel"
"github.com/henrygd/beszel/src/common"
"github.com/henrygd/beszel/internal/common"
"github.com/fxamacker/cbor/v2"
"github.com/lxzan/gws"
@@ -85,7 +85,7 @@ func getToken() (string, error) {
if err != nil {
return "", err
}
return string(tokenBytes), nil
return strings.TrimSpace(string(tokenBytes)), nil
}
// getOptions returns the WebSocket client options, creating them if necessary.

View File

@@ -13,7 +13,7 @@ import (
"github.com/henrygd/beszel"
"github.com/henrygd/beszel/src/common"
"github.com/henrygd/beszel/internal/common"
"github.com/fxamacker/cbor/v2"
"github.com/stretchr/testify/assert"
@@ -537,4 +537,25 @@ func TestGetToken(t *testing.T) {
assert.NoError(t, err)
assert.Equal(t, "", token, "Empty file should return empty string")
})
t.Run("strips whitespace from TOKEN_FILE", func(t *testing.T) {
unsetEnvVars()
tokenWithWhitespace := " test-token-with-whitespace \n\t"
expectedToken := "test-token-with-whitespace"
tokenFile, err := os.CreateTemp("", "token-test-*.txt")
require.NoError(t, err)
defer os.Remove(tokenFile.Name())
_, err = tokenFile.WriteString(tokenWithWhitespace)
require.NoError(t, err)
tokenFile.Close()
os.Setenv("TOKEN_FILE", tokenFile.Name())
defer os.Unsetenv("TOKEN_FILE")
token, err := getToken()
assert.NoError(t, err)
assert.Equal(t, expectedToken, token, "Whitespace should be stripped from token file content")
})
}

View File

@@ -8,7 +8,7 @@ import (
"strings"
"time"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/shirou/gopsutil/v4/disk"
)

View File

@@ -14,7 +14,7 @@ import (
"sync"
"time"
"github.com/henrygd/beszel/src/entities/container"
"github.com/henrygd/beszel/internal/entities/container"
"github.com/blang/semver"
)

View File

@@ -12,7 +12,7 @@ import (
"sync"
"time"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"golang.org/x/exp/slog"
)

View File

@@ -9,7 +9,7 @@ import (
"testing"
"time"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

View File

@@ -10,7 +10,7 @@ import (
"strings"
"unicode/utf8"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/shirou/gopsutil/v4/common"
"github.com/shirou/gopsutil/v4/sensors"

View File

@@ -9,7 +9,7 @@ import (
"os"
"testing"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/shirou/gopsutil/v4/common"
"github.com/shirou/gopsutil/v4/sensors"

View File

@@ -12,8 +12,8 @@ import (
"time"
"github.com/henrygd/beszel"
"github.com/henrygd/beszel/src/common"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/common"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/blang/semver"
"github.com/fxamacker/cbor/v2"

View File

@@ -13,8 +13,8 @@ import (
"testing"
"time"
"github.com/henrygd/beszel/src/entities/container"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/container"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/blang/semver"
"github.com/fxamacker/cbor/v2"

View File

@@ -11,7 +11,7 @@ import (
"github.com/henrygd/beszel"
"github.com/henrygd/beszel/agent/battery"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/shirou/gopsutil/v4/cpu"
"github.com/shirou/gopsutil/v4/disk"

View File

@@ -8,7 +8,7 @@ import (
"runtime"
"strings"
"github.com/henrygd/beszel/src/ghupdate"
"github.com/henrygd/beszel/internal/ghupdate"
)
// restarter knows how to restart the beszel-agent service.

View File

@@ -1,10 +1,15 @@
// Package beszel provides core application constants and version information
// which are used throughout the application.
package beszel
import "github.com/blang/semver"
const (
// Version is the current version of the application.
Version = "0.12.7"
// AppName is the name of the application.
AppName = "beszel"
)
// MinVersionCbor is the minimum supported version for CBOR compatibility.
var MinVersionCbor = semver.MustParse("0.12.0")

View File

@@ -1,3 +1,3 @@
files:
- source: /beszel/site/src/locales/en/en.po
translation: /beszel/site/src/locales/%two_letters_code%/%two_letters_code%.po
- source: /internal/site/src/locales/en/
translation: /internal/site/src/locales/%two_letters_code%/%two_letters_code%.po

View File

@@ -6,7 +6,7 @@ import (
"strings"
"time"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"

View File

@@ -13,7 +13,7 @@ import (
"testing/synctest"
"time"
beszelTests "github.com/henrygd/beszel/src/tests"
beszelTests "github.com/henrygd/beszel/internal/tests"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"

View File

@@ -8,8 +8,8 @@ import (
"time"
"github.com/henrygd/beszel"
"github.com/henrygd/beszel/src/hub"
_ "github.com/henrygd/beszel/src/migrations"
"github.com/henrygd/beszel/internal/hub"
_ "github.com/henrygd/beszel/internal/migrations"
"github.com/pocketbase/pocketbase"
"github.com/pocketbase/pocketbase/plugins/migratecmd"

View File

@@ -10,7 +10,7 @@ COPY . ./
# Build
ARG TARGETOS TARGETARCH
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./src/cmd/agent
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /agent ./internal/cmd/agent
RUN rm -rf /tmp/*

View File

@@ -17,7 +17,7 @@ RUN update-ca-certificates
# Build
ARG TARGETOS TARGETARCH
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /beszel ./src/cmd/hub
RUN CGO_ENABLED=0 GOGC=75 GOOS=$TARGETOS GOARCH=$TARGETARCH go build -ldflags "-w -s" -o /beszel ./internal/cmd/hub
# ? -------------------------
FROM scratch

View File

@@ -5,7 +5,7 @@ package system
import (
"time"
"github.com/henrygd/beszel/src/entities/container"
"github.com/henrygd/beszel/internal/entities/container"
)
type Stats struct {

View File

@@ -8,9 +8,9 @@ import (
"sync"
"time"
"github.com/henrygd/beszel/src/common"
"github.com/henrygd/beszel/src/hub/expirymap"
"github.com/henrygd/beszel/src/hub/ws"
"github.com/henrygd/beszel/internal/common"
"github.com/henrygd/beszel/internal/hub/expirymap"
"github.com/henrygd/beszel/internal/hub/ws"
"github.com/blang/semver"
"github.com/lxzan/gws"

View File

@@ -15,8 +15,8 @@ import (
"time"
"github.com/henrygd/beszel/agent"
"github.com/henrygd/beszel/src/common"
"github.com/henrygd/beszel/src/hub/ws"
"github.com/henrygd/beszel/internal/common"
"github.com/henrygd/beszel/internal/hub/ws"
"github.com/pocketbase/pocketbase/core"
pbtests "github.com/pocketbase/pocketbase/tests"

View File

@@ -8,7 +8,7 @@ import (
"path/filepath"
"github.com/google/uuid"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"

View File

@@ -8,9 +8,9 @@ import (
"path/filepath"
"testing"
"github.com/henrygd/beszel/src/tests"
"github.com/henrygd/beszel/internal/tests"
"github.com/henrygd/beszel/src/hub/config"
"github.com/henrygd/beszel/internal/hub/config"
"github.com/pocketbase/pocketbase/core"
"github.com/stretchr/testify/assert"

View File

@@ -13,11 +13,11 @@ import (
"time"
"github.com/henrygd/beszel"
"github.com/henrygd/beszel/src/alerts"
"github.com/henrygd/beszel/src/hub/config"
"github.com/henrygd/beszel/src/hub/systems"
"github.com/henrygd/beszel/src/records"
"github.com/henrygd/beszel/src/users"
"github.com/henrygd/beszel/internal/alerts"
"github.com/henrygd/beszel/internal/hub/config"
"github.com/henrygd/beszel/internal/hub/systems"
"github.com/henrygd/beszel/internal/records"
"github.com/henrygd/beszel/internal/users"
"github.com/google/uuid"
"github.com/pocketbase/pocketbase"
@@ -69,6 +69,8 @@ func (h *Hub) StartHub() error {
if err := config.SyncSystems(e); err != nil {
return err
}
// register middlewares
h.registerMiddlewares(e)
// register api routes
if err := h.registerApiRoutes(e); err != nil {
return err
@@ -171,6 +173,37 @@ func (h *Hub) registerCronJobs(_ *core.ServeEvent) error {
return nil
}
// custom middlewares
func (h *Hub) registerMiddlewares(se *core.ServeEvent) {
// authorizes request with user matching the provided email
authorizeRequestWithEmail := func(e *core.RequestEvent, email string) (err error) {
if e.Auth != nil || email == "" {
return e.Next()
}
isAuthRefresh := e.Request.URL.Path == "/api/collections/users/auth-refresh" && e.Request.Method == http.MethodPost
e.Auth, err = e.App.FindFirstRecordByData("users", "email", email)
if err != nil || !isAuthRefresh {
return e.Next()
}
// auth refresh endpoint, make sure token is set in header
token, _ := e.Auth.NewAuthToken()
e.Request.Header.Set("Authorization", token)
return e.Next()
}
// authenticate with trusted header
if autoLogin, _ := GetEnv("AUTO_LOGIN"); autoLogin != "" {
se.Router.BindFunc(func(e *core.RequestEvent) error {
return authorizeRequestWithEmail(e, autoLogin)
})
}
// authenticate with trusted header
if trustedHeader, _ := GetEnv("TRUSTED_AUTH_HEADER"); trustedHeader != "" {
se.Router.BindFunc(func(e *core.RequestEvent) error {
return authorizeRequestWithEmail(e, e.Request.Header.Get(trustedHeader))
})
}
}
// custom api routes
func (h *Hub) registerApiRoutes(se *core.ServeEvent) error {
// auth protected routes

View File

@@ -15,8 +15,8 @@ import (
"strings"
"testing"
"github.com/henrygd/beszel/src/migrations"
beszelTests "github.com/henrygd/beszel/src/tests"
"github.com/henrygd/beszel/internal/migrations"
beszelTests "github.com/henrygd/beszel/internal/tests"
"github.com/pocketbase/pocketbase/core"
pbTests "github.com/pocketbase/pocketbase/tests"
@@ -711,3 +711,117 @@ func TestCreateUserEndpointAvailability(t *testing.T) {
scenario.Test(t)
})
}
func TestAutoLoginMiddleware(t *testing.T) {
var hubs []*beszelTests.TestHub
defer func() {
defer os.Unsetenv("AUTO_LOGIN")
for _, hub := range hubs {
hub.Cleanup()
}
}()
os.Setenv("AUTO_LOGIN", "user@test.com")
testAppFactory := func(t testing.TB) *pbTests.TestApp {
hub, _ := beszelTests.NewTestHub(t.TempDir())
hubs = append(hubs, hub)
hub.StartHub()
return hub.TestApp
}
scenarios := []beszelTests.ApiScenario{
{
Name: "GET /getkey - without auto login should fail",
Method: http.MethodGet,
URL: "/api/beszel/getkey",
ExpectedStatus: 401,
ExpectedContent: []string{"requires valid"},
TestAppFactory: testAppFactory,
},
{
Name: "GET /getkey - with auto login should fail if no matching user",
Method: http.MethodGet,
URL: "/api/beszel/getkey",
ExpectedStatus: 401,
ExpectedContent: []string{"requires valid"},
TestAppFactory: testAppFactory,
},
{
Name: "GET /getkey - with auto login should succeed",
Method: http.MethodGet,
URL: "/api/beszel/getkey",
ExpectedStatus: 200,
ExpectedContent: []string{"\"key\":", "\"v\":"},
TestAppFactory: testAppFactory,
BeforeTestFunc: func(t testing.TB, app *pbTests.TestApp, e *core.ServeEvent) {
beszelTests.CreateUser(app, "user@test.com", "password123")
},
},
}
for _, scenario := range scenarios {
scenario.Test(t)
}
}
func TestTrustedHeaderMiddleware(t *testing.T) {
var hubs []*beszelTests.TestHub
defer func() {
defer os.Unsetenv("TRUSTED_AUTH_HEADER")
for _, hub := range hubs {
hub.Cleanup()
}
}()
os.Setenv("TRUSTED_AUTH_HEADER", "X-Beszel-Trusted")
testAppFactory := func(t testing.TB) *pbTests.TestApp {
hub, _ := beszelTests.NewTestHub(t.TempDir())
hubs = append(hubs, hub)
hub.StartHub()
return hub.TestApp
}
scenarios := []beszelTests.ApiScenario{
{
Name: "GET /getkey - without trusted header should fail",
Method: http.MethodGet,
URL: "/api/beszel/getkey",
ExpectedStatus: 401,
ExpectedContent: []string{"requires valid"},
TestAppFactory: testAppFactory,
},
{
Name: "GET /getkey - with trusted header should fail if no matching user",
Method: http.MethodGet,
URL: "/api/beszel/getkey",
Headers: map[string]string{
"X-Beszel-Trusted": "user@test.com",
},
ExpectedStatus: 401,
ExpectedContent: []string{"requires valid"},
TestAppFactory: testAppFactory,
},
{
Name: "GET /getkey - with trusted header should succeed",
Method: http.MethodGet,
URL: "/api/beszel/getkey",
Headers: map[string]string{
"X-Beszel-Trusted": "user@test.com",
},
ExpectedStatus: 200,
ExpectedContent: []string{"\"key\":", "\"v\":"},
TestAppFactory: testAppFactory,
BeforeTestFunc: func(t testing.TB, app *pbTests.TestApp, e *core.ServeEvent) {
beszelTests.CreateUser(app, "user@test.com", "password123")
},
},
}
for _, scenario := range scenarios {
scenario.Test(t)
}
}

View File

@@ -3,7 +3,7 @@
package hub
import "github.com/henrygd/beszel/src/hub/systems"
import "github.com/henrygd/beszel/internal/hub/systems"
// TESTING ONLY: GetSystemManager returns the system manager
func (h *Hub) GetSystemManager() *systems.SystemManager {

View File

@@ -9,7 +9,7 @@ import (
"strings"
"github.com/henrygd/beszel"
"github.com/henrygd/beszel/src/site"
"github.com/henrygd/beszel/internal/site"
"github.com/pocketbase/pocketbase/apis"
"github.com/pocketbase/pocketbase/core"

View File

@@ -10,9 +10,9 @@ import (
"strings"
"time"
"github.com/henrygd/beszel/src/hub/ws"
"github.com/henrygd/beszel/internal/hub/ws"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/henrygd/beszel"

View File

@@ -5,11 +5,11 @@ import (
"fmt"
"time"
"github.com/henrygd/beszel/src/hub/ws"
"github.com/henrygd/beszel/internal/hub/ws"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/henrygd/beszel/src/common"
"github.com/henrygd/beszel/internal/common"
"github.com/henrygd/beszel"

View File

@@ -10,10 +10,10 @@ import (
"testing/synctest"
"time"
"github.com/henrygd/beszel/src/entities/container"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/src/hub/systems"
"github.com/henrygd/beszel/src/tests"
"github.com/henrygd/beszel/internal/entities/container"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/henrygd/beszel/internal/hub/systems"
"github.com/henrygd/beszel/internal/tests"
"github.com/stretchr/testify/assert"
"github.com/stretchr/testify/require"

View File

@@ -7,7 +7,7 @@ import (
"context"
"fmt"
entities "github.com/henrygd/beszel/src/entities/system"
entities "github.com/henrygd/beszel/internal/entities/system"
)
// TESTING ONLY: GetSystemCount returns the number of systems in the store

View File

@@ -6,7 +6,7 @@ import (
"os"
"os/exec"
"github.com/henrygd/beszel/src/ghupdate"
"github.com/henrygd/beszel/internal/ghupdate"
"github.com/spf13/cobra"
)

View File

@@ -5,9 +5,9 @@ import (
"time"
"weak"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/henrygd/beszel/src/common"
"github.com/henrygd/beszel/internal/common"
"github.com/fxamacker/cbor/v2"
"github.com/lxzan/gws"

View File

@@ -8,7 +8,7 @@ import (
"testing"
"time"
"github.com/henrygd/beszel/src/common"
"github.com/henrygd/beszel/internal/common"
"github.com/fxamacker/cbor/v2"
"github.com/stretchr/testify/assert"

View File

@@ -9,8 +9,8 @@ import (
"strings"
"time"
"github.com/henrygd/beszel/src/entities/container"
"github.com/henrygd/beszel/src/entities/system"
"github.com/henrygd/beszel/internal/entities/container"
"github.com/henrygd/beszel/internal/entities/system"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"

View File

@@ -8,8 +8,8 @@ import (
"testing"
"time"
"github.com/henrygd/beszel/src/records"
"github.com/henrygd/beszel/src/tests"
"github.com/henrygd/beszel/internal/records"
"github.com/henrygd/beszel/internal/tests"
"github.com/pocketbase/dbx"
"github.com/pocketbase/pocketbase/core"

View File

@@ -17,7 +17,10 @@
"linter": {
"enabled": true,
"rules": {
"recommended": true
"recommended": true,
"correctness": {
"useUniqueElementIds": "off"
}
}
},
"javascript": {
@@ -35,4 +38,4 @@
}
}
}
}
}

View File

Before

Width:  |  Height:  |  Size: 906 B

After

Width:  |  Height:  |  Size: 906 B

View File

Before

Width:  |  Height:  |  Size: 906 B

After

Width:  |  Height:  |  Size: 906 B

View File

Before

Width:  |  Height:  |  Size: 903 B

After

Width:  |  Height:  |  Size: 903 B

View File

Before

Width:  |  Height:  |  Size: 6.3 KiB

After

Width:  |  Height:  |  Size: 6.3 KiB

View File

@@ -22,7 +22,7 @@ import { memo, useEffect, useRef, useState } from "react"
import { $router, basePath, Link, navigate } from "./router"
import { SystemRecord } from "@/types"
import { SystemStatus } from "@/lib/enums"
import { AppleIcon, DockerIcon, TuxIcon, WindowsIcon } from "./ui/icons"
import { AppleIcon, DockerIcon, FreeBsdIcon, TuxIcon, WindowsIcon } from "./ui/icons"
import { InputCopy } from "./ui/input-copy"
import { getPagePath } from "@nanostores/router"
import {
@@ -253,6 +253,12 @@ export const SystemDialog = ({ setOpen, system }: { setOpen: (open: boolean) =>
copyWindowsCommand(isUnixSocket ? hostValue : port.current?.value, publicKey, token),
icons: [WindowsIcon],
},
{
text: t({ message: "FreeBSD command", context: "Button to copy install command" }),
onClick: async () =>
copyLinuxCommand(isUnixSocket ? hostValue : port.current?.value, publicKey, token),
icons: [FreeBsdIcon],
},
{
text: t`Manual setup instructions`,
url: "https://beszel.dev/guide/agent-installation#binary",

View File

@@ -1,11 +1,11 @@
import { Area, AreaChart, CartesianGrid, YAxis } from "recharts"
import { ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { type ChartConfig, ChartContainer, ChartTooltip, ChartTooltipContent, xAxis } from "@/components/ui/chart"
import { memo, useMemo } from "react"
import { cn, formatShortDate, chartMargin, toFixedFloat, formatBytes, decimalString } from "@/lib/utils"
// import Spinner from '../spinner'
import { useStore } from "@nanostores/react"
import { $containerFilter, $userSettings } from "@/lib/stores"
import { ChartData } from "@/types"
import type { ChartData } from "@/types"
import { Separator } from "../ui/separator"
import { ChartType, Unit } from "@/lib/enums"
import { useYAxisWidth } from "./hooks"
@@ -31,6 +31,7 @@ export default memo(function ContainerChart({
const isNetChart = chartType === ChartType.Network
// biome-ignore lint/correctness/useExhaustiveDependencies: not necessary
const { toolTipFormatter, dataFunction, tickFormatter } = useMemo(() => {
const obj = {} as {
toolTipFormatter: (item: any, key: string) => React.ReactNode | string
@@ -47,7 +48,7 @@ export default memo(function ContainerChart({
const chartUnit = isNetChart ? userSettings.unitNet : Unit.Bytes
obj.tickFormatter = (val) => {
const { value, unit } = formatBytes(val, isNetChart, chartUnit, true)
return updateYAxisWidth(toFixedFloat(value, value >= 10 ? 0 : 1) + " " + unit)
return updateYAxisWidth(`${toFixedFloat(value, value >= 10 ? 0 : 1)} ${unit}`)
}
}
// tooltip formatter
@@ -74,10 +75,10 @@ export default memo(function ContainerChart({
} else if (chartType === ChartType.Memory) {
obj.toolTipFormatter = (item: any) => {
const { value, unit } = formatBytes(item.value, false, Unit.Bytes, true)
return decimalString(value) + " " + unit
return `${decimalString(value)} ${unit}`
}
} else {
obj.toolTipFormatter = (item: any) => decimalString(item.value) + unit
obj.toolTipFormatter = (item: any) => `${decimalString(item.value)} ${unit}`
}
// data function
if (isNetChart) {
@@ -133,7 +134,7 @@ export default memo(function ContainerChart({
animationDuration={150}
truncate={true}
labelFormatter={(_, data) => formatShortDate(data[0].payload.created)}
// @ts-ignore
// @ts-expect-error
itemSorter={(a, b) => b.value - a.value}
content={<ChartTooltipContent filter={filter} contentFormatter={toolTipFormatter} />}
/>

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