2.5 KB
site.go
package controllers
import (
"net/http"
"os"
"github.com/readysite/readysite/pkg/application"
"github.com/readysite/readysite/website/internal/access"
"github.com/readysite/readysite/website/internal/content"
"github.com/readysite/readysite/website/internal/helpers"
"github.com/readysite/readysite/website/models"
)
// Site returns the site controller.
// NOTE: This controller must be registered LAST as it uses a catch-all route.
func Site() (string, *SiteController) {
return "site", &SiteController{}
}
// SiteController handles public site rendering.
type SiteController struct {
application.BaseController
}
// Setup registers routes.
func (c *SiteController) Setup(app *application.App) {
c.BaseController.Setup(app)
// Catch-all route for public pages - must be registered LAST
http.Handle("GET /{path...}", app.Method(c, "Render", nil))
}
// Handle implements Controller interface with value receiver for request isolation.
func (c SiteController) Handle(r *http.Request) application.Controller {
c.Request = r
return &c
}
// Render renders a public page.
func (c *SiteController) Render(w http.ResponseWriter, r *http.Request) {
path := r.PathValue("path")
// Check for setup redirect
if helpers.GetSetting(models.SettingSetupComplete) != "true" {
if hostingURL := os.Getenv("HOSTING_URL"); hostingURL != "" {
http.Redirect(w, r, hostingURL, http.StatusSeeOther)
return
}
http.Redirect(w, r, "/setup", http.StatusSeeOther)
return
}
// Default to "home" for root path
pageID := path
if pageID == "" {
pageID = "home"
}
// Try to find the page
page, err := models.Pages.Get(pageID)
if err != nil {
page = content.FindByPath(path)
}
// Check access: published pages are public, otherwise check ACL
user := access.GetUserFromJWT(r)
if page == nil || (!page.IsPublished() && !access.CheckAccess(user, access.ResourcePage, page.ID, access.PermRead)) {
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.WriteHeader(http.StatusNotFound)
w.Write([]byte(content.NotFound404HTML()))
return
}
w.Header().Set("Content-Type", "text/html; charset=utf-8")
w.Write([]byte(content.RenderPage(page, r)))
}
// PublishedPages returns published root pages for navigation.
func (c *SiteController) PublishedPages() []*models.Page {
allPages, _ := models.Pages.Search("WHERE ParentID = '' ORDER BY Position, CreatedAt")
var published []*models.Page
for _, p := range allPages {
if p.IsPublished() {
published = append(published, p)
}
}
return published
}