Add admin-controlled signup toggle and hide signup links.
parent
8ff0b7f2c2
commit
a5a2e7063a
|
|
@ -29,6 +29,7 @@ func AboutHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - About",
|
Title: "ThreadR - About",
|
||||||
Navbar: "about",
|
Navbar: "about",
|
||||||
LoggedIn: loggedIn,
|
LoggedIn: loggedIn,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,89 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"net/http"
|
||||||
|
"threadr/models"
|
||||||
|
|
||||||
|
"github.com/gorilla/sessions"
|
||||||
|
)
|
||||||
|
|
||||||
|
func AdminHandler(app *App) http.HandlerFunc {
|
||||||
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
|
session := r.Context().Value("session").(*sessions.Session)
|
||||||
|
userID, ok := session.Values["user_id"].(int)
|
||||||
|
if !ok {
|
||||||
|
http.Redirect(w, r, app.Config.ThreadrDir+"/login/", http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
user, err := models.GetUserByID(app.DB, userID)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error fetching user in AdminHandler: %v", err)
|
||||||
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if user == nil || !models.HasGlobalPermission(user, models.PermManageUsers) {
|
||||||
|
http.Error(w, "Forbidden", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
cookie, _ := r.Cookie("threadr_cookie_banner")
|
||||||
|
|
||||||
|
if r.Method == http.MethodPost {
|
||||||
|
if !app.validateCSRFToken(r, session) {
|
||||||
|
http.Error(w, "Invalid CSRF token", http.StatusForbidden)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
allowSignup := r.FormValue("allow_signup") == "on"
|
||||||
|
if err := models.SetAllowSignup(app.DB, allowSignup); err != nil {
|
||||||
|
log.Printf("Error updating site settings in AdminHandler: %v", err)
|
||||||
|
http.Error(w, "Failed to save settings", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
http.Redirect(w, r, app.Config.ThreadrDir+"/admin/?saved=true", http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
if r.Method != http.MethodGet {
|
||||||
|
http.Error(w, "Method Not Allowed", http.StatusMethodNotAllowed)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
settings, err := models.GetSiteSettings(app.DB)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error fetching site settings in AdminHandler: %v", err)
|
||||||
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
data := struct {
|
||||||
|
PageData
|
||||||
|
AllowSignup bool
|
||||||
|
ShowSuccess bool
|
||||||
|
}{
|
||||||
|
PageData: PageData{
|
||||||
|
Title: "ThreadR - Admin",
|
||||||
|
Navbar: "admin",
|
||||||
|
LoggedIn: true,
|
||||||
|
IsAdmin: true,
|
||||||
|
AllowSignup: settings.AllowSignup,
|
||||||
|
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
||||||
|
BasePath: app.Config.ThreadrDir,
|
||||||
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
CurrentURL: r.URL.RequestURI(),
|
||||||
|
CSRFToken: app.csrfToken(session),
|
||||||
|
},
|
||||||
|
AllowSignup: settings.AllowSignup,
|
||||||
|
ShowSuccess: r.URL.Query().Get("saved") == "true",
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := app.Tmpl.ExecuteTemplate(w, "admin", data); err != nil {
|
||||||
|
log.Printf("Error executing template in AdminHandler: %v", err)
|
||||||
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -14,6 +14,8 @@ type PageData struct {
|
||||||
Title string
|
Title string
|
||||||
Navbar string
|
Navbar string
|
||||||
LoggedIn bool
|
LoggedIn bool
|
||||||
|
IsAdmin bool
|
||||||
|
AllowSignup bool
|
||||||
ShowCookieBanner bool
|
ShowCookieBanner bool
|
||||||
BasePath string
|
BasePath string
|
||||||
StaticPath string
|
StaticPath string
|
||||||
|
|
|
||||||
|
|
@ -119,6 +119,7 @@ func BoardHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - " + board.Name,
|
Title: "ThreadR - " + board.Name,
|
||||||
Navbar: "boards",
|
Navbar: "boards",
|
||||||
LoggedIn: loggedIn,
|
LoggedIn: loggedIn,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
|
||||||
|
|
@ -107,6 +107,7 @@ func BoardsHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - Boards",
|
Title: "ThreadR - Boards",
|
||||||
Navbar: "boards",
|
Navbar: "boards",
|
||||||
LoggedIn: loggedIn,
|
LoggedIn: loggedIn,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
|
||||||
|
|
@ -239,6 +239,7 @@ func ChatHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR Chat - " + board.Name,
|
Title: "ThreadR Chat - " + board.Name,
|
||||||
Navbar: "boards",
|
Navbar: "boards",
|
||||||
LoggedIn: true,
|
LoggedIn: true,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
|
||||||
|
|
@ -19,6 +19,7 @@ func HomeHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - Home",
|
Title: "ThreadR - Home",
|
||||||
Navbar: "home",
|
Navbar: "home",
|
||||||
LoggedIn: loggedIn,
|
LoggedIn: loggedIn,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: filepath.Join(app.Config.ThreadrDir, "static"),
|
StaticPath: filepath.Join(app.Config.ThreadrDir, "static"),
|
||||||
|
|
|
||||||
|
|
@ -55,6 +55,7 @@ func LoginHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - Login",
|
Title: "ThreadR - Login",
|
||||||
Navbar: "login",
|
Navbar: "login",
|
||||||
LoggedIn: false,
|
LoggedIn: false,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
CurrentURL: r.URL.RequestURI(),
|
CurrentURL: r.URL.RequestURI(),
|
||||||
|
|
@ -64,6 +65,8 @@ func LoginHandler(app *App) http.HandlerFunc {
|
||||||
}
|
}
|
||||||
if r.URL.Query().Get("error") == "invalid" {
|
if r.URL.Query().Get("error") == "invalid" {
|
||||||
data.Error = "Invalid username or password"
|
data.Error = "Invalid username or password"
|
||||||
|
} else if r.URL.Query().Get("error") == "signup_disabled" {
|
||||||
|
data.Error = "Sign up is currently disabled by the administrator"
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := app.Tmpl.ExecuteTemplate(w, "login", data); err != nil {
|
if err := app.Tmpl.ExecuteTemplate(w, "login", data); err != nil {
|
||||||
|
|
|
||||||
|
|
@ -86,6 +86,7 @@ func NewsHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - News",
|
Title: "ThreadR - News",
|
||||||
Navbar: "news",
|
Navbar: "news",
|
||||||
LoggedIn: loggedIn,
|
LoggedIn: loggedIn,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
|
||||||
|
|
@ -70,6 +70,7 @@ func PreferencesHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - Preferences",
|
Title: "ThreadR - Preferences",
|
||||||
Navbar: "preferences",
|
Navbar: "preferences",
|
||||||
LoggedIn: true,
|
LoggedIn: true,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
ShowCookieBanner: false,
|
ShowCookieBanner: false,
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
|
||||||
|
|
@ -38,6 +38,7 @@ func ProfileHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - Profile",
|
Title: "ThreadR - Profile",
|
||||||
Navbar: "profile",
|
Navbar: "profile",
|
||||||
LoggedIn: true,
|
LoggedIn: true,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
ShowCookieBanner: false,
|
ShowCookieBanner: false,
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
|
||||||
|
|
@ -133,6 +133,7 @@ func ProfileEditHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - Edit Profile",
|
Title: "ThreadR - Edit Profile",
|
||||||
Navbar: "profile",
|
Navbar: "profile",
|
||||||
LoggedIn: true,
|
LoggedIn: true,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
ShowCookieBanner: false,
|
ShowCookieBanner: false,
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
|
||||||
|
|
@ -11,6 +11,18 @@ func SignupHandler(app *App) http.HandlerFunc {
|
||||||
return func(w http.ResponseWriter, r *http.Request) {
|
return func(w http.ResponseWriter, r *http.Request) {
|
||||||
session := r.Context().Value("session").(*sessions.Session)
|
session := r.Context().Value("session").(*sessions.Session)
|
||||||
cookie, _ := r.Cookie("threadr_cookie_banner")
|
cookie, _ := r.Cookie("threadr_cookie_banner")
|
||||||
|
|
||||||
|
settings, err := models.GetSiteSettings(app.DB)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error fetching site settings in SignupHandler: %v", err)
|
||||||
|
http.Error(w, "Internal Server Error", http.StatusInternalServerError)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
if !settings.AllowSignup {
|
||||||
|
http.Redirect(w, r, app.Config.ThreadrDir+"/login/?error=signup_disabled", http.StatusFound)
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
if r.Method == http.MethodPost {
|
if r.Method == http.MethodPost {
|
||||||
if !app.validateCSRFToken(r, session) {
|
if !app.validateCSRFToken(r, session) {
|
||||||
http.Error(w, "Invalid CSRF token", http.StatusForbidden)
|
http.Error(w, "Invalid CSRF token", http.StatusForbidden)
|
||||||
|
|
@ -32,6 +44,7 @@ func SignupHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - Sign Up",
|
Title: "ThreadR - Sign Up",
|
||||||
Navbar: "signup",
|
Navbar: "signup",
|
||||||
LoggedIn: false,
|
LoggedIn: false,
|
||||||
|
AllowSignup: true,
|
||||||
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
@ -59,6 +72,7 @@ func SignupHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - Sign Up",
|
Title: "ThreadR - Sign Up",
|
||||||
Navbar: "signup",
|
Navbar: "signup",
|
||||||
LoggedIn: false,
|
LoggedIn: false,
|
||||||
|
AllowSignup: true,
|
||||||
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
@ -85,6 +99,7 @@ func SignupHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - Sign Up",
|
Title: "ThreadR - Sign Up",
|
||||||
Navbar: "signup",
|
Navbar: "signup",
|
||||||
LoggedIn: session.Values["user_id"] != nil,
|
LoggedIn: session.Values["user_id"] != nil,
|
||||||
|
AllowSignup: true,
|
||||||
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,16 @@
|
||||||
|
package handlers
|
||||||
|
|
||||||
|
import (
|
||||||
|
"log"
|
||||||
|
"threadr/models"
|
||||||
|
)
|
||||||
|
|
||||||
|
func (app *App) allowSignup() bool {
|
||||||
|
settings, err := models.GetSiteSettings(app.DB)
|
||||||
|
if err != nil {
|
||||||
|
log.Printf("Error fetching site settings: %v", err)
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings.AllowSignup
|
||||||
|
}
|
||||||
|
|
@ -165,6 +165,7 @@ func ThreadHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - " + thread.Title,
|
Title: "ThreadR - " + thread.Title,
|
||||||
Navbar: "boards",
|
Navbar: "boards",
|
||||||
LoggedIn: loggedIn,
|
LoggedIn: loggedIn,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
ShowCookieBanner: cookie == nil || cookie.Value != "accepted",
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,9 @@ func UserHomeHandler(app *App) http.HandlerFunc {
|
||||||
http.Error(w, "User not found", http.StatusNotFound)
|
http.Error(w, "User not found", http.StatusNotFound)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
isAdmin := models.HasGlobalPermission(user, models.PermManageUsers)
|
||||||
|
|
||||||
data := struct {
|
data := struct {
|
||||||
PageData
|
PageData
|
||||||
Username string
|
Username string
|
||||||
|
|
@ -33,6 +36,8 @@ func UserHomeHandler(app *App) http.HandlerFunc {
|
||||||
Title: "ThreadR - User Home",
|
Title: "ThreadR - User Home",
|
||||||
Navbar: "userhome",
|
Navbar: "userhome",
|
||||||
LoggedIn: true,
|
LoggedIn: true,
|
||||||
|
IsAdmin: isAdmin,
|
||||||
|
AllowSignup: app.allowSignup(),
|
||||||
ShowCookieBanner: false,
|
ShowCookieBanner: false,
|
||||||
BasePath: app.Config.ThreadrDir,
|
BasePath: app.Config.ThreadrDir,
|
||||||
StaticPath: app.Config.ThreadrDir + "/static",
|
StaticPath: app.Config.ThreadrDir + "/static",
|
||||||
|
|
|
||||||
13
main.go
13
main.go
|
|
@ -231,6 +231,12 @@ func createTablesIfNotExist(db *sql.DB) error {
|
||||||
return fmt.Errorf("error creating user_preferences table: %v", err)
|
return fmt.Errorf("error creating user_preferences table: %v", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Create site_settings table
|
||||||
|
err = models.EnsureSiteSettings(db)
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("error ensuring site_settings table: %v", err)
|
||||||
|
}
|
||||||
|
|
||||||
log.Println("Database tables created.")
|
log.Println("Database tables created.")
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
@ -351,6 +357,11 @@ func main() {
|
||||||
// Normal startup (without automatic table creation)
|
// Normal startup (without automatic table creation)
|
||||||
log.Println("Starting ThreadR server...")
|
log.Println("Starting ThreadR server...")
|
||||||
|
|
||||||
|
err = models.EnsureSiteSettings(db)
|
||||||
|
if err != nil {
|
||||||
|
log.Fatal("Error ensuring site_settings table:", err)
|
||||||
|
}
|
||||||
|
|
||||||
dir, err := os.Getwd()
|
dir, err := os.Getwd()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Fatal("Error getting working directory:", err)
|
log.Fatal("Error getting working directory:", err)
|
||||||
|
|
@ -364,6 +375,7 @@ func main() {
|
||||||
|
|
||||||
// Parse page-specific templates with unique names
|
// Parse page-specific templates with unique names
|
||||||
pageTemplates := []string{
|
pageTemplates := []string{
|
||||||
|
"admin.html",
|
||||||
"about.html",
|
"about.html",
|
||||||
"board.html",
|
"board.html",
|
||||||
"boards.html",
|
"boards.html",
|
||||||
|
|
@ -428,6 +440,7 @@ func main() {
|
||||||
handleAuthed("/profile/", handlers.ProfileHandler(app))
|
handleAuthed("/profile/", handlers.ProfileHandler(app))
|
||||||
handleAuthed("/profile/edit/", handlers.ProfileEditHandler(app))
|
handleAuthed("/profile/edit/", handlers.ProfileEditHandler(app))
|
||||||
handleAuthed("/preferences/", handlers.PreferencesHandler(app))
|
handleAuthed("/preferences/", handlers.PreferencesHandler(app))
|
||||||
|
handleAuthed("/admin/", handlers.AdminHandler(app))
|
||||||
handleAuthed("/like/", handlers.LikeHandler(app))
|
handleAuthed("/like/", handlers.LikeHandler(app))
|
||||||
handle("/news/", handlers.NewsHandler(app))
|
handle("/news/", handlers.NewsHandler(app))
|
||||||
handle("/signup/", handlers.SignupHandler(app))
|
handle("/signup/", handlers.SignupHandler(app))
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,43 @@
|
||||||
|
package models
|
||||||
|
|
||||||
|
import "database/sql"
|
||||||
|
|
||||||
|
const siteSettingsID = 1
|
||||||
|
|
||||||
|
type SiteSettings struct {
|
||||||
|
AllowSignup bool
|
||||||
|
}
|
||||||
|
|
||||||
|
func EnsureSiteSettings(db *sql.DB) error {
|
||||||
|
_, err := db.Exec(`
|
||||||
|
CREATE TABLE IF NOT EXISTS site_settings (
|
||||||
|
id INT PRIMARY KEY,
|
||||||
|
allow_signup BOOLEAN NOT NULL DEFAULT TRUE,
|
||||||
|
updated_at TIMESTAMP DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP
|
||||||
|
)`)
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
_, err = db.Exec(`
|
||||||
|
INSERT INTO site_settings (id, allow_signup)
|
||||||
|
VALUES (?, TRUE)
|
||||||
|
ON DUPLICATE KEY UPDATE id = id
|
||||||
|
`, siteSettingsID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
||||||
|
func GetSiteSettings(db *sql.DB) (*SiteSettings, error) {
|
||||||
|
settings := &SiteSettings{}
|
||||||
|
err := db.QueryRow("SELECT allow_signup FROM site_settings WHERE id = ?", siteSettingsID).Scan(&settings.AllowSignup)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return settings, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func SetAllowSignup(db *sql.DB, allowSignup bool) error {
|
||||||
|
_, err := db.Exec("UPDATE site_settings SET allow_signup = ?, updated_at = CURRENT_TIMESTAMP WHERE id = ?", allowSignup, siteSettingsID)
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
|
@ -0,0 +1,39 @@
|
||||||
|
{{define "admin"}}
|
||||||
|
<!DOCTYPE html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>{{.Title}}</title>
|
||||||
|
<link rel="stylesheet" href="{{.StaticPath}}/style.css">
|
||||||
|
<script src="{{.StaticPath}}/app.js" defer></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
{{template "navbar" .}}
|
||||||
|
<main>
|
||||||
|
<header>
|
||||||
|
<h2>Admin Panel</h2>
|
||||||
|
</header>
|
||||||
|
{{if .ShowSuccess}}
|
||||||
|
<div class="notification success" style="position: static; margin-bottom: 1em; animation: none;">
|
||||||
|
Settings saved successfully!
|
||||||
|
</div>
|
||||||
|
{{end}}
|
||||||
|
<section>
|
||||||
|
<h3>Registration</h3>
|
||||||
|
<form method="post" action="{{.BasePath}}/admin/">
|
||||||
|
<input type="hidden" name="csrf_token" value="{{.CSRFToken}}">
|
||||||
|
<label for="allow_signup" style="display: flex; align-items: center; gap: 0.5em; cursor: pointer;">
|
||||||
|
<input type="checkbox" id="allow_signup" name="allow_signup" {{if .AllowSignup}}checked{{end}}>
|
||||||
|
<span>Allow new user signups</span>
|
||||||
|
</label>
|
||||||
|
<p style="margin-left: 1.5em; margin-top: 0.25em; font-size: 0.9em; opacity: 0.8;">
|
||||||
|
When disabled, the signup page redirects to login and prevents account creation.
|
||||||
|
</p>
|
||||||
|
|
||||||
|
<input type="submit" value="Save Settings" style="margin-top: 1.5em;">
|
||||||
|
</form>
|
||||||
|
</section>
|
||||||
|
</main>
|
||||||
|
{{template "cookie_banner" .}}
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
|
{{end}}
|
||||||
|
|
@ -14,6 +14,9 @@
|
||||||
</header>
|
</header>
|
||||||
<section>
|
<section>
|
||||||
<p>This is your user home page.</p>
|
<p>This is your user home page.</p>
|
||||||
|
{{if .IsAdmin}}
|
||||||
|
<p><a href="{{.BasePath}}/admin/">Go to Admin Panel</a></p>
|
||||||
|
{{end}}
|
||||||
</section>
|
</section>
|
||||||
</main>
|
</main>
|
||||||
{{template "cookie_banner" .}}
|
{{template "cookie_banner" .}}
|
||||||
|
|
|
||||||
|
|
@ -5,11 +5,16 @@
|
||||||
<li><a {{if eq .Navbar "userhome"}}class="active"{{end}} href="{{.BasePath}}/userhome/">User Home</a></li>
|
<li><a {{if eq .Navbar "userhome"}}class="active"{{end}} href="{{.BasePath}}/userhome/">User Home</a></li>
|
||||||
<li><a {{if eq .Navbar "profile"}}class="active"{{end}} href="{{.BasePath}}/profile/">Profile</a></li>
|
<li><a {{if eq .Navbar "profile"}}class="active"{{end}} href="{{.BasePath}}/profile/">Profile</a></li>
|
||||||
<li><a {{if eq .Navbar "preferences"}}class="active"{{end}} href="{{.BasePath}}/preferences/">Preferences</a></li>
|
<li><a {{if eq .Navbar "preferences"}}class="active"{{end}} href="{{.BasePath}}/preferences/">Preferences</a></li>
|
||||||
|
{{if .IsAdmin}}
|
||||||
|
<li><a {{if eq .Navbar "admin"}}class="active"{{end}} href="{{.BasePath}}/admin/">Admin</a></li>
|
||||||
|
{{end}}
|
||||||
<li><a href="{{.BasePath}}/logout/">Logout</a></li>
|
<li><a href="{{.BasePath}}/logout/">Logout</a></li>
|
||||||
{{else}}
|
{{else}}
|
||||||
<li><a {{if eq .Navbar "login"}}class="active"{{end}} href="{{.BasePath}}/login/">Login</a></li>
|
<li><a {{if eq .Navbar "login"}}class="active"{{end}} href="{{.BasePath}}/login/">Login</a></li>
|
||||||
|
{{if .AllowSignup}}
|
||||||
<li><a {{if eq .Navbar "signup"}}class="active"{{end}} href="{{.BasePath}}/signup/">Sign Up</a></li>
|
<li><a {{if eq .Navbar "signup"}}class="active"{{end}} href="{{.BasePath}}/signup/">Sign Up</a></li>
|
||||||
{{end}}
|
{{end}}
|
||||||
|
{{end}}
|
||||||
<li><a {{if eq .Navbar "boards"}}class="active"{{end}} href="{{.BasePath}}/boards/">Boards</a></li>
|
<li><a {{if eq .Navbar "boards"}}class="active"{{end}} href="{{.BasePath}}/boards/">Boards</a></li>
|
||||||
<li><a {{if eq .Navbar "news"}}class="active"{{end}} href="{{.BasePath}}/news/">News</a></li>
|
<li><a {{if eq .Navbar "news"}}class="active"{{end}} href="{{.BasePath}}/news/">News</a></li>
|
||||||
<li><a {{if eq .Navbar "about"}}class="active"{{end}} href="{{.BasePath}}/about/">About</a></li>
|
<li><a {{if eq .Navbar "about"}}class="active"{{end}} href="{{.BasePath}}/about/">About</a></li>
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue