v0.332.0: one sign-in for the file manager — a dashboard pass, a host-only files cookie, a per-box secret header (R-1100, operator D16)
gates / gates (push) Successful in 47s
gates / gates (push) Successful in 47s
This commit is contained in:
@@ -264,23 +264,35 @@ networks:
|
||||
// v0.327.1). The name resolves only while FileBrowser is on traefik-public, which the box allows only after this run's
|
||||
// default login was checked — so the route can stay in place and still never reach an unchecked FileBrowser (502 then).
|
||||
// TLS as the old Docker label had it (`tls: {}`, the default certificate store / the wildcard).
|
||||
func RenderFileBrowserRoute(domain string) string {
|
||||
//
|
||||
// R-1100: with ssoHeader set, every request to files.<domain> first asks the controller (forwardAuth, FilesAuthURL).
|
||||
// traefik removes ssoHeader from the client's request whatever the answer (it is in authResponseHeaders — measured,
|
||||
// any case, twice: audits/proxyauth-spike-2026-10-18) and sets it only from the controller's 200, which carries it only
|
||||
// for a browser holding the dashboard's files pass. The same answer handles /_felhom/sso (the pass → the files cookie).
|
||||
// ssoHeader "" = the route as before, byte for byte. Pinned by TestFileBrowserRoute_R1100_*.
|
||||
func RenderFileBrowserRoute(domain, ssoHeader string) string {
|
||||
mw, mwDef := "", ""
|
||||
if ssoHeader != "" {
|
||||
mw = " middlewares:\n - " + FilesSSOMiddleware + "\n"
|
||||
mwDef = fmt.Sprintf(" middlewares:\n %s:\n forwardAuth:\n address: %q\n authResponseHeaders:\n - %q\n",
|
||||
FilesSSOMiddleware, FilesAuthURL, ssoHeader)
|
||||
}
|
||||
return fmt.Sprintf(`# Traefik dynamic route for FileBrowser (files.<domain>) — managed by felhom-controller (R-1126).
|
||||
# WARNING: auto-generated at base-infra bring-up. Manual edits are overwritten.
|
||||
http:
|
||||
routers:
|
||||
%s routers:
|
||||
filebrowser:
|
||||
rule: "Host(`+"`"+`files.%s`+"`"+`)"
|
||||
entryPoints:
|
||||
- websecure
|
||||
service: filebrowser
|
||||
tls: {}
|
||||
%s tls: {}
|
||||
services:
|
||||
filebrowser:
|
||||
loadBalancer:
|
||||
servers:
|
||||
- url: "http://filebrowser:80"
|
||||
`, domain)
|
||||
`, mwDef, domain, mw)
|
||||
}
|
||||
|
||||
// RenderControllerRoute returns a traefik file-provider dynamic config routing the controller's own
|
||||
@@ -420,12 +432,13 @@ http:
|
||||
// storage path (each a named sidebar entry). Empty paths → a single default /srv source. Ported
|
||||
// verbatim from internal/web/handlers.go.
|
||||
func RenderFileBrowserConfig(paths []settings.StoragePath, importSource bool) string {
|
||||
return RenderFileBrowserConfigKept(paths, importSource, "")
|
||||
return RenderFileBrowserConfigKept(paths, importSource, "", FileBrowserSSO{})
|
||||
}
|
||||
|
||||
// RenderFileBrowserConfigKept is RenderFileBrowserConfig plus the read-only kept-data source, LAST,
|
||||
// named keptLabel ("" = no such source: nothing is kept, or the caller predates it).
|
||||
func RenderFileBrowserConfigKept(paths []settings.StoragePath, importSource bool, keptLabel string) string {
|
||||
// named keptLabel ("" = no such source: nothing is kept, or the caller predates it), and the household's header
|
||||
// sign-in (R-1100; a zero sso = none, the config byte for byte as before).
|
||||
func RenderFileBrowserConfigKept(paths []settings.StoragePath, importSource bool, keptLabel string, sso FileBrowserSSO) string {
|
||||
var sources string
|
||||
// The canonical drop-zone (R-75) is FIRST and is NOT a registered storage path — it is a separate
|
||||
// bind of <system namespace>/userdata/import. Separate rather than nested inside a drive source:
|
||||
@@ -471,7 +484,7 @@ server:
|
||||
logging:
|
||||
- levels: "info|warning|error"
|
||||
sources:
|
||||
%suserDefaults:
|
||||
%s%suserDefaults:
|
||||
stickySidebar: true
|
||||
darkMode: true
|
||||
viewMode: "normal"
|
||||
@@ -490,7 +503,23 @@ server:
|
||||
autoplayMedia: true
|
||||
folder: true
|
||||
permissions:
|
||||
api: false
|
||||
%sfrontend:
|
||||
# No „Install app" (PWA) prompt in the sidebar: the file manager is opened from the dashboard (v0.321.0;
|
||||
# structs.go:294, sent to the page at backend/http/static.go:300).
|
||||
disablePWAInstall: true
|
||||
`, sources, renderFileBrowserAuth(sso), fileBrowserDefaultPermissions(sso))
|
||||
}
|
||||
|
||||
// fileBrowserDefaultPermissions is userDefaults.permissions — what FileBrowser gives a user it creates. With the header
|
||||
// sign-in, the one user it creates on its own is the household's header user (FileBrowserSSOUser, on its first sign-in),
|
||||
// and that user must be able to do with the files what the household does as `admin`: change, add, delete, share,
|
||||
// download — but not run FileBrowser itself (admin) or its API keys (api). FileBrowser has no per-user setting for a
|
||||
// header user; the defaults are the only place the box can set its rights (R-1100). A user the household adds by hand
|
||||
// in FileBrowser starts from the same ticks and the household can change them there. Without the header sign-in: the
|
||||
// old download-only defaults, unchanged. Pinned by TestFileBrowserConfig_R1100_HeaderUserGetsTheHouseholdsRights.
|
||||
func fileBrowserDefaultPermissions(sso FileBrowserSSO) string {
|
||||
if sso.Header == "" {
|
||||
return ` api: false
|
||||
admin: false
|
||||
modify: false
|
||||
share: false
|
||||
@@ -498,9 +527,15 @@ server:
|
||||
delete: false
|
||||
create: false
|
||||
download: true
|
||||
frontend:
|
||||
# No „Install app" (PWA) prompt in the sidebar: the file manager is opened from the dashboard (v0.321.0;
|
||||
# structs.go:294, sent to the page at backend/http/static.go:300).
|
||||
disablePWAInstall: true
|
||||
`, sources)
|
||||
`
|
||||
}
|
||||
return ` api: false
|
||||
admin: false
|
||||
modify: true
|
||||
share: true
|
||||
realtime: true
|
||||
delete: true
|
||||
create: true
|
||||
download: true
|
||||
`
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user