Put discussions feature behind flag
60b8dd63c9ab310178d391edd8d71ffc0ea2a618
1 parent
1f53abd7
handler.go
+19 -7
| 18 | 18 | Ref string |
|
| 19 | 19 | CommitHash string |
|
| 20 | 20 | Handle string |
|
| 21 | 21 | Avatar string |
|
| 22 | 22 | DevMode bool |
|
| 23 | + | Discussions bool |
|
| 23 | 24 | Data any |
|
| 24 | 25 | } |
|
| 25 | 26 | ||
| 26 | 27 | func (s *server) newPageData(r *http.Request, repo *RepoInfo, section, ref string) pageData { |
|
| 27 | - | handle := getSessionHandle(r) |
|
| 28 | - | var avatar string |
|
| 29 | - | if handle != "" { |
|
| 30 | - | avatar = getAvatar(s.db, handle) |
|
| 28 | + | var handle, avatar string |
|
| 29 | + | if s.discussions { |
|
| 30 | + | handle = getSessionHandle(r) |
|
| 31 | + | if handle != "" { |
|
| 32 | + | avatar = getAvatar(s.db, handle) |
|
| 33 | + | } |
|
| 31 | 34 | } |
|
| 32 | 35 | pd := pageData{ |
|
| 33 | 36 | SiteTitle: s.title, |
|
| 34 | 37 | SiteDescription: s.description, |
|
| 35 | 38 | BaseURL: s.baseURL, |
|
| 36 | 39 | Section: section, |
|
| 37 | 40 | Ref: ref, |
|
| 38 | 41 | Handle: handle, |
|
| 39 | 42 | Avatar: avatar, |
|
| 40 | 43 | DevMode: s.dev, |
|
| 44 | + | Discussions: s.discussions, |
|
| 41 | 45 | } |
|
| 42 | 46 | if repo != nil { |
|
| 43 | 47 | pd.Repo = repo.Name |
|
| 44 | 48 | pd.Description = repo.Description |
|
| 45 | 49 | } |
| 106 | 110 | if path == "" { |
|
| 107 | 111 | s.handleIndex(w, r) |
|
| 108 | 112 | return |
|
| 109 | 113 | } |
|
| 110 | 114 | ||
| 111 | - | if path == "login" { |
|
| 115 | + | if path == "login" && s.discussions { |
|
| 112 | 116 | s.handleLogin(w, r) |
|
| 113 | 117 | return |
|
| 114 | 118 | } |
|
| 115 | - | if path == "logout" { |
|
| 119 | + | if path == "logout" && s.discussions { |
|
| 116 | 120 | s.handleLogout(w, r) |
|
| 117 | 121 | return |
|
| 118 | 122 | } |
|
| 119 | 123 | ||
| 120 | - | if path == "dev/login" && s.dev { |
|
| 124 | + | if path == "dev/login" && s.dev && s.discussions { |
|
| 121 | 125 | s.handleDevLogin(w, r) |
|
| 122 | 126 | return |
|
| 123 | 127 | } |
|
| 124 | 128 | ||
| 125 | 129 | // Site-level forum (discussions not scoped to a repo). |
|
| 126 | 130 | if path == "discussions" || strings.HasPrefix(path, "discussions/") { |
|
| 131 | + | if !s.discussions { |
|
| 132 | + | s.renderError(w, r, http.StatusNotFound, "Page not found") |
|
| 133 | + | return |
|
| 134 | + | } |
|
| 127 | 135 | rest := strings.TrimPrefix(path, "discussions") |
|
| 128 | 136 | rest = strings.TrimPrefix(rest, "/") |
|
| 129 | 137 | s.routeSiteDiscussions(w, r, rest) |
|
| 130 | 138 | return |
|
| 131 | 139 | } |
| 166 | 174 | case "commit": |
|
| 167 | 175 | s.handleCommit(w, r, repo, rest) |
|
| 168 | 176 | case "raw": |
|
| 169 | 177 | s.handleRaw(w, r, repo, rest) |
|
| 170 | 178 | case "discussions": |
|
| 179 | + | if !s.discussions { |
|
| 180 | + | s.renderError(w, r, http.StatusNotFound, "Page not found") |
|
| 181 | + | return |
|
| 182 | + | } |
|
| 171 | 183 | s.routeDiscussions(w, r, repo, rest) |
|
| 172 | 184 | default: |
|
| 173 | 185 | s.renderError(w, r, http.StatusNotFound, "Page not found") |
|
| 174 | 186 | } |
|
| 175 | 187 | } |
main.go
+10 -4
| 22 | 22 | baseURL string |
|
| 23 | 23 | scanPath string |
|
| 24 | 24 | username string |
|
| 25 | 25 | password string |
|
| 26 | 26 | dev bool |
|
| 27 | + | discussions bool |
|
| 27 | 28 | } |
|
| 28 | 29 | ||
| 29 | 30 | func main() { |
|
| 30 | 31 | listen := flag.String("listen", ":8080", "listen address") |
|
| 31 | 32 | scanPath := flag.String("scan-path", ".", "path to scan for git repos") |
| 34 | 35 | baseURL := flag.String("base-url", "", "base URL prefix (e.g. /git)") |
|
| 35 | 36 | nonBare := flag.Bool("non-bare", false, "also scan for non-bare repos (dirs containing .git)") |
|
| 36 | 37 | username := flag.String("username", "", "HTTP basic auth username (requires -password)") |
|
| 37 | 38 | password := flag.String("password", "", "HTTP basic auth password (requires -username)") |
|
| 38 | 39 | dbPath := flag.String("db-path", "./forge.db", "path to SQLite database for discussions") |
|
| 40 | + | discussions := flag.Bool("discussions", false, "enable discussions feature") |
|
| 39 | 41 | dev := flag.Bool("dev", false, "enable dev mode (auto sign-in link)") |
|
| 40 | 42 | flag.Parse() |
|
| 41 | 43 | ||
| 42 | 44 | if (*username == "") != (*password == "") { |
|
| 43 | 45 | log.Fatal("-username and -password must both be set, or both be omitted") |
| 64 | 66 | tmpl, err := loadTemplates() |
|
| 65 | 67 | if err != nil { |
|
| 66 | 68 | log.Fatalf("load templates: %v", err) |
|
| 67 | 69 | } |
|
| 68 | 70 | ||
| 69 | - | db, err := openDB(*dbPath) |
|
| 70 | - | if err != nil { |
|
| 71 | - | log.Fatalf("open database: %v", err) |
|
| 71 | + | var db *sql.DB |
|
| 72 | + | if *discussions { |
|
| 73 | + | db, err = openDB(*dbPath) |
|
| 74 | + | if err != nil { |
|
| 75 | + | log.Fatalf("open database: %v", err) |
|
| 76 | + | } |
|
| 77 | + | defer db.Close() |
|
| 72 | 78 | } |
|
| 73 | - | defer db.Close() |
|
| 74 | 79 | ||
| 75 | 80 | srv := &server{ |
|
| 76 | 81 | repos: repos, |
|
| 77 | 82 | sorted: sorted, |
|
| 78 | 83 | tmpl: tmpl, |
| 82 | 87 | baseURL: strings.TrimRight(*baseURL, "/"), |
|
| 83 | 88 | scanPath: abs, |
|
| 84 | 89 | username: *username, |
|
| 85 | 90 | password: *password, |
|
| 86 | 91 | dev: *dev, |
|
| 92 | + | discussions: *discussions, |
|
| 87 | 93 | } |
|
| 88 | 94 | ||
| 89 | 95 | mux := http.NewServeMux() |
|
| 90 | 96 | mux.HandleFunc("/style.css", srv.serveCSS) |
|
| 91 | 97 | mux.HandleFunc("/radiant.svg", srv.serveLogo) |
templates/layout.html
+5 -5
| 10 | 10 | <div class="container"> |
|
| 11 | 11 | {{if not .Repo}} |
|
| 12 | 12 | <nav class="repo-nav"> |
|
| 13 | 13 | <span class="repo-name"><a href="{{.BaseURL}}/" class="logo-link"><img class="logo" src="{{.BaseURL}}/radiant.svg" alt="" width="16" height="16"></a><a href="{{.BaseURL}}/">{{.SiteTitle}}</a>{{if .SiteDescription}}<span class="repo-desc desktop">{{.SiteDescription}}</span>{{end}}</span> |
|
| 14 | 14 | <a href="{{.BaseURL}}/" class="tab{{if eq .Section "repositories"}} active{{end}}">repositories</a> |
|
| 15 | - | <a href="{{.BaseURL}}/discussions" class="tab{{if eq .Section "forum"}} active{{end}}">discussions</a> |
|
| 16 | - | <span class="nav-auth">{{if .Handle}}<details class="avatar-menu"><summary>{{if .Avatar}}<img class="avatar" src="{{.Avatar}}" alt="" width="24" height="24">{{else}}<span class="avatar-placeholder">{{.Handle}}</span>{{end}}</summary><div class="avatar-dropdown"><span class="signed-in">{{.Handle}}</span><a href="{{.BaseURL}}/logout?return={{.BaseURL}}/" class="btn nav-btn">Sign out</a></div></details>{{else}}<a href="{{.BaseURL}}/login?return={{.BaseURL}}/" class="btn nav-btn">Sign in</a>{{end}}</span> |
|
| 15 | + | {{if .Discussions}}<a href="{{.BaseURL}}/discussions" class="tab{{if eq .Section "forum"}} active{{end}}">discussions</a>{{end}} |
|
| 16 | + | {{if .Discussions}}<span class="nav-auth">{{if .Handle}}<details class="avatar-menu"><summary>{{if .Avatar}}<img class="avatar" src="{{.Avatar}}" alt="" width="24" height="24">{{else}}<span class="avatar-placeholder">{{.Handle}}</span>{{end}}</summary><div class="avatar-dropdown"><span class="signed-in">{{.Handle}}</span><a href="{{.BaseURL}}/logout?return={{.BaseURL}}/" class="btn nav-btn">Sign out</a></div></details>{{else}}<a href="{{.BaseURL}}/login?return={{.BaseURL}}/" class="btn nav-btn">Sign in</a>{{end}}</span>{{end}} |
|
| 17 | 17 | </nav> |
|
| 18 | 18 | {{end}} |
|
| 19 | 19 | {{if .Repo}} |
|
| 20 | 20 | <nav class="repo-nav"> |
|
| 21 | 21 | <span class="repo-name"><a href="{{.BaseURL}}/" class="logo-link"><img class="logo" src="{{.BaseURL}}/radiant.svg" alt="" width="16" height="16"></a><a href="{{.BaseURL}}/{{.Repo}}/">{{.Repo}}</a>{{if .Description}}<span class="repo-desc desktop">{{.Description}}</span>{{end}}</span> |
|
| 22 | 22 | <a href="{{.BaseURL}}/{{.Repo}}/" class="tab{{if eq .Section "home"}} active{{end}}">home</a> |
|
| 23 | 23 | <a href="{{.BaseURL}}/{{.Repo}}/log/{{.Ref}}" class="tab{{if eq .Section "log"}} active{{end}}">log</a> |
|
| 24 | 24 | <a href="{{.BaseURL}}/{{.Repo}}/refs" class="tab{{if eq .Section "refs"}} active{{end}}">refs</a> |
|
| 25 | - | <a href="{{.BaseURL}}/{{.Repo}}/discussions" class="tab{{if eq .Section "discussions"}} active{{end}}">discussions</a> |
|
| 25 | + | {{if .Discussions}}<a href="{{.BaseURL}}/{{.Repo}}/discussions" class="tab{{if eq .Section "discussions"}} active{{end}}">discussions</a>{{end}} |
|
| 26 | 26 | {{if .CommitHash}}<a href="{{.BaseURL}}/{{.Repo}}/commit/{{.CommitHash}}" class="tab tab-mono active">{{shortHash .CommitHash}}</a>{{end}} |
|
| 27 | - | <span class="nav-auth">{{if .Handle}}<details class="avatar-menu"><summary>{{if .Avatar}}<img class="avatar" src="{{.Avatar}}" alt="" width="24" height="24">{{else}}<span class="avatar-placeholder">{{.Handle}}</span>{{end}}</summary><div class="avatar-dropdown"><span class="signed-in">{{.Handle}}</span><a href="{{.BaseURL}}/logout?return={{.BaseURL}}/{{.Repo}}/" class="btn nav-btn">Sign out</a></div></details>{{else}}<a href="{{.BaseURL}}/login?return={{.BaseURL}}/{{.Repo}}/" class="btn nav-btn">Sign in</a>{{end}}</span> |
|
| 27 | + | {{if .Discussions}}<span class="nav-auth">{{if .Handle}}<details class="avatar-menu"><summary>{{if .Avatar}}<img class="avatar" src="{{.Avatar}}" alt="" width="24" height="24">{{else}}<span class="avatar-placeholder">{{.Handle}}</span>{{end}}</summary><div class="avatar-dropdown"><span class="signed-in">{{.Handle}}</span><a href="{{.BaseURL}}/logout?return={{.BaseURL}}/{{.Repo}}/" class="btn nav-btn">Sign out</a></div></details>{{else}}<a href="{{.BaseURL}}/login?return={{.BaseURL}}/{{.Repo}}/" class="btn nav-btn">Sign in</a>{{end}}</span>{{end}} |
|
| 28 | 28 | </nav> |
|
| 29 | 29 | {{end}} |
|
| 30 | 30 | <main> |
|
| 31 | 31 | {{template "content" .}} |
|
| 32 | 32 | </main> |
|
| 33 | 33 | {{if not .Repo}} |
|
| 34 | 34 | <footer> |
|
| 35 | - | <p><span class="powered-by">Powered by <a href="https://code.radiant.computer/forge">Radiant Forge</a></span>{{if and .DevMode (not .Handle)}}<span class="dev-login"><a href="{{.BaseURL}}/dev/login?return={{.BaseURL}}/">Sign in as cloudhead.io</a></span>{{end}}<span class="copyright">© 2026 Radiant Computer</span></p> |
|
| 35 | + | <p><span class="powered-by">Powered by <a href="https://code.radiant.computer/forge">Radiant Forge</a></span>{{if and .Discussions .DevMode (not .Handle)}}<span class="dev-login"><a href="{{.BaseURL}}/dev/login?return={{.BaseURL}}/">Sign in as cloudhead.io</a></span>{{end}}<span class="copyright">© 2026 Radiant Computer</span></p> |
|
| 36 | 36 | </footer> |
|
| 37 | 37 | {{end}} |
|
| 38 | 38 | </div> |
|
| 39 | 39 | <script src="{{.BaseURL}}/js/hirad.js"></script> |
|
| 40 | 40 | <script src="{{.BaseURL}}/js/hiril.js"></script> |