@ -17,6 +17,7 @@ import (
"github.com/mitchellh/go-wordwrap"
"github.com/mitchellh/go-wordwrap"
"github.com/writeas/web-core/auth"
"github.com/writeas/web-core/auth"
"strconv"
"strconv"
"strings"
)
)
type SetupData struct {
type SetupData struct {
@ -24,7 +25,7 @@ type SetupData struct {
Config * Config
Config * Config
}
}
func Configure ( fname string , configSections [ ] string ) ( * SetupData , error ) {
func Configure ( fname string , configSections string ) ( * SetupData , error ) {
data := & SetupData { }
data := & SetupData { }
var err error
var err error
if fname == "" {
if fname == "" {
@ -52,9 +53,6 @@ func Configure(fname string, configSections []string) (*SetupData, error) {
fmt . Println ( wordwrap . WrapString ( " This quick configuration process will " + action + " the application's config file, " + fname + ".\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 ( wordwrap . WrapString ( " This quick configuration process will " + action + " the application's config file, " + fname + ".\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 ( )
fmt . Println ( )
title ( " Server setup " )
fmt . Println ( )
tmpls := & promptui . PromptTemplates {
tmpls := & promptui . PromptTemplates {
Success : "{{ . | bold | faint }}: " ,
Success : "{{ . | bold | faint }}: " ,
}
}
@ -78,284 +76,296 @@ func Configure(fname string, configSections []string) (*SetupData, error) {
data . Config . Server . Dev = isDevEnv
data . Config . Server . Dev = isDevEnv
var prompt promptui . Prompt
var prompt promptui . Prompt
if isDevEnv || ! isStandalone {
// Running in dev environment or behind reverse proxy; ask for port
if strings . Contains ( configSections , "server" ) {
prompt = promptui . Prompt {
Templates : tmpls ,
title ( " Server setup " )
Label : "Local port" ,
fmt . Println ( )
Validate : validatePort ,
Default : fmt . Sprintf ( "%d" , data . Config . Server . Port ) ,
if isDevEnv || ! isStandalone {
// Running in dev environment or behind reverse proxy; ask for port
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Local port" ,
Validate : validatePort ,
Default : fmt . Sprintf ( "%d" , data . Config . Server . Port ) ,
}
port , err := prompt . Run ( )
if err != nil {
return data , err
}
data . Config . Server . Port , _ = strconv . Atoi ( port ) // Ignore error, as we've already validated number
}
}
port , err := prompt . Run ( )
if err != nil {
if isStandalone {
return data , err
selPrompt = promptui . Select {
Templates : selTmpls ,
Label : "Web server mode" ,
Items : [ ] string { "Insecure (port 80)" , "Secure (port 443)" } ,
}
sel , _ , err := selPrompt . Run ( )
if err != nil {
return data , err
}
if sel == 0 {
data . Config . Server . Port = 80
data . Config . Server . TLSCertPath = ""
data . Config . Server . TLSKeyPath = ""
} else if sel == 1 {
data . Config . Server . Port = 443
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Certificate path" ,
Validate : validateNonEmpty ,
Default : data . Config . Server . TLSCertPath ,
}
data . Config . Server . TLSCertPath , err = prompt . Run ( )
if err != nil {
return data , err
}
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Key path" ,
Validate : validateNonEmpty ,
Default : data . Config . Server . TLSKeyPath ,
}
data . Config . Server . TLSKeyPath , err = prompt . Run ( )
if err != nil {
return data , err
}
}
} else {
data . Config . Server . TLSCertPath = ""
data . Config . Server . TLSKeyPath = ""
}
}
data . Config . Server . Port , _ = strconv . Atoi ( port ) // Ignore error, as we've already validated number
fmt . Println ( )
}
}
if strings . Contains ( configSections , "db" ) {
if isStandalone {
title ( " Database setup " )
fmt . Println ( )
selPrompt = promptui . Select {
selPrompt = promptui . Select {
Templates : selTmpls ,
Templates : selTmpls ,
Label : "Web server mode" ,
Label : "Database driver " ,
Items : [ ] string { "Insecure (port 80)" , "Secure (port 443)" } ,
Items : [ ] string { "MySQL" , "SQLite " } ,
}
}
sel , _ , err := selPrompt . Run ( )
sel , _ , err := selPrompt . Run ( )
if err != nil {
if err != nil {
return data , err
return data , err
}
}
if sel == 0 {
if sel == 0 {
data . Config . Server . Port = 80
// Configure for MySQL
data . Config . Server . TLSCertPath = ""
data . Config . UseMySQL ( isNewCfg )
data . Config . Server . TLSKeyPath = ""
} else if sel == 1 {
data . Config . Server . Port = 443
prompt = promptui . Prompt {
prompt = promptui . Prompt {
Templates : tmpls ,
Templates : tmpls ,
Label : "Certificate path" ,
Label : "Username" ,
Validate : validateNonEmpty ,
Validate : validateNonEmpty ,
Default : data . Config . Server . TLSCertPath ,
Default : data . Config . Database . User ,
}
}
data . Config . Server . TLSCertPath , err = prompt . Run ( )
data . Config . Database . User , err = prompt . Run ( )
if err != nil {
if err != nil {
return data , err
return data , err
}
}
prompt = promptui . Prompt {
prompt = promptui . Prompt {
Templates : tmpls ,
Templates : tmpls ,
Label : "Key path" ,
Label : "Password " ,
Validate : validateNonEmpty ,
Validate : validateNonEmpty ,
Default : data . Config . Server . TLSKeyPath ,
Default : data . Config . Database . Password ,
Mask : '*' ,
}
}
data . Config . Server . TLSKeyPath , err = prompt . Run ( )
data . Config . Database . Password , err = prompt . Run ( )
if err != nil {
return data , err
}
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Database name" ,
Validate : validateNonEmpty ,
Default : data . Config . Database . Database ,
}
data . Config . Database . Database , err = prompt . Run ( )
if err != nil {
return data , err
}
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Host" ,
Validate : validateNonEmpty ,
Default : data . Config . Database . Host ,
}
data . Config . Database . Host , err = prompt . Run ( )
if err != nil {
return data , err
}
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Port" ,
Validate : validatePort ,
Default : fmt . Sprintf ( "%d" , data . Config . Database . Port ) ,
}
dbPort , err := prompt . Run ( )
if err != nil {
return data , err
}
data . Config . Database . Port , _ = strconv . Atoi ( dbPort ) // Ignore error, as we've already validated number
} else if sel == 1 {
// Configure for SQLite
data . Config . UseSQLite ( isNewCfg )
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Filename" ,
Validate : validateNonEmpty ,
Default : data . Config . Database . FileName ,
}
data . Config . Database . FileName , err = prompt . Run ( )
if err != nil {
if err != nil {
return data , err
return data , err
}
}
}
}
} else {
data . Config . Server . TLSCertPath = ""
fmt . Println ( )
data . Config . Server . TLSKeyPath = ""
}
fmt . Println ( )
title ( " Database setup " )
fmt . Println ( )
selPrompt = promptui . Select {
Templates : selTmpls ,
Label : "Database driver" ,
Items : [ ] string { "MySQL" , "SQLite" } ,
}
sel , _ , err := selPrompt . Run ( )
if err != nil {
return data , err
}
}
if strings . Contains ( configSections , "app" ) {
if sel == 0 {
title ( " App setup " )
// Configure for MySQL
fmt . Println ( )
data . Config . UseMySQL ( isNewCfg )
selPrompt = promptui . Select {
prompt = promptui . Prompt {
Templates : selTmpls ,
Templates : tmpls ,
Label : "Site type" ,
Label : "Username" ,
Items : [ ] string { "Single user blog" , "Multi-user instance" } ,
Validate : validateNonEmpty ,
Default : data . Config . Database . User ,
}
data . Config . Database . User , err = prompt . Run ( )
if err != nil {
return data , err
}
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Password" ,
Validate : validateNonEmpty ,
Default : data . Config . Database . Password ,
Mask : '*' ,
}
data . Config . Database . Password , err = prompt . Run ( )
if err != nil {
return data , err
}
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Database name" ,
Validate : validateNonEmpty ,
Default : data . Config . Database . Database ,
}
data . Config . Database . Database , err = prompt . Run ( )
if err != nil {
return data , err
}
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Host" ,
Validate : validateNonEmpty ,
Default : data . Config . Database . Host ,
}
data . Config . Database . Host , err = prompt . Run ( )
if err != nil {
return data , err
}
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Port" ,
Validate : validatePort ,
Default : fmt . Sprintf ( "%d" , data . Config . Database . Port ) ,
}
}
dbPort , err := p rompt. Run ( )
_ , usersType , err := selPrompt . Run ( )
if err != nil {
if err != nil {
return data , err
return data , err
}
}
data . Config . Database . Port , _ = strconv . Atoi ( dbPort ) // Ignore error, as we've already validated number
data . Config . App . SingleUser = usersType == "Single user blog"
} else if sel == 1 {
// Configure for SQLite
if data . Config . App . SingleUser {
data . Config . UseSQLite ( isNewCfg )
data . User = & UserCreation { }
prompt = promptui . Prompt {
// prompt for username
Templates : tmpls ,
prompt = promptui . Prompt {
Label : "Filename" ,
Templates : tmpls ,
Validate : validateNonEmpty ,
Label : "Admin username" ,
Default : data . Config . Database . FileName ,
Validate : validateNonEmpty ,
}
data . User . Username , err = prompt . Run ( )
if err != nil {
return data , err
}
// prompt for password
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Admin password" ,
Validate : validateNonEmpty ,
}
newUserPass , err := prompt . Run ( )
if err != nil {
return data , err
}
data . User . HashedPass , err = auth . HashPass ( [ ] byte ( newUserPass ) )
if err != nil {
return data , err
}
}
}
data . Config . Database . FileName , err = prompt . Run ( )
if err != nil {
siteNameLabel := "Instance name"
return data , err
if data . Config . App . SingleUser {
siteNameLabel = "Blog name"
}
}
}
fmt . Println ( )
title ( " App setup " )
fmt . Println ( )
selPrompt = promptui . Select {
Templates : selTmpls ,
Label : "Site type" ,
Items : [ ] string { "Single user blog" , "Multi-user instance" } ,
}
_ , usersType , err := selPrompt . Run ( )
if err != nil {
return data , err
}
data . Config . App . SingleUser = usersType == "Single user blog"
if data . Config . App . SingleUser {
data . User = & UserCreation { }
// prompt for username
prompt = promptui . Prompt {
prompt = promptui . Prompt {
Templates : tmpls ,
Templates : tmpls ,
Label : "Admin username" ,
Label : siteNameLabel ,
Validate : validateNonEmpty ,
Validate : validateNonEmpty ,
Default : data . Config . App . SiteName ,
}
}
data . User . Usern ame, err = prompt . Run ( )
data . Config . App . SiteName , err = prompt . Run ( )
if err != nil {
if err != nil {
return data , err
return data , err
}
}
// prompt for password
prompt = promptui . Prompt {
prompt = promptui . Prompt {
Templates : tmpls ,
Templates : tmpls ,
Label : "Admin password" ,
Label : "Public URL" ,
Validate : validateNonEmpty ,
Validate : validateDomain ,
Default : data . Config . App . Host ,
}
}
newUserPass , err : = prompt . Run ( )
data . Config . App . Host , err = prompt . Run ( )
if err != nil {
if err != nil {
return data , err
return data , err
}
}
data . User . HashedPass , err = auth . HashPass ( [ ] byte ( newUserPass ) )
if ! data . Config . App . SingleUser {
if err != nil {
selPrompt = promptui . Select {
return data , err
Templates : selTmpls ,
}
Label : "Registration" ,
}
Items : [ ] string { "Open" , "Closed" } ,
}
siteNameLabel := "Instance name"
_ , regType , err := selPrompt . Run ( )
if data . Config . App . SingleUser {
if err != nil {
siteNameLabel = "Blog name"
return data , err
}
}
prompt = promptui . Prompt {
data . Config . App . OpenRegistration = regType == "Open"
Templates : tmpls ,
Label : siteNameLabel ,
prompt = promptui . Prompt {
Validate : validateNonEmpty ,
Templates : tmpls ,
Default : data . Config . App . SiteName ,
Label : "Max blogs per user" ,
}
Default : fmt . Sprintf ( "%d" , data . Config . App . MaxBlogs ) ,
data . Config . App . SiteName , err = prompt . Run ( )
}
if err != nil {
maxBlogs , err := prompt . Run ( )
return data , err
if err != nil {
}
return data , err
}
prompt = promptui . Prompt {
data . Config . App . MaxBlogs , _ = strconv . Atoi ( maxBlogs ) // Ignore error, as we've already validated number
Templates : tmpls ,
Label : "Public URL" ,
Validate : validateDomain ,
Default : data . Config . App . Host ,
}
data . Config . App . Host , err = prompt . Run ( )
if err != nil {
return data , err
}
if ! data . Config . App . SingleUser {
selPrompt = promptui . Select {
Templates : selTmpls ,
Label : "Registration" ,
Items : [ ] string { "Open" , "Closed" } ,
}
_ , regType , err := selPrompt . Run ( )
if err != nil {
return data , err
}
data . Config . App . OpenRegistration = regType == "Open"
prompt = promptui . Prompt {
Templates : tmpls ,
Label : "Max blogs per user" ,
Default : fmt . Sprintf ( "%d" , data . Config . App . MaxBlogs ) ,
}
maxBlogs , err := prompt . Run ( )
if err != nil {
return data , err
}
}
data . Config . App . MaxBlogs , _ = strconv . Atoi ( maxBlogs ) // Ignore error, as we've already validated number
}
selPrompt = promptui . Select {
Templates : selTmpls ,
Label : "Federation" ,
Items : [ ] string { "Enabled" , "Disabled" } ,
}
_ , fedType , err := selPrompt . Run ( )
if err != nil {
return data , err
}
data . Config . App . Federation = fedType == "Enabled"
if data . Config . App . Federation {
selPrompt = promptui . Select {
selPrompt = promptui . Select {
Templates : selTmpls ,
Templates : selTmpls ,
Label : "Federation usage stats " ,
Label : "Federation" ,
Items : [ ] string { "Public" , "Private " } ,
Items : [ ] string { "Enabled" , "Disabled" } ,
}
}
_ , fedStats Type , err := selPrompt . Run ( )
_ , fedType , err := selPrompt . Run ( )
if err != nil {
if err != nil {
return data , err
return data , err
}
}
data . Config . App . PublicStats = fedStatsType == "Public"
data . Config . App . Federation = fedType == "Enabled"
selPrompt = promptui . Select {
if data . Config . App . Federation {
Templates : selTmpls ,
selPrompt = promptui . Select {
Label : "Instance metadata privacy" ,
Templates : selTmpls ,
Items : [ ] string { "Public" , "Private" } ,
Label : "Federation usage stats" ,
}
Items : [ ] string { "Public" , "Private" } ,
_ , fedStatsType , err = selPrompt . Run ( )
}
if err != nil {
_ , fedStatsType , err := selPrompt . Run ( )
return data , err
if err != nil {
return data , err
}
data . Config . App . PublicStats = fedStatsType == "Public"
selPrompt = promptui . Select {
Templates : selTmpls ,
Label : "Instance metadata privacy" ,
Items : [ ] string { "Public" , "Private" } ,
}
_ , fedStatsType , err = selPrompt . Run ( )
if err != nil {
return data , err
}
data . Config . App . Private = fedStatsType == "Private"
}
}
data . Config . App . Private = fedStatsType == "Private"
}
}
return data , Save ( data . Config , fname )
return data , Save ( data . Config , fname )