Move config struct to webcontroller

This commit is contained in:
2022-11-07 18:10:06 +01:00
parent db0ae5a322
commit e87bcace2d
6 changed files with 68 additions and 91 deletions

View File

@@ -11,18 +11,6 @@ import (
"github.com/julienschmidt/httprouter" "github.com/julienschmidt/httprouter"
) )
// PixelWebConfig contains the Pixeldrain Web UI configuration
type PixelWebConfig struct {
APIURLExternal string `toml:"api_url_external"`
APIURLInternal string `toml:"api_url_internal"`
WebsiteAddress string `toml:"website_address"`
SessionCookieDomain string `toml:"session_cookie_domain"`
ResourceDir string `toml:"resource_dir"`
DebugMode bool `toml:"debug_mode"`
ProxyAPIRequests bool `toml:"proxy_api_requests"`
MaintenanceMode bool `toml:"maintenance_mode"`
}
// DefaultConfig is the default configuration for Pixeldrain Web // DefaultConfig is the default configuration for Pixeldrain Web
const DefaultConfig = `## Pixeldrain Web UI server configuration const DefaultConfig = `## Pixeldrain Web UI server configuration
@@ -33,6 +21,11 @@ api_url_external = "/api"
# Address used to make internal API requests to the backend # Address used to make internal API requests to the backend
api_url_internal = "https://pixeldrain.com/api" api_url_internal = "https://pixeldrain.com/api"
# When connecting to the API over a Unix domain socket you should enter the
# socket path here. api_url_internal needs to be correct too, as the API path
# prefix will be derived from there
api_socket_path = ""
website_address = "https://pixeldrain.com" website_address = "https://pixeldrain.com"
session_cookie_domain = "" session_cookie_domain = ""
resource_dir = "res" resource_dir = "res"
@@ -56,12 +49,12 @@ func Init(r *httprouter.Router, prefix string, setLogLevel bool) {
// Seed the RNG // Seed the RNG
rand.Seed(time.Now().UnixNano()) rand.Seed(time.Now().UnixNano())
var webconf = &PixelWebConfig{} var conf webcontroller.Config
var _, err = config.New( var _, err = config.New(
DefaultConfig, DefaultConfig,
"", "",
"pdwebconf.toml", "pdwebconf.toml",
webconf, &conf,
true, true,
) )
if err != nil { if err != nil {
@@ -69,20 +62,9 @@ func Init(r *httprouter.Router, prefix string, setLogLevel bool) {
os.Exit(1) os.Exit(1)
} }
if !webconf.DebugMode && setLogLevel { if !conf.DebugMode && setLogLevel {
log.SetLogLevel(log.LevelInfo) log.SetLogLevel(log.LevelInfo)
} }
webcontroller.New( webcontroller.New(r, prefix, conf)
r,
prefix,
webconf.ResourceDir,
webconf.APIURLInternal,
webconf.APIURLExternal,
webconf.WebsiteAddress,
webconf.SessionCookieDomain,
webconf.MaintenanceMode,
webconf.DebugMode,
webconf.ProxyAPIRequests,
)
} }

View File

@@ -14,7 +14,7 @@ import (
func (wc *WebController) viewTokenOrBust() (t string) { func (wc *WebController) viewTokenOrBust() (t string) {
var err error var err error
if t, err = wc.api.GetMiscViewToken(); err != nil && !wc.proxyAPIRequests { if t, err = wc.api.GetMiscViewToken(); err != nil && !wc.config.ProxyAPIRequests {
log.Error("Could not get viewtoken: %s", err) log.Error("Could not get viewtoken: %s", err)
} }
return t return t

View File

@@ -25,7 +25,7 @@ func (wc *WebController) metadataFromFile(f pixelapi.FileInfo) (og ogData) {
og.addProp("og:title", f.Name) og.addProp("og:title", f.Name)
og.addProp("og:site_name", "pixeldrain") og.addProp("og:site_name", "pixeldrain")
og.addProp("og:description", "This file has been shared with you on pixeldrain") og.addProp("og:description", "This file has been shared with you on pixeldrain")
og.addProp("og:url", wc.websiteAddress+"/u/"+f.ID) og.addProp("og:url", wc.config.WebsiteAddress+"/u/"+f.ID)
og.addProp("description", "This file has been shared with you on pixeldrain") og.addProp("description", "This file has been shared with you on pixeldrain")
og.addName("description", "This file has been shared with you on pixeldrain") og.addName("description", "This file has been shared with you on pixeldrain")
og.addName("keywords", "pixeldrain,shared,sharing,upload,file,free") og.addName("keywords", "pixeldrain,shared,sharing,upload,file,free")
@@ -35,39 +35,39 @@ func (wc *WebController) metadataFromFile(f pixelapi.FileInfo) (og ogData) {
if strings.HasPrefix(f.MimeType, "image") { if strings.HasPrefix(f.MimeType, "image") {
og.addProp("og:type", "article") og.addProp("og:type", "article")
og.addProp("og:image", wc.websiteAddress+"/api/file/"+f.ID) og.addProp("og:image", wc.config.WebsiteAddress+"/api/file/"+f.ID)
og.addProp("og:image:url", wc.websiteAddress+"/api/file/"+f.ID) og.addProp("og:image:url", wc.config.WebsiteAddress+"/api/file/"+f.ID)
og.addProp("og:image:secure_url", wc.websiteAddress+"/api/file/"+f.ID) og.addProp("og:image:secure_url", wc.config.WebsiteAddress+"/api/file/"+f.ID)
og.addProp("og:image:type", f.MimeType) og.addProp("og:image:type", f.MimeType)
og.addName("twitter:card", "summary_large_image") og.addName("twitter:card", "summary_large_image")
og.addName("twitter:image", wc.websiteAddress+"/api/file/"+f.ID) og.addName("twitter:image", wc.config.WebsiteAddress+"/api/file/"+f.ID)
og.addLink("image_src", wc.websiteAddress+"/api/file/"+f.ID) og.addLink("image_src", wc.config.WebsiteAddress+"/api/file/"+f.ID)
} else if strings.HasPrefix(f.MimeType, "video") { } else if strings.HasPrefix(f.MimeType, "video") {
og.addProp("og:type", "video.other") og.addProp("og:type", "video.other")
og.addProp("og:image", wc.websiteAddress+"/api/file/"+f.ID+"/thumbnail") og.addProp("og:image", wc.config.WebsiteAddress+"/api/file/"+f.ID+"/thumbnail")
og.addProp("og:video", wc.websiteAddress+"/api/file/"+f.ID) og.addProp("og:video", wc.config.WebsiteAddress+"/api/file/"+f.ID)
og.addProp("og:video:url", wc.websiteAddress+"/api/file/"+f.ID) og.addProp("og:video:url", wc.config.WebsiteAddress+"/api/file/"+f.ID)
og.addProp("og:video:secure_url", wc.websiteAddress+"/api/file/"+f.ID) og.addProp("og:video:secure_url", wc.config.WebsiteAddress+"/api/file/"+f.ID)
og.addProp("og:video:type", f.MimeType) og.addProp("og:video:type", f.MimeType)
og.addName("twitter:card", "player") og.addName("twitter:card", "player")
og.addName("twitter:image", wc.websiteAddress+"/api/file/"+f.ID+"/thumbnail") og.addName("twitter:image", wc.config.WebsiteAddress+"/api/file/"+f.ID+"/thumbnail")
og.addName("twitter:player", wc.websiteAddress+"/api/file/"+f.ID) og.addName("twitter:player", wc.config.WebsiteAddress+"/api/file/"+f.ID)
og.addName("twitter:player:stream", wc.websiteAddress+"/api/file/"+f.ID) og.addName("twitter:player:stream", wc.config.WebsiteAddress+"/api/file/"+f.ID)
og.addName("twitter:player:stream:content_type", f.MimeType) og.addName("twitter:player:stream:content_type", f.MimeType)
og.addLink("image_src", wc.websiteAddress+"/api/file/"+f.ID+"/thumbnail") og.addLink("image_src", wc.config.WebsiteAddress+"/api/file/"+f.ID+"/thumbnail")
} else if strings.HasPrefix(f.MimeType, "audio") { } else if strings.HasPrefix(f.MimeType, "audio") {
og.addProp("og:type", "music.song") og.addProp("og:type", "music.song")
og.addProp("og:image", wc.websiteAddress+"/api/file/"+f.ID+"/thumbnail") og.addProp("og:image", wc.config.WebsiteAddress+"/api/file/"+f.ID+"/thumbnail")
og.addProp("og:audio", wc.websiteAddress+"/api/file/"+f.ID) og.addProp("og:audio", wc.config.WebsiteAddress+"/api/file/"+f.ID)
og.addProp("og:audio:secure_url", wc.websiteAddress+"/api/file/"+f.ID) og.addProp("og:audio:secure_url", wc.config.WebsiteAddress+"/api/file/"+f.ID)
og.addProp("og:audio:type", f.MimeType) og.addProp("og:audio:type", f.MimeType)
og.addLink("image_src", wc.websiteAddress+"/api/file/"+f.ID+"/thumbnail") og.addLink("image_src", wc.config.WebsiteAddress+"/api/file/"+f.ID+"/thumbnail")
} else { } else {
og.addProp("og:type", "website") og.addProp("og:type", "website")
og.addProp("og:image", wc.websiteAddress+"/api/file/"+f.ID+"/thumbnail") og.addProp("og:image", wc.config.WebsiteAddress+"/api/file/"+f.ID+"/thumbnail")
og.addLink("image_src", wc.websiteAddress+"/api/file/"+f.ID+"/thumbnail") og.addLink("image_src", wc.config.WebsiteAddress+"/api/file/"+f.ID+"/thumbnail")
} }
return og return og
} }
@@ -78,15 +78,15 @@ func (wc *WebController) metadataFromList(l pixelapi.ListInfo) (og ogData) {
og.addProp("og:description", "A collection of files on pixeldrain") og.addProp("og:description", "A collection of files on pixeldrain")
og.addProp("description", "A collection of files on pixeldrain") og.addProp("description", "A collection of files on pixeldrain")
og.addName("description", "A collection of files on pixeldrain") og.addName("description", "A collection of files on pixeldrain")
og.addProp("og:url", wc.websiteAddress+"/l/"+l.ID) og.addProp("og:url", wc.config.WebsiteAddress+"/l/"+l.ID)
og.addName("twitter:title", l.Title) og.addName("twitter:title", l.Title)
og.addName("twitter:site", "@Fornax96") og.addName("twitter:site", "@Fornax96")
og.addName("twitter:domain", "pixeldrain.com") og.addName("twitter:domain", "pixeldrain.com")
if l.FileCount > 0 { if l.FileCount > 0 {
og.addProp("og:image", wc.websiteAddress+"/api/file/"+l.Files[0].ID+"/thumbnail") og.addProp("og:image", wc.config.WebsiteAddress+"/api/file/"+l.Files[0].ID+"/thumbnail")
og.addProp("og:image:url", wc.websiteAddress+"/api/file/"+l.Files[0].ID+"/thumbnail") og.addProp("og:image:url", wc.config.WebsiteAddress+"/api/file/"+l.Files[0].ID+"/thumbnail")
og.addName("twitter:image", wc.websiteAddress+"/api/file/"+l.Files[0].ID+"/thumbnail") og.addName("twitter:image", wc.config.WebsiteAddress+"/api/file/"+l.Files[0].ID+"/thumbnail")
og.addLink("image_src", wc.websiteAddress+"/api/file/"+l.Files[0].ID+"/thumbnail") og.addLink("image_src", wc.config.WebsiteAddress+"/api/file/"+l.Files[0].ID+"/thumbnail")
} }
return og return og
} }

View File

@@ -44,7 +44,7 @@ func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request)
tpm: wc.templates, tpm: wc.templates,
Authenticated: false, Authenticated: false,
UserAgent: r.UserAgent(), UserAgent: r.UserAgent(),
APIEndpoint: template.URL(wc.apiURLExternal), APIEndpoint: template.URL(wc.config.APIURLExternal),
// Use the user's IP address for making requests // Use the user's IP address for making requests
PixelAPI: wc.api.RealIP(util.RemoteAddress(r)).RealAgent(r.UserAgent()), PixelAPI: wc.api.RealIP(util.RemoteAddress(r)).RealAgent(r.UserAgent()),
@@ -74,7 +74,7 @@ func (wc *WebController) newTemplateData(w http.ResponseWriter, r *http.Request)
Value: "", Value: "",
Path: "/", Path: "/",
Expires: time.Unix(0, 0), Expires: time.Unix(0, 0),
Domain: wc.sessionCookieDomain, Domain: wc.config.SessionCookieDomain,
}) })
http.SetCookie(w, &http.Cookie{ http.SetCookie(w, &http.Cookie{
Name: "pd_auth_key", Name: "pd_auth_key",

View File

@@ -205,7 +205,7 @@ func (wc *WebController) loginForm(td *TemplateData, r *http.Request) (f Form) {
Value: session.AuthKey.String(), Value: session.AuthKey.String(),
Path: "/", Path: "/",
Expires: time.Now().AddDate(50, 0, 0), Expires: time.Now().AddDate(50, 0, 0),
Domain: wc.sessionCookieDomain, Domain: wc.config.SessionCookieDomain,
// Strict means the Cookie will only be sent when the user // Strict means the Cookie will only be sent when the user
// reaches a page by a link from the same domain. Lax means any // reaches a page by a link from the same domain. Lax means any

View File

@@ -18,21 +18,27 @@ import (
blackfriday "github.com/russross/blackfriday/v2" blackfriday "github.com/russross/blackfriday/v2"
) )
type Config struct {
APIURLExternal string `toml:"api_url_external"`
APIURLInternal string `toml:"api_url_internal"`
APISocketPath string `toml:"api_socket_path"`
WebsiteAddress string `toml:"website_address"`
SessionCookieDomain string `toml:"session_cookie_domain"`
ResourceDir string `toml:"resource_dir"`
DebugMode bool `toml:"debug_mode"`
ProxyAPIRequests bool `toml:"proxy_api_requests"`
MaintenanceMode bool `toml:"maintenance_mode"`
}
// WebController controls how requests are handled and makes sure they have // WebController controls how requests are handled and makes sure they have
// proper context when running // proper context when running
type WebController struct { type WebController struct {
templates *TemplateManager templates *TemplateManager
config Config
resourceDir string // Server hostname, displayed in the footer of every web page
hostname string hostname string
apiURLInternal string
apiURLExternal string
websiteAddress string
sessionCookieDomain string
proxyAPIRequests bool
// page-specific variables // page-specific variables
captchaSiteKey string captchaSiteKey string
@@ -46,30 +52,19 @@ type WebController struct {
// New initializes a new WebController by registering all the request handlers // New initializes a new WebController by registering all the request handlers
// and parsing all templates in the resource directory // and parsing all templates in the resource directory
func New( func New(r *httprouter.Router, prefix string, conf Config) (wc *WebController) {
r *httprouter.Router,
prefix string,
resourceDir string,
apiURLInternal string,
apiURLExternal string,
websiteAddress string,
sessionCookieDomain string,
maintenanceMode bool,
debugMode bool,
proxyAPIRequests bool,
) (wc *WebController) {
var err error var err error
wc = &WebController{ wc = &WebController{
resourceDir: resourceDir, config: conf,
apiURLInternal: apiURLInternal, httpClient: &http.Client{Timeout: time.Minute * 10},
apiURLExternal: apiURLExternal, api: pixelapi.New(conf.APIURLInternal),
websiteAddress: websiteAddress,
sessionCookieDomain: sessionCookieDomain,
proxyAPIRequests: proxyAPIRequests,
httpClient: &http.Client{Timeout: time.Minute * 10},
api: pixelapi.New(apiURLInternal),
} }
wc.templates = NewTemplateManager(resourceDir, apiURLExternal, debugMode)
if conf.APISocketPath != "" {
wc.api = wc.api.UnixSocketPath(conf.APISocketPath)
}
wc.templates = NewTemplateManager(conf.ResourceDir, conf.APIURLExternal, conf.DebugMode)
wc.templates.ParseTemplates(false) wc.templates.ParseTemplates(false)
if wc.hostname, err = os.Hostname(); err != nil { if wc.hostname, err = os.Hostname(); err != nil {
@@ -77,7 +72,7 @@ func New(
} }
// Serve static files // Serve static files
var fs = http.FileServer(http.Dir(resourceDir + "/static")) var fs = http.FileServer(http.Dir(conf.ResourceDir + "/static"))
var resourceHandler = func(w http.ResponseWriter, r *http.Request, p httprouter.Params) { var resourceHandler = func(w http.ResponseWriter, r *http.Request, p httprouter.Params) {
// Cache resources for a year // Cache resources for a year
w.Header().Set("Cache-Control", "public, max-age=31536000") w.Header().Set("Cache-Control", "public, max-age=31536000")
@@ -93,7 +88,7 @@ func New(
r.GET(prefix+"/robots.txt" /* */, wc.serveFile("/robots.txt")) r.GET(prefix+"/robots.txt" /* */, wc.serveFile("/robots.txt"))
r.GET(prefix+"/ads.txt" /* */, wc.serveFile("/ads.txt")) r.GET(prefix+"/ads.txt" /* */, wc.serveFile("/ads.txt"))
if maintenanceMode { if conf.MaintenanceMode {
r.NotFound = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { r.NotFound = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.WriteHeader(http.StatusServiceUnavailable) w.WriteHeader(http.StatusServiceUnavailable)
wc.templates.Get().ExecuteTemplate(w, "maintenance", wc.newTemplateData(w, r)) wc.templates.Get().ExecuteTemplate(w, "maintenance", wc.newTemplateData(w, r))
@@ -101,10 +96,10 @@ func New(
return wc return wc
} }
if proxyAPIRequests { if conf.ProxyAPIRequests {
remoteURL, err := url.Parse(strings.TrimSuffix(apiURLInternal, "/api")) remoteURL, err := url.Parse(strings.TrimSuffix(conf.APIURLInternal, "/api"))
if err != nil { if err != nil {
panic(fmt.Errorf("failed to parse reverse proxy URL '%s': %w", apiURLInternal, err)) panic(fmt.Errorf("failed to parse reverse proxy URL '%s': %w", conf.APIURLInternal, err))
} }
log.Info("Starting API proxy to %s", remoteURL) log.Info("Starting API proxy to %s", remoteURL)
@@ -315,7 +310,7 @@ func (wc *WebController) serveFile(path string) httprouter.Handle {
r *http.Request, r *http.Request,
p httprouter.Params, p httprouter.Params,
) { ) {
http.ServeFile(w, r, wc.resourceDir+"/static"+path) http.ServeFile(w, r, wc.config.ResourceDir+"/static"+path)
} }
} }