Initial commit
Test / test (push) Successful in 7m5s
Release / gates (push) Successful in 7m28s
Release / build (amd64, freebsd) (push) Successful in 2m52s
Release / build (amd64, linux) (push) Successful in 2m46s
Release / build (arm64, freebsd) (push) Successful in 2m22s
Release / build (arm64, linux) (push) Successful in 2m38s
Release / build (loong64, linux) (push) Successful in 2m7s
Release / build (riscv64, linux) (push) Successful in 2m17s
Release / release (push) Successful in 1m0s

Assisted-by: GLM 5.3
This commit is contained in:
2026-09-29 10:03:32 +02:00
commit f8ed33df83
206 changed files with 44165 additions and 0 deletions
+182
View File
@@ -0,0 +1,182 @@
// Copyright (c) 2026 Petr Balvín <opensource@petrbalvin.org> (https://petrbalvin.org)
// SPDX-License-Identifier: PolyForm-Noncommercial-1.0.0
package admin
import (
"fmt"
"strings"
"sourcedock.dev/petrbalvin/volumen/internal/store"
"sourcedock.dev/petrbalvin/volumen/internal/tokens"
"sourcedock.dev/petrbalvin/volumen/internal/users"
"sourcedock.dev/petrbalvin/volumen/internal/webhooks"
)
// roleOption is one <option> of a role select.
type roleOption struct {
Value string
Selected bool
}
// userRow is one entry of the users panel.
type userRow struct {
Username string
Display string
Initial string
Role string
Photo string
IsSelf bool
RoleOptions []roleOption
}
// hookRow is one configured webhook endpoint.
type hookRow struct {
Index string
URL string
// Managed is false for a hook declared in config.toml, which the
// settings forms may test but not change.
Managed bool
Enabled bool
Signed bool
EventsText string
}
// deliveryRow is one webhook delivery log entry.
type deliveryRow struct {
Timestamp string
Event string
HookURL string
OK bool
StatusCode int
Error string
Attempts int
// Result is the pre-formatted failure text ("failed (N attempts)"),
// translated by the caller that knows the request's language.
Result string
}
// tokenRow is one API token table row.
type tokenRow struct {
Name string
CreatedDay string
LastUsedDay string
}
// mediaRow is one media library tile.
type mediaRow struct {
Name string
URL string
SizeKB string
// Dimensions is the header-carried pixel size ("1920 × 1080"), or
// "" when the container did not yield one.
Dimensions string
}
func roleOptions(current string) []roleOption {
out := make([]roleOption, 0, len(users.Roles))
for _, role := range users.Roles {
out = append(out, roleOption{Value: role, Selected: role == current})
}
return out
}
func userRows(current string, list []*users.User) []userRow {
out := make([]userRow, 0, len(list))
for _, user := range list {
display := user.Name
if display == "" {
display = user.Username
}
out = append(out, userRow{
Username: user.Username,
Display: display,
Initial: firstUpper(display, "?"),
Role: user.Role,
Photo: user.Photo,
IsSelf: user.Username == current,
RoleOptions: roleOptions(user.Role),
})
}
return out
}
// hookRows renders the manager's merged hook list; the first static
// count came from config.toml and the rest are the admin's to manage.
func hookRows(hooks []webhooks.Webhook, staticCount int) []hookRow {
out := make([]hookRow, 0, len(hooks))
for i, hook := range hooks {
eventsText := "all"
if len(hook.Events) > 0 {
eventsText = strings.Join(hook.Events, ", ")
}
out = append(out, hookRow{
Index: fmt.Sprintf("%d", i),
URL: hook.URL,
Managed: i >= staticCount,
Enabled: hook.Enabled,
Signed: hook.Secret != "",
EventsText: eventsText,
})
}
return out
}
func deliveryRows(list []webhooks.Delivery) []deliveryRow {
out := make([]deliveryRow, 0, len(list))
for _, d := range list {
out = append(out, deliveryRow{
Timestamp: d.Timestamp,
Event: d.Event,
HookURL: d.HookURL,
OK: d.Status == "ok",
StatusCode: d.StatusCode,
Error: d.Error,
Attempts: d.Attempts,
})
}
return out
}
func tokenRows(list []tokens.Token) []tokenRow {
out := make([]tokenRow, 0, len(list))
for _, token := range list {
lastUsed := "never"
if len(token.LastUsed) >= 10 {
lastUsed = token.LastUsed[:10]
}
created := token.Created
if len(created) >= 10 {
created = created[:10]
}
out = append(out, tokenRow{
Name: token.Name,
CreatedDay: created,
LastUsedDay: lastUsed,
})
}
return out
}
func mediaRows(list []store.Media) []mediaRow {
out := make([]mediaRow, 0, len(list))
for _, item := range list {
out = append(out, mediaRow{
Name: item.Name,
URL: item.URL,
SizeKB: fmt.Sprintf("%.1f", float64(item.Size)/1024),
Dimensions: pixelSize(item.Width, item.Height),
})
}
return out
}
// pixelSize renders the header-carried pixel size, empty when the
// container did not yield one.
func pixelSize(width, height int) string {
if width <= 0 || height <= 0 {
return ""
}
return fmt.Sprintf("%d × %d", width, height)
}