commit 7913fe3eaf88810973278501d1578dc197c3ecbe
parent 31cbdc01e6051987f3ad5133b96590a7ec11ff55
Author: cblgh <cblgh@cblgh.org>
Date: Thu, 20 Oct 2022 10:57:07 +0200
cleanup & decide on initial structure for content files
Diffstat:
6 files changed, 58 insertions(+), 61 deletions(-)
diff --git a/defaults/sample-config.toml b/defaults/sample-config.toml
@@ -1,10 +1,10 @@
[general]
name = ""
-conduct_url = "" # optional + recommended: if omitted, the checkboxes in registration relating to CoC will be hidden
-language = "" # Swedish, English
+conduct_url = "" # optional + recommended: if omitted, the CoC checkboxes in /register will be hidden
+language = "" # Swedish, English. contributions for more translations welcome!
[documents]
-logo = "logo.html"
-about = "about.md"
-rules = "rules.md"
-verification_explanation = "verification-instructions.md"
+logo = "content/logo.html" # can contain emoji, <img>, <svg> etc. see defaults/sample-logo.html in repo for instructions
+about = "content/about.md"
+rules = "content/rules.md"
+verification_explanation = "content/verification-instructions.md"
diff --git a/defaults/sample-logo.html b/defaults/sample-logo.html
@@ -5,7 +5,6 @@
<path d="M125,65 A60,60 0 0,1 185,125 L125,125 Z M185,245 A60,60 0 0,1 125,185 L185,185 Z M65,65 A60,60 0 0,1 125,125 L65,125 Z M65,245 A60,60 0 0,0 125,185 L65,185 Z M245,65 A60,60 0 0,0 185,125 L245,125 Z M245,245 A60,60 0 0,1 185,185 L245,185 Z"/>
</g>
</svg>
--->
<!-- here's how to have a png logo
it's important with the path starting with /assets/, and that the loaded asset is inside dir <cercaroot>/html/assets
diff --git a/run.go b/run.go
@@ -43,7 +43,7 @@ func main() {
flag.StringVar(&allowlistLocation, "allowlist", "", "domains which can be used to read verification codes from during registration")
flag.StringVar(&sessionKey, "authkey", "", "session cookies authentication key")
flag.StringVar(&configPath, "config", "cerca.toml", "config and settings file containing cerca's customizations")
- flag.StringVar(&dataDir, "data", "./data", "directory where cerca will dump its files (database and customizable documents)")
+ flag.StringVar(&dataDir, "data", "./data", "directory where cerca will dump its database")
flag.Parse()
if len(sessionKey) == 0 {
complain("please pass a random session auth key with --authkey")
diff --git a/server/server.go b/server/server.go
@@ -27,21 +27,6 @@ import (
"github.com/carlmjohnson/requests"
)
-/* 2022-09-20: customizable stuff
-* CommunityName
-* CommunityLogo
-* CommunityLink
-* ForumName
- */
-
-// TODO (2022-09-20): make verification instructions another md file to load, pass path from config
-/*
-* pass in:
-* registration rules
-* verification instructions
-* code of conduct link
- */
-
/* TODO (2022-01-03): include csrf token via gorilla, or w/e, when rendering */
type TemplateData struct {
@@ -104,7 +89,6 @@ type RequestHandler struct {
}
var developing bool
-var config types.Config
func dump(err error) {
if developing {
@@ -218,6 +202,9 @@ func (h RequestHandler) renderView(res http.ResponseWriter, viewName string, dat
data.Title = strings.ReplaceAll(viewName, "-", " ")
}
+ if h.config.Community.Name != "" {
+ data.ForumName = h.config.Community.Name
+ }
if data.ForumName == "" {
data.ForumName = "Forum"
}
@@ -734,7 +721,6 @@ func (h RequestHandler) DeletePostRoute(res http.ResponseWriter, req *http.Reque
func Serve(allowlist []string, sessionKey string, isdev bool, dir string, conf types.Config) {
port := ":8272"
- config = conf
if isdev {
developing = true
@@ -763,7 +749,6 @@ func Serve(allowlist []string, sessionKey string, isdev bool, dir string, conf t
type CercaForum struct {
http.ServeMux
Directory string
- Files map[string][]byte
}
func (u *CercaForum) directory() string {
@@ -778,41 +763,46 @@ func (u *CercaForum) directory() string {
return u.Directory
}
-func (c *CercaForum) loadFile(key, filepath, defaultContent string) {
- _, err := util.CreateIfNotExist(filepath, defaultContent)
- util.Check(err, "create if not exist (%s) %s", key, filepath)
- c.Files[key], err = os.ReadFile(filepath)
- util.Check(err, "read %s", filepath)
-}
-
// NewServer sets up a new CercaForum object. Always use this to initialize
// new CercaForum objects. Pass the result to http.Serve() with your choice
// of net.Listener.
-func NewServer(allowlist []string, sessionKey, dir string, conf types.Config) (*CercaForum, error) {
+func NewServer(allowlist []string, sessionKey, dir string, config types.Config) (*CercaForum, error) {
s := &CercaForum{
ServeMux: http.ServeMux{},
Directory: dir,
- Files: make(map[string][]byte),
}
dbpath := filepath.Join(s.directory(), "forum.db")
db := database.InitDB(dbpath)
- // TODO (2022-10-18): introduce step where if config document path is empty => config.Documents.<path> =
- // filepath.Join(s.directory(), <name>)
+ // TODO? (2022-10-18): introduce step where if config document path is empty =>
+ // cconfig.Documents.<path> = filepath.Join(s.directory(), <name>)
// load the documents specified in the config
// iff document doesn't exist, dump a default document where it should be and read that
- s.loadFile("about", config.Documents.AboutPath, defaults.DEFAULT_ABOUT)
- s.loadFile("rules", config.Documents.RegisterRulesPath, defaults.DEFAULT_RULES)
- s.loadFile("verification-instructions", config.Documents.VerificationExplanationPath, defaults.DEFAULT_VERIFICATION)
- s.loadFile("logo", config.Documents.LogoPath, defaults.DEFAULT_LOGO)
-
- /* note: be careful with trailing slashes; go's default handler is a bit sensitive */
+ type triple struct { key, docpath, content string }
+ triples := []triple{
+ {"about", config.Documents.AboutPath, defaults.DEFAULT_ABOUT},
+ {"rules", config.Documents.RegisterRulesPath, defaults.DEFAULT_RULES},
+ {"verification-instructions", config.Documents.VerificationExplanationPath, defaults.DEFAULT_VERIFICATION},
+ {"logo", config.Documents.LogoPath, defaults.DEFAULT_LOGO},
+ }
+
+ files := make(map[string][]byte)
+ for _, t := range triples {
+ data, err := util.LoadFile(t.key, t.docpath, t.content)
+ if err != nil {
+ return s, err
+ }
+ files[t.key] = data
+ }
+
+ // TODO (2022-10-20): when receiving user request, inspect user-agent language and change language from server default
translator := i18n.Init(config.Community.Language)
templates := template.Must(generateTemplates(config, translator))
- handler := RequestHandler{&db, session.New(sessionKey, developing), allowlist, s.Files, config, translator, templates}
+ handler := RequestHandler{&db, session.New(sessionKey, developing), allowlist, files, config, translator, templates}
+ /* note: be careful with trailing slashes; go's default handler is a bit sensitive */
// TODO (2022-01-10): introduce middleware to make sure there is never an issue with trailing slashes
s.ServeMux.HandleFunc("/reset/", handler.ResetPasswordRoute)
s.ServeMux.HandleFunc("/about", handler.AboutRoute)
diff --git a/types/types.go b/types/types.go
@@ -1,11 +1,6 @@
package types
type Config struct {
- // use as:
- // config.Files["about"] -> about markdown
- // config.Files["rules"] -> rules explanation markdown
- // config.Files["verification"] -> verification explanation
-
Community struct {
Name string `json:"name"`
ConductLink string `json:"conduct_url"`
@@ -16,19 +11,14 @@ type Config struct {
LogoPath string `json:"logo"`
AboutPath string `json:"about"`
RegisterRulesPath string `json:"rules"`
- VerificationExplanationPath string `json:"verification_explanation"`
+ VerificationExplanationPath string `json:"verification_instructions"`
} `json:"documents"`
}
/*
-config.Community.Name
-config.Community.Link
-config.Community.ConductLink
-
config structure
["General"]
Name = "Merveilles"
-Link = "https://wiki.xxiivv.com/site/merveilles.html"
ConductLink = "https://github.com/merveilles/Resources/blob/master/CONDUCT.md"
diff --git a/util/util.go b/util/util.go
@@ -8,6 +8,7 @@ import (
"encoding/json"
"errors"
"io/fs"
+ "path/filepath"
"fmt"
"html/template"
"log"
@@ -154,12 +155,16 @@ func Capitalize(s string) string {
return strings.ToUpper(string(s[0])) + s[1:]
}
-func CreateIfNotExist(filepath, content string) (bool, error) {
- _, err := os.Stat(filepath)
+func CreateIfNotExist(docpath, content string) (bool, error) {
+ err := os.MkdirAll(filepath.Dir(docpath), 0750)
+ if err != nil {
+ return false, err
+ }
+ _, err = os.Stat(docpath)
if err != nil {
// if the file doesn't exist, create it
if errors.Is(err, fs.ErrNotExist) {
- err = os.WriteFile(filepath, []byte(content), 0777)
+ err = os.WriteFile(docpath, []byte(content), 0777)
if err != nil {
return false, err
}
@@ -172,9 +177,6 @@ func CreateIfNotExist(filepath, content string) (bool, error) {
return false, nil
}
-// TODO (2022-09-21):
-// * DONE go:embed sample-config.toml ---> defaults.DEFAULT_<x>
-// * util.checkFileExists(path, mockContents)
func ReadConfig(confpath string) types.Config {
ed := Describe("config")
_, err := CreateIfNotExist(confpath, defaults.DEFAULT_CONFIG)
@@ -191,3 +193,19 @@ func ReadConfig(confpath string) types.Config {
return conf
}
+
+func LoadFile(key, docpath, defaultContent string) ([]byte, error) {
+ ed := Describe("load file")
+ _, err := CreateIfNotExist(docpath, defaultContent)
+ err = ed.Eout(err, "create if not exist (%s) %s", key, docpath)
+ if err != nil {
+ return nil, err
+ }
+ data, err := os.ReadFile(docpath)
+ err = ed.Eout(err, "read %s", docpath)
+ if err != nil {
+ return nil, err
+ }
+ return data, nil
+}
+