2021-05-11 08:33:00 +00:00
// Package cfg contains global variables that represent the current wiki configuration, including CLI options, configuration file values and header links.
2021-05-09 09:36:39 +00:00
package cfg
2021-03-06 09:40:47 +00:00
import (
2021-06-19 16:48:54 +00:00
"errors"
2021-06-19 17:00:28 +00:00
"fmt"
2021-06-19 16:48:54 +00:00
"os"
2021-03-06 09:40:47 +00:00
"strconv"
"github.com/go-ini/ini"
)
2021-06-19 16:48:54 +00:00
// These variables represent the configuration. You are not meant to modify
// them after they were set.
// See https://mycorrhiza.lesarbr.es/hypha/configuration/fields for the
// documentation.
2021-05-09 09:36:39 +00:00
var (
WikiName string
NaviTitleIcon string
HomeHypha string
UserHypha string
HeaderLinksHypha string
HTTPPort string
URL string
GeminiCertificatePath string
2021-06-19 16:48:54 +00:00
UseFixedAuth bool
UseRegistration bool
LimitRegistration int
2021-05-22 18:05:14 +00:00
OmnipresentScripts [ ] string
ViewScripts [ ] string
EditScripts [ ] string
2021-05-09 09:36:39 +00:00
)
2021-06-19 16:48:54 +00:00
// WikiDir is a full path to the wiki storage directory, which also must be a
// git repo. This variable is set in parseCliArgs().
var WikiDir string
2021-05-11 08:33:00 +00:00
2021-06-19 16:48:54 +00:00
// Config represents a Mycorrhiza wiki configuration file. This type is used
// only when reading configs.
2021-03-06 09:40:47 +00:00
type Config struct {
2021-06-19 16:48:54 +00:00
WikiName string ` comment:"This name appears in the header and on various pages." `
NaviTitleIcon string ` comment:"This icon is used in the breadcrumbs bar." `
2021-03-06 09:40:47 +00:00
Hyphae
Network
2021-06-19 16:48:54 +00:00
Authorization ` comment:"" `
CustomScripts ` comment:"You can specify additional scripts to load on different kinds of pages, delimited by a comma ',' sign." `
2021-03-06 09:40:47 +00:00
}
2021-05-09 09:36:39 +00:00
// Hyphae is a section of Config which has fields related to special hyphae.
2021-03-06 09:40:47 +00:00
type Hyphae struct {
2021-06-19 16:48:54 +00:00
HomeHypha string ` comment:"This hypha will be the main (index) page of your wiki, served on /." `
UserHypha string ` comment:"This hypha is used as a prefix for user hyphae." `
HeaderLinksHypha string ` comment:"You can also specify a hypha to populate your own custom header links from." `
2021-03-06 09:40:47 +00:00
}
2021-06-19 16:48:54 +00:00
// Network is a section of Config that has fields related to network stuff:
// HTTP and Gemini.
2021-03-06 09:40:47 +00:00
type Network struct {
HTTPPort uint64
2021-06-19 16:48:54 +00:00
URL string ` comment:"Set your wiki's public URL here. It's used for OpenGraph generation and syndication feeds." `
GeminiCertificatePath string ` comment:"Gemini requires servers to use TLS for client connections. Specify your certificate's path here." `
2021-03-06 09:40:47 +00:00
}
2021-06-19 16:48:54 +00:00
// CustomScripts is a section with paths to JavaScript files that are loaded on
// specified pages.
2021-05-22 18:05:14 +00:00
type CustomScripts struct {
// OmnipresentScripts: everywhere...
2021-06-19 16:48:54 +00:00
OmnipresentScripts [ ] string ` delim:"," comment:"These scripts are loaded from anywhere." `
2021-05-22 18:05:14 +00:00
// ViewScripts: /hypha, /rev
2021-06-19 16:48:54 +00:00
ViewScripts [ ] string ` delim:"," comment:"These scripts are only loaded on view pages." `
2021-05-22 18:05:14 +00:00
// Edit: /edit
2021-06-19 16:48:54 +00:00
EditScripts [ ] string ` delim:"," comment:"These scripts are only loaded on the edit page." `
2021-05-22 18:05:14 +00:00
}
2021-06-19 16:48:54 +00:00
// Authorization is a section of Config that has fields related to
// authorization and authentication.
2021-03-06 09:40:47 +00:00
type Authorization struct {
2021-06-19 16:48:54 +00:00
UseFixedAuth bool
UseRegistration bool
LimitRegistration uint64 ` comment:"This field controls the maximum amount of allowed registrations." `
2021-03-06 09:40:47 +00:00
}
2021-06-19 16:48:54 +00:00
// ReadConfigFile reads a config on the given path and stores the
// configuration. Call it sometime during the initialization.
2021-06-19 17:00:28 +00:00
func ReadConfigFile ( path string ) error {
2021-03-06 09:40:47 +00:00
cfg := & Config {
2021-06-12 15:01:24 +00:00
WikiName : "Mycorrhiza Wiki" ,
2021-03-06 09:40:47 +00:00
NaviTitleIcon : "🍄" ,
Hyphae : Hyphae {
HomeHypha : "home" ,
UserHypha : "u" ,
HeaderLinksHypha : "" ,
} ,
Network : Network {
HTTPPort : 1737 ,
URL : "" ,
GeminiCertificatePath : "" ,
} ,
Authorization : Authorization {
2021-06-19 16:48:54 +00:00
UseFixedAuth : false ,
UseRegistration : false ,
LimitRegistration : 0 ,
2021-03-06 09:40:47 +00:00
} ,
2021-05-22 18:05:14 +00:00
CustomScripts : CustomScripts {
OmnipresentScripts : [ ] string { } ,
ViewScripts : [ ] string { } ,
EditScripts : [ ] string { } ,
} ,
2021-03-06 09:40:47 +00:00
}
2021-03-09 14:27:14 +00:00
2021-06-19 16:48:54 +00:00
dirty := false
f , err := ini . Load ( path )
if err != nil {
if errors . Is ( err , os . ErrNotExist ) {
f = ini . Empty ( )
dirty = true
} else {
2021-06-19 17:00:28 +00:00
return fmt . Errorf ( "Failed to open the config file: %w" , err )
2021-06-19 16:48:54 +00:00
}
}
// Map the config file to the config struct. It'll do nothing if the file
// doesn't exist or is empty.
f . MapTo ( cfg )
// Update the port if it's set externally and is different from what's in
// the config file
if HTTPPort != "" && HTTPPort != strconv . FormatUint ( cfg . Network . HTTPPort , 10 ) {
port , err := strconv . ParseUint ( HTTPPort , 10 , 64 )
2021-04-28 10:40:53 +00:00
if err != nil {
2021-06-19 17:00:28 +00:00
return fmt . Errorf ( "Failed to parse the port from command-line arguments: %w" , err )
2021-04-28 10:40:53 +00:00
}
2021-06-19 16:48:54 +00:00
cfg . Network . HTTPPort = port
dirty = true
}
// Save changes, if there are any
if dirty {
err = f . ReflectFrom ( cfg )
2021-03-09 14:27:14 +00:00
if err != nil {
2021-06-19 17:00:28 +00:00
return fmt . Errorf ( "Failed to serialize the config: %w" , err )
2021-06-19 16:48:54 +00:00
}
// Disable key-value auto-aligning, but retain spaces around '=' sign
ini . PrettyFormat = false
ini . PrettyEqual = true
if err = f . SaveTo ( path ) ; err != nil {
2021-06-19 17:00:28 +00:00
return fmt . Errorf ( "Failed to save the config file: %w" , err )
2021-03-09 14:27:14 +00:00
}
2021-03-06 09:40:47 +00:00
}
2021-04-12 14:26:49 +00:00
// Map the struct to the global variables
2021-05-09 09:36:39 +00:00
WikiName = cfg . WikiName
NaviTitleIcon = cfg . NaviTitleIcon
HomeHypha = cfg . HomeHypha
2021-03-06 09:40:47 +00:00
UserHypha = cfg . UserHypha
HeaderLinksHypha = cfg . HeaderLinksHypha
2021-05-09 09:36:39 +00:00
HTTPPort = strconv . FormatUint ( cfg . HTTPPort , 10 )
2021-03-06 09:40:47 +00:00
URL = cfg . URL
2021-05-09 09:36:39 +00:00
GeminiCertificatePath = cfg . GeminiCertificatePath
2021-03-06 09:40:47 +00:00
UseFixedAuth = cfg . UseFixedAuth
2021-04-12 14:26:49 +00:00
UseRegistration = cfg . UseRegistration
2021-04-19 16:39:25 +00:00
LimitRegistration = int ( cfg . LimitRegistration )
2021-05-22 18:05:14 +00:00
OmnipresentScripts = cfg . OmnipresentScripts
ViewScripts = cfg . ViewScripts
EditScripts = cfg . EditScripts
2021-05-11 08:33:00 +00:00
// This URL makes much more sense.
if URL == "" {
URL = "http://0.0.0.0:" + HTTPPort
}
2021-06-19 17:00:28 +00:00
return nil
2021-03-06 09:40:47 +00:00
}