This commit is contained in:
Iris Lightshard 2022-05-29 00:26:36 -06:00
parent b7e2dc3ab7
commit bea90e0e1c
Signed by: Iris Lightshard
GPG key ID: 3B7FBC22144E6398
6 changed files with 249 additions and 252 deletions

View file

@ -1,16 +1,16 @@
package adapter package adapter
import ( import (
"nilfm.cc/git/nirvash/page" "nilfm.cc/git/nirvash/page"
) )
type Adapter interface { type Adapter interface {
Name() string Name() string
GetConfig(key string) (interface{}, error) GetConfig(key string) (interface{}, error)
SetConfig(key string, value interface{}) error SetConfig(key string, value interface{}) error
ListPages() map[string]string ListPages() map[string]string
GetPage(string) page.Page GetPage(string) page.Page
FormatPage(string) string FormatPage(string) string
FormattingHelp() string FormattingHelp() string
Build() Build()
} }

View file

@ -1,41 +1,41 @@
package adapter package adapter
import ( import (
"nilfm.cc/git/nirvash/page" "nilfm.cc/git/nirvash/page"
) )
type EurekaAdapter struct { type EurekaAdapter struct {
Root string Root string
} }
func (self *EurekaAdapter) Name() string { func (self *EurekaAdapter) Name() string {
return "eureka" return "eureka"
} }
func (self *EurekaAdapter) GetConfig(key string) (interface{}, error) { func (self *EurekaAdapter) GetConfig(key string) (interface{}, error) {
return nil, nil return nil, nil
} }
func (self *EurekaAdapter) SetConfig(key string, value interface{}) error { func (self *EurekaAdapter) SetConfig(key string, value interface{}) error {
return nil return nil
} }
func (self *EurekaAdapter) ListPages() map[string]string { func (self *EurekaAdapter) ListPages() map[string]string {
return map[string]string{} return map[string]string{}
} }
func (self *EurekaAdapter) GetPage(path string) page.Page { func (self *EurekaAdapter) GetPage(path string) page.Page {
return page.Page{} return page.Page{}
} }
func (self *EurekaAdapter) FormatPage(raw string) string { func (self *EurekaAdapter) FormatPage(raw string) string {
return raw return raw
} }
func (self *EurekaAdapter) FormattingHelp() string { func (self *EurekaAdapter) FormattingHelp() string {
return "help!" return "help!"
} }
func (self *EurekaAdapter) Build() { func (self *EurekaAdapter) Build() {
return return
} }

View file

@ -1,61 +1,61 @@
package cmd package cmd
import ( import (
"fmt" "fmt"
"strings" "nilfm.cc/git/nirvash/config"
"nilfm.cc/git/quartzgun/auth" "nilfm.cc/git/quartzgun/auth"
"nilfm.cc/git/nirvash/config" "strings"
) )
func Process(args []string, userStore auth.UserStore, cfg *config.Config) bool { func Process(args []string, userStore auth.UserStore, cfg *config.Config) bool {
if len(args) == 1 { if len(args) == 1 {
return false return false
} }
switch args[1] { switch args[1] {
case "adduser": case "adduser":
if len(args) < 4 { if len(args) < 4 {
return help() return help()
} }
userStore.AddUser(args[2], args[3]) userStore.AddUser(args[2], args[3])
case "rmuser": case "rmuser":
if len(args) < 3 { if len(args) < 3 {
return help() return help()
} }
userStore.DeleteUser(args[2]) userStore.DeleteUser(args[2])
case "passwd": case "passwd":
if len(args) < 5 { if len(args) < 5 {
return help() return help()
} }
userStore.ChangePassword(args[2], args[3], args[4]) userStore.ChangePassword(args[2], args[3], args[4])
case "configure": case "configure":
fmt.Printf("configuring\n") fmt.Printf("configuring\n")
for _, token := range args[2:] { for _, token := range args[2:] {
kvp := strings.Split(token, "=") kvp := strings.Split(token, "=")
k := kvp[0] k := kvp[0]
v := kvp[1] v := kvp[1]
fmt.Printf("%s = %s\n", k, v) fmt.Printf("%s = %s\n", k, v)
switch k { switch k {
case "adapter": case "adapter":
config.SetAdapter(cfg, v) config.SetAdapter(cfg, v)
case "root": case "root":
cfg.Root = v cfg.Root = v
case "assetRoot": case "assetRoot":
cfg.AssetRoot = v cfg.AssetRoot = v
case "staticRoot": case "staticRoot":
cfg.StaticRoot = v cfg.StaticRoot = v
case "plugins": case "plugins":
// handle plugins later // handle plugins later
default: default:
panic("unknown configuration option: " + v) panic("unknown configuration option: " + v)
} }
} }
config.Write(cfg) config.Write(cfg)
default: default:
help() help()
} }
return true return true
} }
func help() bool { func help() bool {
return true return true
} }

View file

@ -1,173 +1,170 @@
package config package config
import ( import (
"fmt" "fmt"
"runtime" "nilfm.cc/git/nirvash/adapter"
"os" "os"
"strings" "path/filepath"
"path/filepath" "runtime"
"nilfm.cc/git/nirvash/adapter" "strings"
) )
type Config struct { type Config struct {
Adapter adapter.Adapter // adapter for this instance Adapter adapter.Adapter // adapter for this instance
Root string // root of the site data Root string // root of the site data
StaticRoot string // root of static files for StaticFileManager StaticRoot string // root of static files for StaticFileManager
AssetRoot string // root of Nirvash dist files (CSS, images) AssetRoot string // root of Nirvash dist files (CSS, images)
Plugins map[string]interface{} Plugins map[string]interface{}
} }
func GetConfigLocation() string { func GetConfigLocation() string {
home := os.Getenv("HOME") home := os.Getenv("HOME")
appdata := os.Getenv("APPDATA") appdata := os.Getenv("APPDATA")
switch (runtime.GOOS) { switch runtime.GOOS {
case "windows": case "windows":
return filepath.Join(appdata, "nirvash") return filepath.Join(appdata, "nirvash")
case "darwin": case "darwin":
return filepath.Join(home, "Library", "Application Support", "nirvash") return filepath.Join(home, "Library", "Application Support", "nirvash")
case "plan9": case "plan9":
return filepath.Join(home, "lib", "nirvash") return filepath.Join(home, "lib", "nirvash")
default: default:
return filepath.Join(home, ".config", "nirvash") return filepath.Join(home, ".config", "nirvash")
} }
} }
func ensureConfigLocationExists() { func ensureConfigLocationExists() {
_, err := os.Stat(GetConfigLocation()) _, err := os.Stat(GetConfigLocation())
if os.IsNotExist(err) { if os.IsNotExist(err) {
os.MkdirAll(GetConfigLocation(), os.ModePerm) os.MkdirAll(GetConfigLocation(), os.ModePerm)
} }
} }
func Read() *Config { func Read() *Config {
ensureConfigLocationExists() ensureConfigLocationExists()
return parseConfig(filepath.Join(GetConfigLocation(), "nirvash.conf")) return parseConfig(filepath.Join(GetConfigLocation(), "nirvash.conf"))
} }
func Write(cfg *Config) error { func Write(cfg *Config) error {
ensureConfigLocationExists() ensureConfigLocationExists()
return writeConfig(cfg, filepath.Join(GetConfigLocation(), "nirvash.conf")) return writeConfig(cfg, filepath.Join(GetConfigLocation(), "nirvash.conf"))
} }
func SetAdapter(cfg *Config, adptr string) { func SetAdapter(cfg *Config, adptr string) {
switch adptr { switch adptr {
case "eureka": case "eureka":
cfg.Adapter = &adapter.EurekaAdapter{} cfg.Adapter = &adapter.EurekaAdapter{}
default: default:
panic("Unsupported adapter! Try one of [ eureka ]") panic("Unsupported adapter! Try one of [ eureka ]")
} }
} }
func IsNull(cfg *Config) bool { func IsNull(cfg *Config) bool {
return cfg.Adapter == nil || len(cfg.Root) == 0 || len(cfg.StaticRoot) == 0 || len(cfg.AssetRoot) == 0 return cfg.Adapter == nil || len(cfg.Root) == 0 || len(cfg.StaticRoot) == 0 || len(cfg.AssetRoot) == 0
} }
func RunWizard(cfg *Config) { func RunWizard(cfg *Config) {
fmt.Printf("All options are required.\n") fmt.Printf("All options are required.\n")
defer func(cfg *Config) { defer func(cfg *Config) {
if r := recover(); r != nil { if r := recover(); r != nil {
fmt.Printf("Invalid selection, starting over...") fmt.Printf("Invalid selection, starting over...")
RunWizard(cfg) RunWizard(cfg)
} }
}(cfg) }(cfg)
inputBuf := "" inputBuf := ""
fmt.Printf("adapter? (eureka) [eureka] ") fmt.Printf("adapter? (eureka) [eureka] ")
fmt.Scanln(&inputBuf) fmt.Scanln(&inputBuf)
if len(strings.TrimSpace(inputBuf)) == 0 { if len(strings.TrimSpace(inputBuf)) == 0 {
inputBuf = "eureka" inputBuf = "eureka"
} }
SetAdapter(cfg, inputBuf) SetAdapter(cfg, inputBuf)
inputBuf = "" inputBuf = ""
fmt.Printf("site data root? ") fmt.Printf("site data root? ")
ensureNonEmptyOption(&inputBuf) ensureNonEmptyOption(&inputBuf)
cfg.Root = inputBuf cfg.Root = inputBuf
inputBuf = "" inputBuf = ""
fmt.Printf("static file root? ") fmt.Printf("static file root? ")
ensureNonEmptyOption(&inputBuf) ensureNonEmptyOption(&inputBuf)
cfg.StaticRoot = inputBuf cfg.StaticRoot = inputBuf
inputBuf = "" inputBuf = ""
fmt.Printf("nirvash asset root? ") fmt.Printf("nirvash asset root? ")
ensureNonEmptyOption(&inputBuf) ensureNonEmptyOption(&inputBuf)
cfg.AssetRoot = inputBuf cfg.AssetRoot = inputBuf
inputBuf = "" inputBuf = ""
fmt.Printf("plugins? (not implemented yet) ") fmt.Printf("plugins? (not implemented yet) ")
ensureNonEmptyOption(&inputBuf) ensureNonEmptyOption(&inputBuf)
//cfg.Plugins = processPlugins(inputBuf) //cfg.Plugins = processPlugins(inputBuf)
fmt.Printf("Configuration complete!\n") fmt.Printf("Configuration complete!\n")
Write(cfg) Write(cfg)
} }
func ensureNonEmptyOption(buffer *string) { func ensureNonEmptyOption(buffer *string) {
for ;; { for {
fmt.Scanln(buffer) fmt.Scanln(buffer)
if len(strings.TrimSpace(*buffer)) != 0 { if len(strings.TrimSpace(*buffer)) != 0 {
break break
} }
} }
} }
func writeConfig(cfg *Config, configFile string) error { func writeConfig(cfg *Config, configFile string) error {
f, err := os.Create(configFile) f, err := os.Create(configFile)
if err != nil { if err != nil {
return err return err
} }
defer f.Close() defer f.Close()
f.WriteString("root=" + cfg.Root + "\n") f.WriteString("root=" + cfg.Root + "\n")
f.WriteString("staticRoot=" + cfg.StaticRoot + "\n") f.WriteString("staticRoot=" + cfg.StaticRoot + "\n")
f.WriteString("assetRoot=" + cfg.AssetRoot + "\n") f.WriteString("assetRoot=" + cfg.AssetRoot + "\n")
f.WriteString("adapter=" + cfg.Adapter.Name() + "\n") f.WriteString("adapter=" + cfg.Adapter.Name() + "\n")
f.WriteString("plugins=\n") f.WriteString("plugins=\n")
return nil return nil
} }
func parseConfig(configFile string) *Config { func parseConfig(configFile string) *Config {
f, err := os.ReadFile(configFile) f, err := os.ReadFile(configFile)
cfg := &Config{} cfg := &Config{}
if err != nil { if err != nil {
return cfg return cfg
} }
fileData := string(f[:]) fileData := string(f[:])
lines := strings.Split(fileData, "\n") lines := strings.Split(fileData, "\n")
for _, l := range lines { for _, l := range lines {
if len(l) == 0 { if len(l) == 0 {
continue continue
} }
if !strings.Contains(l, "=") { if !strings.Contains(l, "=") {
panic("Malformed config not in INI format") panic("Malformed config not in INI format")
} }
kvp := strings.Split(l, "=") kvp := strings.Split(l, "=")
k := strings.TrimSpace(kvp[0]) k := strings.TrimSpace(kvp[0])
v := strings.TrimSpace(kvp[1]) v := strings.TrimSpace(kvp[1])
switch k { switch k {
case "root": case "root":
cfg.Root = v cfg.Root = v
case "staticRoot": case "staticRoot":
cfg.StaticRoot = v cfg.StaticRoot = v
case "assetRoot": case "assetRoot":
cfg.AssetRoot = v cfg.AssetRoot = v
case "plugins": case "plugins":
// not implemented // not implemented
case "adapter": case "adapter":
SetAdapter(cfg, v) SetAdapter(cfg, v)
default: default:
panic("Unrecognized config option: " + k) panic("Unrecognized config option: " + k)
} }
} }
return cfg return cfg
} }

View file

@ -1,46 +1,46 @@
package main package main
import ( import (
"os" "net/http"
"path/filepath" "nilfm.cc/git/nirvash/cmd"
"net/http" "nilfm.cc/git/nirvash/config"
"nilfm.cc/git/quartzgun/indentalUserDB" "nilfm.cc/git/quartzgun/indentalUserDB"
"nilfm.cc/git/quartzgun/router" "nilfm.cc/git/quartzgun/middleware"
"nilfm.cc/git/quartzgun/renderer" "nilfm.cc/git/quartzgun/renderer"
"nilfm.cc/git/quartzgun/middleware" "nilfm.cc/git/quartzgun/router"
"nilfm.cc/git/nirvash/cmd" "os"
"nilfm.cc/git/nirvash/config" "path/filepath"
) )
func main() { func main() {
cfg := config.Read() cfg := config.Read()
udb := indentalUserDB.CreateIndentalUserDB( udb := indentalUserDB.CreateIndentalUserDB(
filepath.Join( filepath.Join(
config.GetConfigLocation(), config.GetConfigLocation(),
"user.db")) "user.db"))
if cmd.Process(os.Args, udb, cfg) { if cmd.Process(os.Args, udb, cfg) {
os.Exit(0) os.Exit(0)
} }
if config.IsNull(cfg) { if config.IsNull(cfg) {
config.RunWizard(cfg) config.RunWizard(cfg)
} }
rtr := &router.Router{ rtr := &router.Router{
StaticPaths: map[string]string{ StaticPaths: map[string]string{
"/static": cfg.AssetRoot, "/static": cfg.AssetRoot,
}, },
} }
rtr.Get("/login", renderer.Template( rtr.Get("/login", renderer.Template(
"templates/login.html")) "templates/login.html"))
rtr.Post("/login", middleware.Authorize("/", udb, "/login?tryagain=1")) rtr.Post("/login", middleware.Authorize("/", udb, "/login?tryagain=1"))
rtr.Get("/", middleware.Protected( rtr.Get("/", middleware.Protected(
renderer.Template( renderer.Template(
"templates/cms_list.html", "templates/cms_list.html",
"templates/header.html", "templates/header.html",
"templates/footer.html"), http.MethodGet, udb, "/login")) "templates/footer.html"), http.MethodGet, udb, "/login"))
http.ListenAndServe(":8080", rtr) http.ListenAndServe(":8080", rtr)
} }

View file

@ -1,11 +1,11 @@
package page package page
import ( import (
"time" "time"
) )
type Page struct { type Page struct {
Title string Title string
Content string Content string
Edited time.Time Edited time.Time
} }