|
|
|
@ -1,5 +1,5 @@ |
|
|
|
|
/* |
|
|
|
|
* Copyright © 2018-2019 A Bunch Tell LLC. |
|
|
|
|
* Copyright © 2018-2020 A Bunch Tell LLC. |
|
|
|
|
* |
|
|
|
|
* This file is part of WriteFreely. |
|
|
|
|
* |
|
|
|
@ -11,122 +11,157 @@ |
|
|
|
|
package main |
|
|
|
|
|
|
|
|
|
import ( |
|
|
|
|
"flag" |
|
|
|
|
"fmt" |
|
|
|
|
"os" |
|
|
|
|
"strings" |
|
|
|
|
|
|
|
|
|
"github.com/gorilla/mux" |
|
|
|
|
"github.com/writeas/web-core/log" |
|
|
|
|
"github.com/writeas/writefreely" |
|
|
|
|
|
|
|
|
|
"github.com/gorilla/mux" |
|
|
|
|
"github.com/urfave/cli/v2" |
|
|
|
|
) |
|
|
|
|
|
|
|
|
|
func main() { |
|
|
|
|
// General options usable with other commands
|
|
|
|
|
debugPtr := flag.Bool("debug", false, "Enables debug logging.") |
|
|
|
|
configFile := flag.String("c", "config.ini", "The configuration file to use") |
|
|
|
|
|
|
|
|
|
// Setup actions
|
|
|
|
|
createConfig := flag.Bool("create-config", false, "Creates a basic configuration and exits") |
|
|
|
|
doConfig := flag.Bool("config", false, "Run the configuration process") |
|
|
|
|
configSections := flag.String("sections", "server db app", "Which sections of the configuration to go through (requires --config), "+ |
|
|
|
|
"valid values are any combination of 'server', 'db' and 'app' "+ |
|
|
|
|
"example: writefreely --config --sections \"db app\"") |
|
|
|
|
genKeys := flag.Bool("gen-keys", false, "Generate encryption and authentication keys") |
|
|
|
|
createSchema := flag.Bool("init-db", false, "Initialize app database") |
|
|
|
|
migrate := flag.Bool("migrate", false, "Migrate the database") |
|
|
|
|
|
|
|
|
|
// Admin actions
|
|
|
|
|
createAdmin := flag.String("create-admin", "", "Create an admin with the given username:password") |
|
|
|
|
createUser := flag.String("create-user", "", "Create a regular user with the given username:password") |
|
|
|
|
deleteUsername := flag.String("delete-user", "", "Delete a user with the given username") |
|
|
|
|
resetPassUser := flag.String("reset-pass", "", "Reset the given user's password") |
|
|
|
|
outputVersion := flag.Bool("v", false, "Output the current version") |
|
|
|
|
flag.Parse() |
|
|
|
|
|
|
|
|
|
app := writefreely.NewApp(*configFile) |
|
|
|
|
|
|
|
|
|
if *outputVersion { |
|
|
|
|
writefreely.OutputVersion() |
|
|
|
|
os.Exit(0) |
|
|
|
|
} else if *createConfig { |
|
|
|
|
err := writefreely.CreateConfig(app) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error(err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
os.Exit(0) |
|
|
|
|
} else if *doConfig { |
|
|
|
|
writefreely.DoConfig(app, *configSections) |
|
|
|
|
os.Exit(0) |
|
|
|
|
} else if *genKeys { |
|
|
|
|
err := writefreely.GenerateKeyFiles(app) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error(err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
os.Exit(0) |
|
|
|
|
} else if *createSchema { |
|
|
|
|
err := writefreely.CreateSchema(app) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error(err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
os.Exit(0) |
|
|
|
|
} else if *createAdmin != "" { |
|
|
|
|
username, password, err := userPass(*createAdmin, true) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error(err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
err = writefreely.CreateUser(app, username, password, true) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error(err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
os.Exit(0) |
|
|
|
|
} else if *createUser != "" { |
|
|
|
|
username, password, err := userPass(*createUser, false) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error(err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
err = writefreely.CreateUser(app, username, password, false) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error(err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
os.Exit(0) |
|
|
|
|
} else if *resetPassUser != "" { |
|
|
|
|
err := writefreely.ResetPassword(app, *resetPassUser) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error(err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
os.Exit(0) |
|
|
|
|
} else if *deleteUsername != "" { |
|
|
|
|
err := writefreely.DoDeleteAccount(app, *deleteUsername) |
|
|
|
|
cli.VersionPrinter = func(c *cli.Context) { |
|
|
|
|
fmt.Printf("%s\n", c.App.Version) |
|
|
|
|
} |
|
|
|
|
app := &cli.App{ |
|
|
|
|
Name: "WriteFreely", |
|
|
|
|
Usage: "A beautifully pared-down blogging platform", |
|
|
|
|
Version: writefreely.FormatVersion(), |
|
|
|
|
Action: legacyActions, // legacy due to use of flags for switching actions
|
|
|
|
|
Flags: []cli.Flag{ |
|
|
|
|
&cli.BoolFlag{ |
|
|
|
|
Name: "create-config", |
|
|
|
|
Value: false, |
|
|
|
|
Usage: "Generate a basic configuration", |
|
|
|
|
Hidden: true, |
|
|
|
|
}, |
|
|
|
|
&cli.BoolFlag{ |
|
|
|
|
Name: "config", |
|
|
|
|
Value: false, |
|
|
|
|
Usage: "Interactive configuration process", |
|
|
|
|
Hidden: true, |
|
|
|
|
}, |
|
|
|
|
&cli.StringFlag{ |
|
|
|
|
Name: "sections", |
|
|
|
|
Value: "server db app", |
|
|
|
|
Usage: "Which sections of the configuration to go through (requires --config)\n" + |
|
|
|
|
"valid values are any combination of 'server', 'db' and 'app' \n" + |
|
|
|
|
"example: writefreely --config --sections \"db app\"", |
|
|
|
|
Hidden: true, |
|
|
|
|
}, |
|
|
|
|
&cli.BoolFlag{ |
|
|
|
|
Name: "gen-keys", |
|
|
|
|
Value: false, |
|
|
|
|
Usage: "Generate encryption and authentication keys", |
|
|
|
|
Hidden: true, |
|
|
|
|
}, |
|
|
|
|
&cli.BoolFlag{ |
|
|
|
|
Name: "init-db", |
|
|
|
|
Value: false, |
|
|
|
|
Usage: "Initialize app database", |
|
|
|
|
Hidden: true, |
|
|
|
|
}, |
|
|
|
|
&cli.BoolFlag{ |
|
|
|
|
Name: "migrate", |
|
|
|
|
Value: false, |
|
|
|
|
Usage: "Migrate the database", |
|
|
|
|
Hidden: true, |
|
|
|
|
}, |
|
|
|
|
&cli.StringFlag{ |
|
|
|
|
Name: "create-admin", |
|
|
|
|
Usage: "Create an admin with the given username:password", |
|
|
|
|
Hidden: true, |
|
|
|
|
}, |
|
|
|
|
&cli.StringFlag{ |
|
|
|
|
Name: "create-user", |
|
|
|
|
Usage: "Create a regular user with the given username:password", |
|
|
|
|
Hidden: true, |
|
|
|
|
}, |
|
|
|
|
&cli.StringFlag{ |
|
|
|
|
Name: "delete-user", |
|
|
|
|
Usage: "Delete a user with the given username", |
|
|
|
|
Hidden: true, |
|
|
|
|
}, |
|
|
|
|
&cli.StringFlag{ |
|
|
|
|
Name: "reset-pass", |
|
|
|
|
Usage: "Reset the given user's password", |
|
|
|
|
Hidden: true, |
|
|
|
|
}, |
|
|
|
|
}, // legacy flags (set to hidden to eventually switch to bash-complete compatible format)
|
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
defaultFlags := []cli.Flag{ |
|
|
|
|
&cli.StringFlag{ |
|
|
|
|
Name: "c", |
|
|
|
|
Value: "config.ini", |
|
|
|
|
Usage: "Load configuration from `FILE`", |
|
|
|
|
}, |
|
|
|
|
&cli.BoolFlag{ |
|
|
|
|
Name: "debug", |
|
|
|
|
Value: false, |
|
|
|
|
Usage: "Enables debug logging", |
|
|
|
|
}, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
app.Flags = append(app.Flags, defaultFlags...) |
|
|
|
|
|
|
|
|
|
app.Commands = []*cli.Command{ |
|
|
|
|
&cmdUser, |
|
|
|
|
&cmdDB, |
|
|
|
|
&cmdConfig, |
|
|
|
|
&cmdKeys, |
|
|
|
|
&cmdServe, |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
err := app.Run(os.Args) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error(err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
} |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func legacyActions(c *cli.Context) error { |
|
|
|
|
app := writefreely.NewApp(c.String("c")) |
|
|
|
|
|
|
|
|
|
switch true { |
|
|
|
|
case c.IsSet("create-config"): |
|
|
|
|
return writefreely.CreateConfig(app) |
|
|
|
|
case c.IsSet("config"): |
|
|
|
|
writefreely.DoConfig(app, c.String("sections")) |
|
|
|
|
return nil |
|
|
|
|
case c.IsSet("gen-keys"): |
|
|
|
|
return writefreely.GenerateKeyFiles(app) |
|
|
|
|
case c.IsSet("init-db"): |
|
|
|
|
return writefreely.CreateSchema(app) |
|
|
|
|
case c.IsSet("migrate"): |
|
|
|
|
return writefreely.Migrate(app) |
|
|
|
|
case c.IsSet("create-admin"): |
|
|
|
|
username, password, err := parseCredentials(c.String("create-admin")) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error(err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
os.Exit(0) |
|
|
|
|
} else if *migrate { |
|
|
|
|
err := writefreely.Migrate(app) |
|
|
|
|
return writefreely.CreateUser(app, username, password, true) |
|
|
|
|
case c.IsSet("create-user"): |
|
|
|
|
username, password, err := parseCredentials(c.String("create-user")) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error(err.Error()) |
|
|
|
|
os.Exit(1) |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
os.Exit(0) |
|
|
|
|
return writefreely.CreateUser(app, username, password, false) |
|
|
|
|
case c.IsSet("delete-user"): |
|
|
|
|
return writefreely.DoDeleteAccount(app, c.String("delete-user")) |
|
|
|
|
case c.IsSet("reset-pass"): |
|
|
|
|
return writefreely.ResetPassword(app, c.String("reset-pass")) |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Initialize the application
|
|
|
|
|
var err error |
|
|
|
|
log.Info("Starting %s...", writefreely.FormatVersion()) |
|
|
|
|
app, err = writefreely.Initialize(app, *debugPtr) |
|
|
|
|
app, err = writefreely.Initialize(app, c.Bool("debug")) |
|
|
|
|
if err != nil { |
|
|
|
|
log.Error("%s", err) |
|
|
|
|
os.Exit(1) |
|
|
|
|
return err |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
// Set app routes
|
|
|
|
@ -136,20 +171,14 @@ func main() { |
|
|
|
|
|
|
|
|
|
// Serve the application
|
|
|
|
|
writefreely.Serve(app, r) |
|
|
|
|
|
|
|
|
|
return nil |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
func userPass(credStr string, isAdmin bool) (user string, pass string, err error) { |
|
|
|
|
creds := strings.Split(credStr, ":") |
|
|
|
|
func parseCredentials(credentialString string) (string, string, error) { |
|
|
|
|
creds := strings.Split(credentialString, ":") |
|
|
|
|
if len(creds) != 2 { |
|
|
|
|
c := "user" |
|
|
|
|
if isAdmin { |
|
|
|
|
c = "admin" |
|
|
|
|
} |
|
|
|
|
err = fmt.Errorf("usage: writefreely --create-%s username:password", c) |
|
|
|
|
return |
|
|
|
|
return "", "", fmt.Errorf("invalid format for passed credentials, must be username:password") |
|
|
|
|
} |
|
|
|
|
|
|
|
|
|
user = creds[0] |
|
|
|
|
pass = creds[1] |
|
|
|
|
return |
|
|
|
|
return creds[0], creds[1], nil |
|
|
|
|
} |
|
|
|
|