2017-09-03 04:50:31 +00:00
/ *
*
* Gosora Installer
* Copyright Azareal 2017 - 2018
*
* /
2017-01-10 06:51:28 +00:00
package main
2017-06-06 08:47:33 +00:00
import (
"bufio"
"database/sql"
2017-09-03 04:50:31 +00:00
"fmt"
"os"
2017-07-12 11:05:18 +00:00
"runtime/debug"
2017-09-03 04:50:31 +00:00
"strconv"
2017-07-12 11:05:18 +00:00
"../query_gen/lib"
2017-06-06 08:47:33 +00:00
)
2017-01-10 06:51:28 +00:00
2017-07-12 11:05:18 +00:00
const saltLength int = 32
2017-09-03 04:50:31 +00:00
2017-07-12 11:05:18 +00:00
var db * sql . DB
2017-01-10 06:51:28 +00:00
var scanner * bufio . Scanner
2017-07-12 11:05:18 +00:00
2017-09-03 04:50:31 +00:00
var dbAdapter = "mysql"
var dbHost string
var dbUsername string
var dbPassword string
var dbName string
var dbPort string
var siteName , siteURL , serverPort string
var defaultAdapter = "mysql"
var defaultHost = "localhost"
var defaultUsername = "root"
var defaultDbname = "gosora"
var defaultSiteName = "Site Name"
var defaultsiteURL = "localhost"
var defaultServerPort = "80" // 8080's a good one, if you're testing and don't want it to clash with port 80
// func() error, removing type to satisfy lint
var initDatabase = _initMysql
var tableDefs = _tableDefsMysql
var initialData = _initialDataMysql
2017-07-12 11:05:18 +00:00
2017-01-10 06:51:28 +00:00
func main ( ) {
2017-07-12 11:05:18 +00:00
// Capture panics rather than immediately closing the window on Windows
defer func ( ) {
r := recover ( )
if r != nil {
fmt . Println ( r )
debug . PrintStack ( )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-07-12 11:05:18 +00:00
return
}
} ( )
2017-09-03 04:50:31 +00:00
2017-01-10 06:51:28 +00:00
scanner = bufio . NewScanner ( os . Stdin )
fmt . Println ( "Welcome to Gosora's Installer" )
fmt . Println ( "We're going to take you through a few steps to help you get started :)" )
2017-09-03 04:50:31 +00:00
if ! getDatabaseDetails ( ) {
2017-01-10 06:51:28 +00:00
err := scanner . Err ( )
if err != nil {
fmt . Println ( err )
} else {
fmt . Println ( "Something went wrong!" )
}
fmt . Println ( "Aborting installation..." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-01-10 06:51:28 +00:00
return
}
2017-06-06 08:47:33 +00:00
2017-09-03 04:50:31 +00:00
if ! getSiteDetails ( ) {
2017-01-10 06:51:28 +00:00
err := scanner . Err ( )
if err != nil {
fmt . Println ( err )
} else {
fmt . Println ( "Something went wrong!" )
}
fmt . Println ( "Aborting installation..." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-01-10 06:51:28 +00:00
return
}
2017-09-03 04:50:31 +00:00
err := initDatabase ( )
2017-01-10 06:51:28 +00:00
if err != nil {
fmt . Println ( err )
fmt . Println ( "Aborting installation..." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-01-10 06:51:28 +00:00
return
}
2017-09-03 04:50:31 +00:00
err = tableDefs ( )
2017-01-10 06:51:28 +00:00
if err != nil {
fmt . Println ( err )
fmt . Println ( "Aborting installation..." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-01-10 06:51:28 +00:00
return
}
2017-09-03 04:50:31 +00:00
hashedPassword , salt , err := BcryptGeneratePassword ( "password" )
2017-01-10 06:51:28 +00:00
if err != nil {
fmt . Println ( err )
fmt . Println ( "Aborting installation..." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-01-10 06:51:28 +00:00
return
}
2017-09-03 04:50:31 +00:00
2017-07-12 11:05:18 +00:00
// Build the admin user query
2017-09-03 04:50:31 +00:00
adminUserStmt , err := qgen . Builder . SimpleInsert ( "users" , "name, password, salt, email, group, is_super_admin, active, createdAt, lastActiveAt, message, last_ip" , "'Admin',?,?,'admin@localhost',1,1,1,UTC_TIMESTAMP(),UTC_TIMESTAMP(),'','127.0.0.1'" )
2017-07-12 11:05:18 +00:00
if err != nil {
2017-01-10 06:51:28 +00:00
fmt . Println ( err )
fmt . Println ( "Aborting installation..." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-01-10 06:51:28 +00:00
return
}
2017-09-03 04:50:31 +00:00
2017-07-12 11:05:18 +00:00
// Run the admin user query
2017-09-03 04:50:31 +00:00
_ , err = adminUserStmt . Exec ( hashedPassword , salt )
2017-07-12 11:05:18 +00:00
if err != nil {
fmt . Println ( err )
fmt . Println ( "Aborting installation..." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-07-12 11:05:18 +00:00
return
2017-01-10 06:51:28 +00:00
}
2017-09-03 04:50:31 +00:00
err = initialData ( )
2017-01-10 06:51:28 +00:00
if err != nil {
fmt . Println ( err )
fmt . Println ( "Aborting installation..." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-01-10 06:51:28 +00:00
return
}
2017-09-03 04:50:31 +00:00
if dbAdapter == "mysql" {
err = _mysqlSeedDatabase ( )
2017-01-10 06:51:28 +00:00
if err != nil {
fmt . Println ( err )
fmt . Println ( "Aborting installation..." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-01-10 06:51:28 +00:00
return
}
}
2017-09-03 04:50:31 +00:00
2017-01-10 06:51:28 +00:00
configContents := [ ] byte ( ` package main
2017-07-17 10:23:42 +00:00
func init ( ) {
2017-05-07 08:31:41 +00:00
// Site Info
2017-09-13 15:09:13 +00:00
site . Name = "` + siteName + `"
site . Email = ""
site . URL = "` + siteURL + `"
2017-09-03 04:50:31 +00:00
site . Port = "` + serverPort + `"
2017-07-17 10:23:42 +00:00
site . EnableSsl = false
site . EnableEmails = false
2017-08-15 13:47:56 +00:00
site . HasProxy = false // Cloudflare counts as this, if it's sitting in the middle
2017-07-17 10:23:42 +00:00
config . SslPrivkey = ""
config . SslFullchain = ""
2017-09-13 15:09:13 +00:00
site . Language = "english"
2017-05-07 08:31:41 +00:00
2017-01-10 06:51:28 +00:00
// Database details
2017-09-13 15:09:13 +00:00
dbConfig . Host = "` + dbHost + `"
dbConfig . Username = "` + dbUsername + `"
dbConfig . Password = "` + dbPassword + `"
dbConfig . Dbname = "` + dbName + `"
dbConfig . Port = "` + dbPort + `" // You probably won't need to change this
2017-01-10 06:51:28 +00:00
// Limiters
2017-07-17 10:23:42 +00:00
config . MaxRequestSize = 5 * megabyte
2017-01-10 06:51:28 +00:00
2017-05-07 08:31:41 +00:00
// Caching
2017-07-17 10:23:42 +00:00
config . CacheTopicUser = CACHE_STATIC
2017-08-06 15:22:18 +00:00
config . UserCacheCapacity = 120 // The max number of users held in memory
config . TopicCacheCapacity = 200 // The max number of topics held in memory
2017-03-15 08:34:14 +00:00
2017-05-07 08:31:41 +00:00
// Email
2017-09-18 17:03:52 +00:00
config . SMTPServer = ""
config . SMTPUsername = ""
config . SMTPPassword = ""
config . SMTPPort = "25"
2017-05-07 08:31:41 +00:00
// Misc
2017-09-11 10:24:03 +00:00
config . DefaultRoute = routeTopics
2017-07-17 10:23:42 +00:00
config . DefaultGroup = 3 // Should be a setting in the database
config . ActivationGroup = 5 // Should be a setting in the database
2017-09-18 17:03:52 +00:00
config . StaffCSS = "staff_post"
2017-09-23 19:57:13 +00:00
config . DefaultForum = 2
2017-07-17 10:23:42 +00:00
config . MinifyTemplates = true
config . MultiServer = false // Experimental: Enable Cross-Server Synchronisation and several other features
//config.Noavatar = "https://api.adorable.io/avatars/{width}/{id}@{site_url}.png"
config . Noavatar = "https://api.adorable.io/avatars/285/{id}@{site_url}.png"
config . ItemsPerPage = 25
2017-01-10 06:51:28 +00:00
// Developer flag
2017-07-17 10:23:42 +00:00
dev . DebugMode = true
//dev.SuperDebug = true
2017-09-23 21:28:50 +00:00
//dev.TemplateDebug = true
2017-07-17 10:23:42 +00:00
//dev.Profiling = true
}
2017-01-10 06:51:28 +00:00
` )
2017-06-06 08:47:33 +00:00
2017-01-10 06:51:28 +00:00
fmt . Println ( "Opening the configuration file" )
configFile , err := os . Create ( "./config.go" )
if err != nil {
fmt . Println ( err )
fmt . Println ( "Aborting installation..." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-01-10 06:51:28 +00:00
return
}
2017-06-06 08:47:33 +00:00
2017-01-10 06:51:28 +00:00
fmt . Println ( "Writing to the configuration file..." )
_ , err = configFile . Write ( configContents )
if err != nil {
fmt . Println ( err )
fmt . Println ( "Aborting installation..." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-01-10 06:51:28 +00:00
return
}
2017-06-06 08:47:33 +00:00
2017-01-10 06:51:28 +00:00
configFile . Sync ( )
configFile . Close ( )
fmt . Println ( "Finished writing to the configuration file" )
2017-06-06 08:47:33 +00:00
2017-01-10 06:51:28 +00:00
fmt . Println ( "Yay, you have successfully installed Gosora!" )
fmt . Println ( "Your name is Admin and you can login with the password 'password'. Don't forget to change it! Seriously. It's really insecure." )
2017-09-03 04:50:31 +00:00
pressAnyKey ( )
2017-01-10 06:51:28 +00:00
}
2017-09-03 04:50:31 +00:00
func getDatabaseDetails ( ) bool {
2017-07-12 11:05:18 +00:00
fmt . Println ( "Which database driver do you wish to use? mysql, mysql, or mysql? Default: mysql" )
if ! scanner . Scan ( ) {
return false
}
2017-09-03 04:50:31 +00:00
dbAdapter = scanner . Text ( )
if dbAdapter == "" {
dbAdapter = defaultAdapter
2017-07-12 11:05:18 +00:00
}
2017-09-03 04:50:31 +00:00
dbAdapter = setDBAdapter ( dbAdapter )
fmt . Println ( "Set database adapter to " + dbAdapter )
fmt . Println ( "Database Host? Default: " + defaultHost )
2017-01-10 06:51:28 +00:00
if ! scanner . Scan ( ) {
return false
}
2017-09-03 04:50:31 +00:00
dbHost = scanner . Text ( )
if dbHost == "" {
dbHost = defaultHost
2017-01-10 06:51:28 +00:00
}
2017-09-03 04:50:31 +00:00
fmt . Println ( "Set database host to " + dbHost )
2017-06-06 08:47:33 +00:00
2017-09-03 04:50:31 +00:00
fmt . Println ( "Database Username? Default: " + defaultUsername )
2017-01-10 06:51:28 +00:00
if ! scanner . Scan ( ) {
return false
}
2017-09-03 04:50:31 +00:00
dbUsername = scanner . Text ( )
if dbUsername == "" {
dbUsername = defaultUsername
2017-01-10 06:51:28 +00:00
}
2017-09-03 04:50:31 +00:00
fmt . Println ( "Set database username to " + dbUsername )
2017-06-06 08:47:33 +00:00
2017-01-10 06:51:28 +00:00
fmt . Println ( "Database Password? Default: ''" )
if ! scanner . Scan ( ) {
return false
}
2017-09-03 04:50:31 +00:00
dbPassword = scanner . Text ( )
if len ( dbPassword ) == 0 {
fmt . Println ( "You didn't set a password for this user. This won't block the installation process, but it might create security issues in the future." )
fmt . Println ( "" )
2017-01-10 06:51:28 +00:00
} else {
2017-09-03 04:50:31 +00:00
fmt . Println ( "Set password to " + obfuscatePassword ( dbPassword ) )
2017-01-10 06:51:28 +00:00
}
2017-06-06 08:47:33 +00:00
2017-09-03 04:50:31 +00:00
fmt . Println ( "Database Name? Pick a name you like or one provided to you. Default: " + defaultDbname )
2017-01-10 06:51:28 +00:00
if ! scanner . Scan ( ) {
return false
}
2017-09-03 04:50:31 +00:00
dbName = scanner . Text ( )
if dbName == "" {
dbName = defaultDbname
2017-01-10 06:51:28 +00:00
}
2017-09-03 04:50:31 +00:00
fmt . Println ( "Set database name to " + dbName )
2017-01-10 06:51:28 +00:00
return true
}
2017-09-03 04:50:31 +00:00
func getSiteDetails ( ) bool {
2017-01-10 06:51:28 +00:00
fmt . Println ( "Okay. We also need to know some actual information about your site!" )
2017-09-03 04:50:31 +00:00
fmt . Println ( "What's your site's name? Default: " + defaultSiteName )
2017-01-10 06:51:28 +00:00
if ! scanner . Scan ( ) {
return false
}
2017-09-03 04:50:31 +00:00
siteName = scanner . Text ( )
if siteName == "" {
siteName = defaultSiteName
2017-01-10 06:51:28 +00:00
}
2017-09-03 04:50:31 +00:00
fmt . Println ( "Set the site name to " + siteName )
2017-06-06 08:47:33 +00:00
2017-09-03 04:50:31 +00:00
fmt . Println ( "What's your site's url? Default: " + defaultsiteURL )
2017-01-10 06:51:28 +00:00
if ! scanner . Scan ( ) {
return false
}
2017-09-03 04:50:31 +00:00
siteURL = scanner . Text ( )
if siteURL == "" {
siteURL = defaultsiteURL
2017-01-10 06:51:28 +00:00
}
2017-09-03 04:50:31 +00:00
fmt . Println ( "Set the site url to " + siteURL )
2017-06-06 08:47:33 +00:00
2017-09-03 04:50:31 +00:00
fmt . Println ( "What port do you want the server to listen on? If you don't know what this means, you should probably leave it on the default. Default: " + defaultServerPort )
2017-01-10 06:51:28 +00:00
if ! scanner . Scan ( ) {
return false
}
2017-09-03 04:50:31 +00:00
serverPort = scanner . Text ( )
if serverPort == "" {
serverPort = defaultServerPort
2017-01-10 06:51:28 +00:00
}
2017-09-03 04:50:31 +00:00
_ , err := strconv . Atoi ( serverPort )
2017-01-12 02:55:08 +00:00
if err != nil {
fmt . Println ( "That's not a valid number!" )
return false
}
2017-09-03 04:50:31 +00:00
fmt . Println ( "Set the server port to " + serverPort )
2017-01-10 06:51:28 +00:00
return true
}
2017-09-03 04:50:31 +00:00
func setDBAdapter ( name string ) string {
switch name {
//case "wip-pgsql":
// set_pgsql_adapter()
// return "wip-pgsql"
2017-07-12 11:05:18 +00:00
}
2017-09-03 04:50:31 +00:00
_setMysqlAdapter ( )
2017-07-12 11:05:18 +00:00
return "mysql"
}
2017-09-03 04:50:31 +00:00
func obfuscatePassword ( password string ) ( out string ) {
2017-01-10 06:51:28 +00:00
for i := 0 ; i < len ( password ) ; i ++ {
out += "*"
}
return out
}
2017-09-03 04:50:31 +00:00
func pressAnyKey ( ) {
2017-01-10 06:51:28 +00:00
//fmt.Println("Press any key to exit...")
fmt . Println ( "Please press enter to exit..." )
for scanner . Scan ( ) {
_ = scanner . Text ( )
return
}
2017-06-06 08:47:33 +00:00
}