boyska
a4d7e6640b
this is useful for initialization scripts or the like. the parser is very basic, but should still be useful
212 lines
4.8 KiB
Go
212 lines
4.8 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"flag"
|
|
"fmt"
|
|
"io"
|
|
"os"
|
|
"strings"
|
|
|
|
paneldb "git.lattuga.net/boyska/feedpanel/db"
|
|
"github.com/go-pg/pg"
|
|
"github.com/howeyc/gopass"
|
|
)
|
|
|
|
type commandFunc func([]string) error
|
|
|
|
var globalOptions struct {
|
|
verbose bool
|
|
pgOptions pg.Options
|
|
}
|
|
|
|
var cmdMap map[string]commandFunc
|
|
|
|
func init() {
|
|
cmdMap = map[string]commandFunc{
|
|
"batch": cmdBatch,
|
|
"setup": cmdSetup,
|
|
"adduser": cmdAddUser,
|
|
"listusers": cmdListUsers,
|
|
}
|
|
}
|
|
|
|
func getDB() paneldb.DB {
|
|
pgdb := pg.Connect(&globalOptions.pgOptions)
|
|
db := paneldb.DB{PgDB: pgdb}
|
|
return db
|
|
}
|
|
|
|
func cmdSetup(args []string) error {
|
|
db := getDB()
|
|
err := db.Setup()
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
if globalOptions.verbose {
|
|
fmt.Println("Tables created")
|
|
}
|
|
os.Exit(0)
|
|
return nil
|
|
}
|
|
|
|
func askPassword() (string, error) {
|
|
fmt.Print("New password: ")
|
|
pass, err := gopass.GetPasswd()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
fmt.Print("Retype new password: ")
|
|
pass2, err := gopass.GetPasswd()
|
|
if err != nil {
|
|
return "", err
|
|
}
|
|
if string(pass) != string(pass2) {
|
|
return "", fmt.Errorf("Passwords differ")
|
|
}
|
|
return string(pass), nil
|
|
}
|
|
|
|
func cmdAddUser(args []string) error {
|
|
flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
|
|
password := flagset.String("password", "", "set password from command line; INSECURE!")
|
|
flagset.Parse(args[1:])
|
|
if len(flagset.Args()) < 2 {
|
|
fmt.Fprintf(os.Stderr, "Usage: %s [options] USER EMAIL\n", args[0])
|
|
flagset.PrintDefaults()
|
|
os.Exit(2)
|
|
}
|
|
user := flagset.Args()[0]
|
|
email := flagset.Args()[1]
|
|
if *password == "" {
|
|
pass, err := askPassword()
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "Error:", err)
|
|
os.Exit(1)
|
|
}
|
|
*password = string(pass)
|
|
}
|
|
db := getDB()
|
|
err := db.UserAdd(user, email, *password)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
if globalOptions.verbose {
|
|
fmt.Printf("Success: user %s added\n", user)
|
|
}
|
|
os.Exit(0)
|
|
return nil
|
|
}
|
|
|
|
func composeListUserOutput(user paneldb.User, usernameFlag, emailFlag, dateCreatedFlag bool) {
|
|
var row string
|
|
if usernameFlag {
|
|
row += user.UserName
|
|
if emailFlag || dateCreatedFlag {
|
|
row += "\t"
|
|
}
|
|
}
|
|
if emailFlag {
|
|
row += user.Email
|
|
if dateCreatedFlag {
|
|
row += "\t"
|
|
}
|
|
}
|
|
if dateCreatedFlag {
|
|
row += user.DateCreated
|
|
}
|
|
fmt.Fprintln(os.Stdout, row)
|
|
}
|
|
|
|
func cmdListUsers(args []string) error {
|
|
flagset := flag.NewFlagSet(args[0], flag.ExitOnError)
|
|
usernameFlag := flagset.Bool("no-nick", true, "skip printing usernames")
|
|
emailFlag := flagset.Bool("no-email", true, "skip printing emails")
|
|
dateCreatedFlag := flagset.Bool("created", false, "print date of user creation")
|
|
headerFlag := flagset.Bool("no-header", false, "skip printing the header")
|
|
flagset.Parse(args[1:])
|
|
db := getDB()
|
|
users, err := db.GetUsers()
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "Error:", err)
|
|
os.Exit(1)
|
|
}
|
|
// Printing the header
|
|
if !*headerFlag {
|
|
header := paneldb.User{
|
|
UserName: "username",
|
|
Email: "email",
|
|
DateCreated: "date_created",
|
|
}
|
|
separator := paneldb.User{
|
|
UserName: "--------",
|
|
Email: "-----",
|
|
DateCreated: "------------",
|
|
}
|
|
composeListUserOutput(header, *usernameFlag, *emailFlag, *dateCreatedFlag)
|
|
composeListUserOutput(separator, *usernameFlag, *emailFlag, *dateCreatedFlag)
|
|
}
|
|
// Printing the user list
|
|
for _, user := range users {
|
|
composeListUserOutput(user, *usernameFlag, *emailFlag, *dateCreatedFlag)
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func usage(w io.Writer) {
|
|
fmt.Fprintf(w, "Usage: %s SUBCOMMAND [command args...]\n", os.Args[0])
|
|
fmt.Fprintln(w, "\nSubcommands:")
|
|
for cmdName, _ := range cmdMap {
|
|
fmt.Fprintln(w, " -", cmdName)
|
|
}
|
|
}
|
|
|
|
func runLine(args []string) {
|
|
cmdName := args[0]
|
|
cmdFunc, ok := cmdMap[cmdName]
|
|
if !ok {
|
|
fmt.Fprintf(os.Stderr, "Invalid command `%s`\n", cmdName)
|
|
usage(os.Stderr)
|
|
os.Exit(2)
|
|
}
|
|
err := cmdFunc(args)
|
|
if err != nil {
|
|
fmt.Fprintln(os.Stderr, "Error")
|
|
fmt.Fprintln(os.Stderr, err)
|
|
os.Exit(1)
|
|
}
|
|
}
|
|
|
|
func cmdBatch(args []string) error {
|
|
scanner := bufio.NewScanner(os.Stdin)
|
|
for scanner.Scan() {
|
|
line := scanner.Text()
|
|
runLine(strings.Split(line, " "))
|
|
}
|
|
|
|
if scanner.Err() != nil {
|
|
fmt.Fprintln(os.Stderr, "Error reading stdin:", scanner.Err())
|
|
os.Exit(1)
|
|
}
|
|
os.Exit(0)
|
|
return nil
|
|
}
|
|
|
|
func main() {
|
|
flag.StringVar(&globalOptions.pgOptions.User, "db-user", "panel", "The user to connect to database to")
|
|
flag.StringVar(&globalOptions.pgOptions.Password, "db-pass", "", "database password")
|
|
flag.StringVar(&globalOptions.pgOptions.Database, "db-name", "feeds", "database name")
|
|
flag.StringVar(&globalOptions.pgOptions.Addr, "db-addr", "127.0.0.1:5432", "database network address")
|
|
flag.BoolVar(&globalOptions.verbose, "verbose", false, "verbose output")
|
|
flag.Parse()
|
|
|
|
if len(flag.Args()) < 1 {
|
|
fmt.Fprintln(os.Stderr, "Not enough arguments!")
|
|
usage(os.Stderr)
|
|
os.Exit(2)
|
|
}
|
|
runLine(flag.Args())
|
|
os.Exit(0)
|
|
}
|