urlpaths: seemingly full functionality

various subpath combos seem to work, and trailing slashes from them are
trimmed (including for the empty admin path "/", which is now "" by
default).
This commit is contained in:
Harvey Tindall
2025-05-14 20:08:21 +01:00
parent 302c4c189c
commit 0967d471ee
5 changed files with 41 additions and 22 deletions

View File

@@ -39,12 +39,19 @@ func (app *appContext) MustSetValue(section, key, val string) {
} }
func (app *appContext) MustSetURLPath(section, key, val string) { func (app *appContext) MustSetURLPath(section, key, val string) {
if !strings.HasPrefix(val, "/") { if !strings.HasPrefix(val, "/") && val != "" {
val = "/" + val val = "/" + val
} }
app.MustSetValue(section, key, val) app.MustSetValue(section, key, val)
} }
func FormatSubpath(path string) string {
if path == "/" {
return ""
}
return strings.TrimSuffix(path, "/")
}
func (app *appContext) loadConfig() error { func (app *appContext) loadConfig() error {
var err error var err error
app.config, err = ini.ShadowLoad(app.configPath) app.config, err = ini.ShadowLoad(app.configPath)
@@ -52,15 +59,23 @@ func (app *appContext) loadConfig() error {
return err return err
} }
app.MustSetURLPath("url_paths", "admin", "/") // URLs
app.MustSetURLPath("ui", "url_base", "")
app.MustSetURLPath("url_paths", "admin", "")
app.MustSetURLPath("url_paths", "user_page", "/my/account") app.MustSetURLPath("url_paths", "user_page", "/my/account")
app.MustSetURLPath("url_paths", "form", "/invite") app.MustSetURLPath("url_paths", "form", "/invite")
PAGES.Admin = app.config.Section("url_paths").Key("admin").MustString("/") PAGES.Base = FormatSubpath(app.config.Section("ui").Key("url_base").String())
PAGES.MyAccount = app.config.Section("url_paths").Key("user_page").MustString("/my/account") PAGES.Admin = FormatSubpath(app.config.Section("url_paths").Key("admin").String())
PAGES.Form = app.config.Section("url_paths").Key("form").MustString("/invite") PAGES.MyAccount = FormatSubpath(app.config.Section("url_paths").Key("user_page").String())
PAGES.Form = FormatSubpath(app.config.Section("url_paths").Key("form").String())
if !(app.config.Section("user_page").Key("enabled").MustBool(true)) {
PAGES.MyAccount = "disabled"
}
if PAGES.Base == PAGES.Form || PAGES.Base == "/accounts" || PAGES.Base == "/settings" || PAGES.Base == "/activity" {
app.err.Printf(lm.BadURLBase, PAGES.Base)
}
app.info.Printf(lm.SubpathBlockMessage, PAGES.Base, PAGES.Admin, PAGES.MyAccount, PAGES.Form)
app.MustSetValue("jellyfin", "public_server", app.config.Section("jellyfin").Key("server").String()) app.MustSetValue("jellyfin", "public_server", app.config.Section("jellyfin").Key("server").String())
app.MustSetValue("ui", "redirect_url", app.config.Section("jellyfin").Key("public_server").String()) app.MustSetValue("ui", "redirect_url", app.config.Section("jellyfin").Key("public_server").String())
for _, key := range app.config.Section("files").Keys() { for _, key := range app.config.Section("files").Keys() {
@@ -75,10 +90,6 @@ func (app *appContext) loadConfig() error {
app.config.Section("files").Key(key).SetValue(app.config.Section("files").Key(key).MustString(filepath.Join(app.dataPath, (key + ".db")))) app.config.Section("files").Key(key).SetValue(app.config.Section("files").Key(key).MustString(filepath.Join(app.dataPath, (key + ".db"))))
} }
PAGES.Base = strings.TrimSuffix(app.config.Section("ui").Key("url_base").MustString(""), "/")
if PAGES.Base == "/invite" || PAGES.Base == "/accounts" || PAGES.Base == "/settings" || PAGES.Base == "/activity" {
app.err.Printf(lm.BadURLBase, PAGES.Base)
}
app.ExternalURI = strings.TrimSuffix(strings.TrimSuffix(app.config.Section("ui").Key("jfa_url").MustString(""), "/invite"), "/") app.ExternalURI = strings.TrimSuffix(strings.TrimSuffix(app.config.Section("ui").Key("jfa_url").MustString(""), "/invite"), "/")
if !strings.HasSuffix(app.ExternalURI, PAGES.Base) { if !strings.HasSuffix(app.ExternalURI, PAGES.Base) {
app.err.Println(lm.NoURLSuffix) app.err.Println(lm.NoURLSuffix)

View File

@@ -194,12 +194,10 @@ sections:
value: Your account has been created. Click below to continue to Jellyfin. value: Your account has been created. Click below to continue to Jellyfin.
description: Displayed when a user creates an account. Use the "post-signup card" description: Displayed when a user creates an account. Use the "post-signup card"
in the Message editor for more control. in the Message editor for more control.
- setting: url_base - setting: subfolder_note
name: Reverse Proxy subfolder name: "Reverse proxy-ing to a subfolder?"
requires_restart: true type: note
type: text description: "Put the folder (e.g. /accounts) in \"Reverse Proxy subfolder\", and the full URL including it (e.g. https://jellyf.in/accounts) in \"External jfa-go URL\"."
description: URL base for when running jfa-go with a reverse proxy in a subfolder.
include preceding /, e.g "/accounts".
- setting: jfa_url - setting: jfa_url
name: External jfa-go URL name: External jfa-go URL
required: true required: true
@@ -209,6 +207,12 @@ sections:
description: The URL at which the jfa-go root (admin page) is accessible, including description: The URL at which the jfa-go root (admin page) is accessible, including
the subfolder if you use one. This is necessary because using a reverse proxy the subfolder if you use one. This is necessary because using a reverse proxy
means the program has no way of knowing the URL itself. means the program has no way of knowing the URL itself.
- setting: url_base
name: Reverse Proxy subfolder
requires_restart: true
type: text
description: URL base for when running jfa-go with a reverse proxy in a subfolder.
include preceding /, e.g "/accounts".
- setting: redirect_url - setting: redirect_url
name: Form success redirect URL name: Form success redirect URL
type: text type: text
@@ -232,10 +236,14 @@ sections:
- ["opaque", "Opaque"] - ["opaque", "Opaque"]
value: clear value: clear
description: Appearance of the Admin login screen. description: Appearance of the Admin login screen.
- setting: urlpaths_note
name: "URL Paths:"
type: note
description: "Want \"My Account\" at \"/\" or the admin page at \"/admin\"? Enable advanced settings and check the \"URL Paths\" section."
- section: url_paths - section: url_paths
meta: meta:
name: URL Paths name: URL Paths
description: Settings for changing where different pages are accessed. description: Settings for changing where different pages are accessed. If you change & forget these, they're printed in the logs on startup. Paths should have a slash at the beginning but not at the end.
advanced: true advanced: true
settings: settings:
- setting: admin - setting: admin
@@ -243,7 +251,7 @@ sections:
type: text type: text
required: true required: true
requires_restart: true requires_restart: true
value: "/" value: ""
description: URL subpath the admin page should be at. description: URL subpath the admin page should be at.
- setting: user_page - setting: user_page
name: "\"My Account\" subpath" name: "\"My Account\" subpath"

View File

@@ -212,9 +212,10 @@ const (
InitProxy = "Initialized proxy @ \"%s\"" InitProxy = "Initialized proxy @ \"%s\""
FailedInitProxy = "Failed to initialize proxy @ \"%s\": %v\nStartup will pause for a bit to grab your attention." FailedInitProxy = "Failed to initialize proxy @ \"%s\": %v\nStartup will pause for a bit to grab your attention."
NoURLSuffix = `Warning: Given "jfa_url"/"External jfa-go URL" value does not include "url_base" value!` NoURLSuffix = `Warning: Given "jfa_url"/"External jfa-go URL" value does not include "url_base" value!`
BadURLBase = `Warning: Given URL Base "%s" may conflict with the applications subpaths.` BadURLBase = `Warning: Given reverse proxy subfolder "%s" may conflict with the applications subpaths.`
NoExternalHost = `No "External jfa-go URL" provided, set one in Settings > General.` NoExternalHost = `No "External jfa-go URL" provided, set one in Settings > General.`
LoginWontSave = ` Your login won't save until you do.` LoginWontSave = ` Your login won't save until you do.`
SubpathBlockMessage = `URLs: Root subfolder = "%s", Admin = "%s", My Account = "%s", Invite forms = "%s"`
// discord.go // discord.go
StartDaemon = "Started %s daemon" StartDaemon = "Started %s daemon"

View File

@@ -178,7 +178,6 @@ for (const tab of tabs) {
} }
} }
// Default tab // Default tab
// if ((window.URLBase + "/").includes(window.location.pathname)) {
if (!matchedTab) { if (!matchedTab) {
window.tabs.switch("", true); window.tabs.switch("", true);
} }

View File

@@ -660,7 +660,7 @@ document.addEventListener("details-reload", () => {
expiryCard.expiry = details.expiry; expiryCard.expiry = details.expiry;
const adminBackButton = document.getElementById("admin-back-button") as HTMLAnchorElement; const adminBackButton = document.getElementById("admin-back-button") as HTMLAnchorElement;
adminBackButton.href = window.location.href.replace(window.pages.MyAccount, window.pages.Admin); adminBackButton.href = window.pages.Base + window.pages.Admin;
let messageCard = document.getElementById("card-message"); let messageCard = document.getElementById("card-message");
if (details.accounts_admin) { if (details.accounts_admin) {