Page MenuHomeMusing Studio

No OneTemporary

diff --git a/config/config.go b/config/config.go
index ea8754f..d59543a 100644
--- a/config/config.go
+++ b/config/config.go
@@ -1,97 +1,99 @@
package config
import (
"gopkg.in/ini.v1"
)
const (
FileName = "config.ini"
)
type (
ServerCfg struct {
Port int `ini:"port"`
}
DatabaseCfg struct {
Type string `ini:"type"`
User string `ini:"username"`
Password string `ini:"password"`
Database string `ini:"database"`
Host string `ini:"host"`
Port int `ini:"port"`
}
AppCfg struct {
SiteName string `ini:"site_name"`
Host string `ini:"host"`
// Site appearance
Theme string `ini:"theme"`
JSDisabled bool `ini:"disable_js"`
WebFonts bool `ini:"webfonts"`
// Users
SingleUser bool `ini:"single_user"`
OpenRegistration bool `ini:"open_registration"`
MinUsernameLen int `ini:"min_username_len"`
+ MaxBlogs int `ini:"max_blogs"`
// Federation
Federation bool `ini:"federation"`
PublicStats bool `ini:"public_stats"`
Private bool `ini:"private"`
}
Config struct {
Server ServerCfg `ini:"server"`
Database DatabaseCfg `ini:"database"`
App AppCfg `ini:"app"`
}
)
func New() *Config {
return &Config{
Server: ServerCfg{
Port: 8080,
},
Database: DatabaseCfg{
Type: "mysql",
Host: "localhost",
Port: 3306,
},
App: AppCfg{
Host: "http://localhost:8080",
Theme: "write",
WebFonts: true,
SingleUser: true,
MinUsernameLen: 3,
+ MaxBlogs: 1,
Federation: true,
PublicStats: true,
},
}
}
func Load() (*Config, error) {
cfg, err := ini.Load(FileName)
if err != nil {
return nil, err
}
// Parse INI file
uc := &Config{}
err = cfg.MapTo(uc)
if err != nil {
return nil, err
}
return uc, nil
}
func Save(uc *Config) error {
cfg := ini.Empty()
err := ini.ReflectFrom(cfg, uc)
if err != nil {
return err
}
return cfg.SaveTo(FileName)
}
diff --git a/config/funcs.go b/config/funcs.go
new file mode 100644
index 0000000..2fc130a
--- /dev/null
+++ b/config/funcs.go
@@ -0,0 +1,17 @@
+package config
+
+import (
+ "strings"
+)
+
+// FriendlyHost returns the app's Host sans any schema
+func (ac AppCfg) FriendlyHost() string {
+ return ac.Host[strings.Index(ac.Host, "://")+len("://"):]
+}
+
+func (ac AppCfg) CanCreateBlogs(currentlyUsed uint64) bool {
+ if ac.MaxBlogs <= 0 {
+ return true
+ }
+ return int(currentlyUsed) < ac.MaxBlogs
+}
diff --git a/config/setup.go b/config/setup.go
index 5ba2053..a89a148 100644
--- a/config/setup.go
+++ b/config/setup.go
@@ -1,181 +1,216 @@
package config
import (
"fmt"
"github.com/fatih/color"
"github.com/manifoldco/promptui"
"github.com/mitchellh/go-wordwrap"
"strconv"
)
func Configure() error {
c, err := Load()
if err != nil {
fmt.Println("No configuration yet. Creating new.")
c = New()
} else {
fmt.Println("Configuration loaded.")
}
title := color.New(color.Bold, color.BgGreen).PrintlnFunc()
intro := color.New(color.Bold, color.FgWhite).PrintlnFunc()
fmt.Println()
intro(" ✍ Write Freely Configuration ✍")
fmt.Println()
fmt.Println(wordwrap.WrapString(" This quick configuration process will generate the application's config file, "+FileName+".\n\n It validates your input along the way, so you can be sure any future errors aren't caused by a bad configuration. If you'd rather configure your server manually, instead run: writefreely --create-config and edit that file.", 75))
fmt.Println()
title(" Server setup ")
fmt.Println()
- prompt := promptui.Prompt{
- Label: "Local port",
- Validate: validatePort,
- Default: fmt.Sprintf("%d", c.Server.Port),
+ tmpls := &promptui.PromptTemplates{
+ Success: "{{ . | bold | faint }}: ",
}
- port, err := prompt.Run()
- if err != nil {
- return err
+ selTmpls := &promptui.SelectTemplates{
+ Selected: fmt.Sprintf(`{{.Label}} {{ . | faint }}`, promptui.IconGood),
}
- c.Server.Port, _ = strconv.Atoi(port) // Ignore error, as we've already validated number
- prompt = promptui.Prompt{
- Label: "Public-facing host",
- Validate: validateDomain,
- Default: c.App.Host,
+ prompt := promptui.Prompt{
+ Templates: tmpls,
+ Label: "Local port",
+ Validate: validatePort,
+ Default: fmt.Sprintf("%d", c.Server.Port),
}
- c.App.Host, err = prompt.Run()
+ port, err := prompt.Run()
if err != nil {
return err
}
+ c.Server.Port, _ = strconv.Atoi(port) // Ignore error, as we've already validated number
fmt.Println()
title(" Database setup ")
fmt.Println()
prompt = promptui.Prompt{
- Label: "Username",
- Validate: validateNonEmpty,
- Default: c.Database.User,
+ Templates: tmpls,
+ Label: "Username",
+ Validate: validateNonEmpty,
+ Default: c.Database.User,
}
c.Database.User, err = prompt.Run()
if err != nil {
return err
}
prompt = promptui.Prompt{
- Label: "Password",
- Validate: validateNonEmpty,
- Default: c.Database.Password,
- Mask: '*',
+ Templates: tmpls,
+ Label: "Password",
+ Validate: validateNonEmpty,
+ Default: c.Database.Password,
+ Mask: '*',
}
c.Database.Password, err = prompt.Run()
if err != nil {
return err
}
prompt = promptui.Prompt{
- Label: "Database name",
- Validate: validateNonEmpty,
- Default: c.Database.Database,
+ Templates: tmpls,
+ Label: "Database name",
+ Validate: validateNonEmpty,
+ Default: c.Database.Database,
}
c.Database.Database, err = prompt.Run()
if err != nil {
return err
}
prompt = promptui.Prompt{
- Label: "Host",
- Validate: validateNonEmpty,
- Default: c.Database.Host,
+ Templates: tmpls,
+ Label: "Host",
+ Validate: validateNonEmpty,
+ Default: c.Database.Host,
}
c.Database.Host, err = prompt.Run()
if err != nil {
return err
}
prompt = promptui.Prompt{
- Label: "Port",
- Validate: validatePort,
- Default: fmt.Sprintf("%d", c.Database.Port),
+ Templates: tmpls,
+ Label: "Port",
+ Validate: validatePort,
+ Default: fmt.Sprintf("%d", c.Database.Port),
}
dbPort, err := prompt.Run()
if err != nil {
return err
}
c.Database.Port, _ = strconv.Atoi(dbPort) // Ignore error, as we've already validated number
fmt.Println()
title(" App setup ")
fmt.Println()
selPrompt := promptui.Select{
- Label: "Site type",
- Items: []string{"Single user", "Multiple users"},
+ Templates: selTmpls,
+ Label: "Site type",
+ Items: []string{"Single user blog", "Multi-user instance"},
}
_, usersType, err := selPrompt.Run()
if err != nil {
return err
}
c.App.SingleUser = usersType == "Single user"
+ // TODO: if c.App.SingleUser {
+ // prompt for username
+ // prompt for password
+ // create blog
siteNameLabel := "Instance name"
if c.App.SingleUser {
siteNameLabel = "Blog name"
}
prompt = promptui.Prompt{
- Label: siteNameLabel,
- Validate: validateNonEmpty,
- Default: c.App.SiteName,
+ Templates: tmpls,
+ Label: siteNameLabel,
+ Validate: validateNonEmpty,
+ Default: c.App.SiteName,
}
c.App.SiteName, err = prompt.Run()
if err != nil {
return err
}
+ prompt = promptui.Prompt{
+ Templates: tmpls,
+ Label: "Public URL",
+ Validate: validateDomain,
+ Default: c.App.Host,
+ }
+ c.App.Host, err = prompt.Run()
+ if err != nil {
+ return err
+ }
+
if !c.App.SingleUser {
selPrompt = promptui.Select{
- Label: "Registration",
- Items: []string{"Open", "Closed"},
+ Templates: selTmpls,
+ Label: "Registration",
+ Items: []string{"Open", "Closed"},
}
_, regType, err := selPrompt.Run()
if err != nil {
return err
}
c.App.OpenRegistration = regType == "Open"
+
+ prompt = promptui.Prompt{
+ Templates: tmpls,
+ Label: "Max blogs per user",
+ Default: fmt.Sprintf("%d", c.App.MaxBlogs),
+ }
+ maxBlogs, err := prompt.Run()
+ if err != nil {
+ return err
+ }
+ c.App.MaxBlogs, _ = strconv.Atoi(maxBlogs) // Ignore error, as we've already validated number
}
selPrompt = promptui.Select{
- Label: "Federation",
- Items: []string{"Enabled", "Disabled"},
+ Templates: selTmpls,
+ Label: "Federation",
+ Items: []string{"Enabled", "Disabled"},
}
_, fedType, err := selPrompt.Run()
if err != nil {
return err
}
c.App.Federation = fedType == "Enabled"
if c.App.Federation {
selPrompt = promptui.Select{
- Label: "Federation usage stats",
- Items: []string{"Public", "Private"},
+ Templates: selTmpls,
+ Label: "Federation usage stats",
+ Items: []string{"Public", "Private"},
}
_, fedStatsType, err := selPrompt.Run()
if err != nil {
return err
}
c.App.PublicStats = fedStatsType == "Public"
selPrompt = promptui.Select{
- Label: "Instance metadata privacy",
- Items: []string{"Public", "Private"},
+ Templates: selTmpls,
+ Label: "Instance metadata privacy",
+ Items: []string{"Public", "Private"},
}
_, fedStatsType, err = selPrompt.Run()
if err != nil {
return err
}
c.App.Private = fedStatsType == "Private"
}
return Save(c)
}

File Metadata

Mime Type
text/x-diff
Expires
Thu, Oct 9, 10:36 PM (20 h, 20 m)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
3440868

Event Timeline