mirror of
https://github.com/semaphoreui/semaphore.git
synced 2024-11-23 12:30:41 +01:00
Move interactive setup to own package
Remove reflex installation for windows
This commit is contained in:
parent
19463ddb4f
commit
56a7a4132d
@ -53,7 +53,7 @@ tasks:
|
||||
GORELEASER_VERSION: "0.159.0"
|
||||
GOLINTER_VERSION: "1.31.0"
|
||||
cmds:
|
||||
- go install github.com/cespare/reflex
|
||||
- '{{ if ne OS "windows" }} go install github.com/cespare/reflex {{ else }} {{ end }}'
|
||||
- go install github.com/gobuffalo/packr/...
|
||||
- go install github.com/haya14busa/goverage
|
||||
- go install github.com/snikch/goodman/cmd/goodman
|
||||
|
86
cli/main.go
86
cli/main.go
@ -2,17 +2,16 @@ package main
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"encoding/json"
|
||||
"fmt"
|
||||
"net/http"
|
||||
"os"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"github.com/ansible-semaphore/semaphore/cli/setup"
|
||||
"github.com/ansible-semaphore/semaphore/db"
|
||||
"github.com/ansible-semaphore/semaphore/db/factory"
|
||||
"github.com/gorilla/context"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"github.com/ansible-semaphore/semaphore/api"
|
||||
@ -31,7 +30,6 @@ func cropTrailingSlashMiddleware(next http.Handler) http.Handler {
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
func main() {
|
||||
util.ConfigInit()
|
||||
|
||||
@ -78,7 +76,7 @@ func main() {
|
||||
|
||||
route := api.Route()
|
||||
|
||||
route.Use(func (next http.Handler) http.Handler {
|
||||
route.Use(func(next http.Handler) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
context.Set(r, "store", store)
|
||||
next.ServeHTTP(w, r)
|
||||
@ -100,79 +98,33 @@ func main() {
|
||||
|
||||
//nolint: gocyclo
|
||||
func doSetup() int {
|
||||
|
||||
fmt.Print(`
|
||||
Hello! You will now be guided through a setup to:
|
||||
|
||||
1. Set up configuration for a MySQL/MariaDB database
|
||||
2. Set up a path for your playbooks (auto-created)
|
||||
3. Run database Migrations
|
||||
4. Set up initial semaphore user & password
|
||||
|
||||
`)
|
||||
|
||||
var b []byte
|
||||
setup := util.NewConfig()
|
||||
var config *util.ConfigType
|
||||
for {
|
||||
setup.Scan()
|
||||
setup.GenerateCookieSecrets()
|
||||
config = &util.ConfigType{}
|
||||
config.GenerateCookieSecrets()
|
||||
setup.InteractiveSetup(config)
|
||||
|
||||
var err error
|
||||
b, err = json.MarshalIndent(&setup, " ", "\t")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("\n Generated configuration:\n %v\n\n", string(b))
|
||||
fmt.Print(" > Is this correct? (yes/no): ")
|
||||
|
||||
var answer string
|
||||
util.ScanErrorChecker(fmt.Scanln(&answer))
|
||||
if answer == "yes" || answer == "y" {
|
||||
if setup.VerifyConfig(config) {
|
||||
break
|
||||
}
|
||||
|
||||
fmt.Println()
|
||||
setup = util.NewConfig()
|
||||
}
|
||||
|
||||
confDir, err := os.Getwd()
|
||||
if err != nil {
|
||||
confDir = "/etc/semaphore"
|
||||
}
|
||||
fmt.Print(" > Config output directory (default " + confDir + "): ")
|
||||
|
||||
var answer string
|
||||
util.ScanErrorChecker(fmt.Scanln(&answer))
|
||||
if len(answer) > 0 {
|
||||
confDir = answer
|
||||
}
|
||||
|
||||
fmt.Printf(" Running: mkdir -p %v..\n", confDir)
|
||||
err = os.MkdirAll(confDir, 0755) //nolint: gas
|
||||
if err != nil {
|
||||
log.Panic("Could not create config directory: " + err.Error())
|
||||
}
|
||||
|
||||
configPath := path.Join(confDir, "/config.json")
|
||||
if err = ioutil.WriteFile(configPath, b, 0644); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
fmt.Printf(" Configuration written to %v..\n", configPath)
|
||||
configPath := setup.ScanConfigPathAndSave(config)
|
||||
util.Config = config
|
||||
|
||||
fmt.Println(" Pinging db..")
|
||||
util.Config = setup
|
||||
|
||||
store := factory.CreateStore()
|
||||
|
||||
if err = store.Connect(); err != nil {
|
||||
fmt.Printf("\n Cannot connect to database!\n %v\n", err.Error())
|
||||
if err := store.Connect(); err != nil {
|
||||
fmt.Printf("Cannot connect to database!\n %v\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
fmt.Println("\n Running DB Migrations..")
|
||||
if err = store.Migrate(); err != nil {
|
||||
fmt.Printf("\n Database migrations failed!\n %v\n", err.Error())
|
||||
fmt.Println("Running DB Migrations..")
|
||||
if err := store.Migrate(); err != nil {
|
||||
fmt.Printf("Database migrations failed!\n %v\n", err.Error())
|
||||
os.Exit(1)
|
||||
}
|
||||
|
||||
|
210
cli/setup/setup.go
Normal file
210
cli/setup/setup.go
Normal file
@ -0,0 +1,210 @@
|
||||
package setup
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"os"
|
||||
"path/filepath"
|
||||
"strings"
|
||||
|
||||
log "github.com/Sirupsen/logrus"
|
||||
|
||||
"github.com/ansible-semaphore/semaphore/util"
|
||||
)
|
||||
|
||||
const yesLong = "yes"
|
||||
const yesShort = "y"
|
||||
|
||||
const interactiveSetupBlurb = `
|
||||
Hello! You will now be guided through a setup to:
|
||||
|
||||
1. Set up configuration for a MySQL/MariaDB database
|
||||
2. Set up a path for your playbooks (auto-created)
|
||||
3. Run database Migrations
|
||||
4. Set up initial semaphore user & password
|
||||
|
||||
`
|
||||
|
||||
func InteractiveSetup(conf *util.ConfigType) {
|
||||
stdin := bufio.NewReader(os.Stdin)
|
||||
|
||||
fmt.Print(interactiveSetupBlurb)
|
||||
|
||||
dbPrompt := `What database to use:
|
||||
1 - MySQL
|
||||
2 - BoltDB
|
||||
`
|
||||
|
||||
var db int
|
||||
promptValue(stdin, dbPrompt, "1", &db)
|
||||
|
||||
switch db {
|
||||
case 1:
|
||||
scanMySQL(conf, stdin)
|
||||
case 2:
|
||||
scanBoltDb(conf, stdin)
|
||||
}
|
||||
|
||||
defaultPlaybookPath := filepath.Join(os.TempDir(), "semaphore")
|
||||
promptValue(stdin, "Playbook path", defaultPlaybookPath, &conf.TmpPath)
|
||||
conf.TmpPath = filepath.Clean(conf.TmpPath)
|
||||
|
||||
promptValue(stdin, "Web root URL (optional, see https://github.com/ansible-semaphore/semaphore/wiki/Web-root-URL)", "", &conf.WebHost)
|
||||
|
||||
promptConfirmation(stdin, "Enable email alerts?", false, &conf.EmailAlert)
|
||||
if conf.EmailAlert {
|
||||
promptValue(stdin, "Mail server host", "localhost", &conf.EmailHost)
|
||||
promptValue(stdin, "Mail server port", "25", &conf.EmailPort)
|
||||
promptValue(stdin, "Mail sender address", "semaphore@localhost", &conf.EmailSender)
|
||||
}
|
||||
|
||||
promptConfirmation(stdin, "Enable telegram alerts?", false, &conf.TelegramAlert)
|
||||
if conf.TelegramAlert {
|
||||
promptValue(stdin, "Telegram bot token (you can get it from @BotFather)", "", &conf.TelegramToken)
|
||||
promptValue(stdin, "Telegram chat ID", "", &conf.TelegramChat)
|
||||
}
|
||||
|
||||
promptConfirmation(stdin, "Enable LDAP authentication?", false, &conf.LdapEnable)
|
||||
if conf.LdapEnable {
|
||||
promptValue(stdin, "LDAP server host", "localhost:389", &conf.LdapServer)
|
||||
promptConfirmation(stdin, "Enable LDAP TLS connection", false, &conf.LdapNeedTLS)
|
||||
promptValue(stdin, "LDAP DN for bind", "cn=user,ou=users,dc=example", &conf.LdapBindDN)
|
||||
promptValue(stdin, "Password for LDAP bind user", "pa55w0rd", &conf.LdapBindPassword)
|
||||
promptValue(stdin, "LDAP DN for user search", "ou=users,dc=example", &conf.LdapSearchDN)
|
||||
promptValue(stdin, "LDAP search filter", `(uid=%s)`, &conf.LdapSearchFilter)
|
||||
promptValue(stdin, "LDAP mapping for DN field", "dn", &conf.LdapMappings.DN)
|
||||
promptValue(stdin, "LDAP mapping for username field", "uid", &conf.LdapMappings.UID)
|
||||
promptValue(stdin, "LDAP mapping for full name field", "cn", &conf.LdapMappings.CN)
|
||||
promptValue(stdin, "LDAP mapping for email field", "mail", &conf.LdapMappings.Mail)
|
||||
}
|
||||
}
|
||||
|
||||
func scanBoltDb(conf *util.ConfigType, stdin *bufio.Reader) {
|
||||
workingDirectory, err := os.Getwd()
|
||||
if err != nil {
|
||||
workingDirectory = os.TempDir()
|
||||
}
|
||||
defaultBoltDBPath := filepath.Join(workingDirectory, "database.boltdb")
|
||||
promptValue(stdin, "DB filename", defaultBoltDBPath, &conf.BoltDb.Hostname)
|
||||
}
|
||||
|
||||
func scanMySQL(conf *util.ConfigType, stdin *bufio.Reader) {
|
||||
promptValue(stdin, "DB Hostname", "127.0.0.1:3306", &conf.MySQL.Hostname)
|
||||
promptValue(stdin, "DB User", "root", &conf.MySQL.Username)
|
||||
promptValue(stdin, "DB Password", "", &conf.MySQL.Password)
|
||||
promptValue(stdin, "DB Name", "semaphore", &conf.MySQL.DbName)
|
||||
}
|
||||
|
||||
func ScanConfigPathAndSave(config *util.ConfigType) string {
|
||||
stdin := bufio.NewReader(os.Stdin)
|
||||
|
||||
configDirectory, err := os.Getwd()
|
||||
if err != nil {
|
||||
configDirectory, err = os.UserConfigDir()
|
||||
if err != nil {
|
||||
// Final fallback
|
||||
configDirectory = "/etc/semaphore"
|
||||
}
|
||||
configDirectory = filepath.Join(configDirectory, "semaphore")
|
||||
}
|
||||
promptValue(stdin, "Config output directory", configDirectory, &configDirectory)
|
||||
|
||||
fmt.Printf("Running: mkdir -p %v..\n", configDirectory)
|
||||
err = os.MkdirAll(configDirectory, 0755)
|
||||
if err != nil {
|
||||
log.Panic("Could not create config directory: " + err.Error())
|
||||
}
|
||||
|
||||
// Marshal config to json
|
||||
bytes, err := config.ToJSON()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
configPath := filepath.Join(configDirectory, "config.json")
|
||||
if err = ioutil.WriteFile(configPath, bytes, 0644); err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("Configuration written to %v..\n", configPath)
|
||||
return configPath
|
||||
}
|
||||
|
||||
func VerifyConfig(config *util.ConfigType) bool {
|
||||
stdin := bufio.NewReader(os.Stdin)
|
||||
|
||||
bytes, err := config.ToJSON()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
|
||||
fmt.Printf("\nGenerated configuration:\n %v\n\n", string(bytes))
|
||||
|
||||
var correct bool
|
||||
promptConfirmation(stdin, "Is this correct?", true, &correct)
|
||||
return correct
|
||||
}
|
||||
|
||||
func promptValue(stdin *bufio.Reader, prompt string, def string, item interface{}) {
|
||||
// Print prompt with optional default value
|
||||
fmt.Print(prompt)
|
||||
if len(def) != 0 {
|
||||
fmt.Print(" (default " + def + ")")
|
||||
}
|
||||
fmt.Print("\n> ")
|
||||
|
||||
str, err := stdin.ReadString('\n')
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{"level": "Warn"}).Warn(err.Error())
|
||||
}
|
||||
|
||||
// Remove newlines
|
||||
str = strings.TrimSuffix(str, "\n")
|
||||
str = strings.TrimSuffix(str, "\r")
|
||||
|
||||
// If default, print default on input line
|
||||
if len(str) == 0 {
|
||||
str = def
|
||||
fmt.Print("\033[1A")
|
||||
fmt.Println("> " + def)
|
||||
}
|
||||
|
||||
//Parse
|
||||
if _, err := fmt.Sscanln(str, item); err != nil && err != io.EOF {
|
||||
log.WithFields(log.Fields{"level": "Warn"}).Warn(err.Error())
|
||||
}
|
||||
|
||||
// Empty line after prompt
|
||||
fmt.Println("")
|
||||
}
|
||||
|
||||
func promptConfirmation(stdin *bufio.Reader, prompt string, def bool, item *bool) {
|
||||
defString := "yes"
|
||||
if !def {
|
||||
defString = "no"
|
||||
}
|
||||
|
||||
fmt.Print(prompt + " (yes/no) (default " + defString + ")")
|
||||
fmt.Print("\n> ")
|
||||
|
||||
str, err := stdin.ReadString('\n')
|
||||
if err != nil {
|
||||
log.WithFields(log.Fields{"level": "Warn"}).Warn(err.Error())
|
||||
}
|
||||
|
||||
switch strings.ToLower(str) {
|
||||
case "y", "yes":
|
||||
*item = true
|
||||
case "n", "no":
|
||||
*item = false
|
||||
default:
|
||||
*item = def
|
||||
fmt.Print("\033[1A")
|
||||
fmt.Println("> " + defString)
|
||||
}
|
||||
|
||||
// Empty line after prompt
|
||||
fmt.Println("")
|
||||
}
|
6
go.mod
6
go.mod
@ -9,8 +9,8 @@ require (
|
||||
github.com/Sirupsen/logrus v1.0.4
|
||||
github.com/cespare/reflex v0.3.0 // indirect
|
||||
github.com/go-gorp/gorp/v3 v3.0.2
|
||||
github.com/go-openapi/loads v0.19.4
|
||||
github.com/go-openapi/spec v0.19.6
|
||||
github.com/go-openapi/loads v0.19.4 // indirect
|
||||
github.com/go-openapi/spec v0.19.6 // indirect
|
||||
github.com/go-sql-driver/mysql v1.4.1
|
||||
github.com/go-swagger/go-swagger v0.22.0 // indirect
|
||||
github.com/go-task/task v2.2.0+incompatible // indirect
|
||||
@ -39,7 +39,7 @@ require (
|
||||
github.com/radovskyb/watcher v1.0.7 // indirect
|
||||
github.com/russross/blackfriday v1.5.2
|
||||
github.com/sirupsen/logrus v1.4.2 // indirect
|
||||
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa
|
||||
github.com/snikch/goodman v0.0.0-20171125024755-10e37e294daa // indirect
|
||||
github.com/spf13/cobra v0.0.5 // indirect
|
||||
github.com/ziutek/mymysql v1.5.4 // indirect
|
||||
go.etcd.io/bbolt v1.3.2
|
||||
|
1
go.sum
1
go.sum
@ -165,6 +165,7 @@ github.com/haya14busa/goverage v0.0.0-20180129164344-eec3514a20b5/go.mod h1:0YZ2
|
||||
github.com/hpcloud/tail v1.0.0/go.mod h1:ab1qPbhIpdTxEkNHXyeSf5vhxWSCs/tWer42PpOxQnU=
|
||||
github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
|
||||
github.com/imdario/mergo v0.3.8/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
|
||||
github.com/inconshreveable/mousetrap v1.0.0 h1:Z8tu5sraLXCXIcARxBp/8cbvlwVa7Z1NHg9XEKhtSvM=
|
||||
github.com/inconshreveable/mousetrap v1.0.0/go.mod h1:PxqpIevigyE2G7u3NXJIT2ANytuPF1OarO4DADm73n8=
|
||||
github.com/jessevdk/go-flags v1.4.0 h1:4IU2WS7AumrZ/40jfhf4QVDMsQwqA7VEHozFRrGARJA=
|
||||
github.com/jessevdk/go-flags v1.4.0/go.mod h1:4FA24M0QyGHXBuZZK/XkWh8h0e1EYbRYJSGM75WSRxI=
|
||||
|
266
util/config.go
266
util/config.go
@ -6,10 +6,8 @@ import (
|
||||
"errors"
|
||||
"flag"
|
||||
"fmt"
|
||||
log "github.com/Sirupsen/logrus"
|
||||
"os"
|
||||
"path"
|
||||
"path/filepath"
|
||||
|
||||
"net/url"
|
||||
|
||||
@ -35,11 +33,6 @@ var Upgrade bool
|
||||
// WebHostURL is the public route to the semaphore server
|
||||
var WebHostURL *url.URL
|
||||
|
||||
const (
|
||||
longPos = "yes"
|
||||
shortPos = "y"
|
||||
)
|
||||
|
||||
type DbDriver int
|
||||
|
||||
const (
|
||||
@ -64,8 +57,8 @@ type ldapMappings struct {
|
||||
|
||||
//ConfigType mapping between Config and the json file that sets it
|
||||
type ConfigType struct {
|
||||
MySQL DbConfig `json:"mysql"`
|
||||
BoltDb DbConfig `json:"bolt"`
|
||||
MySQL DbConfig `json:"mysql"`
|
||||
BoltDb DbConfig `json:"bolt"`
|
||||
|
||||
// Format `:port_num` eg, :3000
|
||||
// if : is missing it will be corrected
|
||||
@ -119,21 +112,9 @@ type ConfigType struct {
|
||||
//Config exposes the application configuration storage for use in the application
|
||||
var Config *ConfigType
|
||||
|
||||
var confPath *string
|
||||
|
||||
// NewConfig returns a reference to a new blank configType
|
||||
// nolint: golint
|
||||
func NewConfig() *ConfigType {
|
||||
return &ConfigType{}
|
||||
}
|
||||
|
||||
// ScanErrorChecker deals with errors encountered while scanning lines
|
||||
// since we do not fail on these errors currently we can simply note them
|
||||
// and move on
|
||||
func ScanErrorChecker(n int, err error) {
|
||||
if err != nil {
|
||||
log.Warn("An input error occurred:" + err.Error())
|
||||
}
|
||||
// ToJSON returns a JSON string of the config
|
||||
func (config *ConfigType) ToJSON() ([]byte, error) {
|
||||
return json.MarshalIndent(&config, " ", "\t")
|
||||
}
|
||||
|
||||
// ConfigInit reads in cli flags, and switches actions appropriately on them
|
||||
@ -141,7 +122,7 @@ func ConfigInit() {
|
||||
flag.BoolVar(&InteractiveSetup, "setup", false, "perform interactive setup")
|
||||
flag.BoolVar(&Migration, "migrate", false, "execute migrations")
|
||||
flag.BoolVar(&Upgrade, "upgrade", false, "upgrade semaphore")
|
||||
confPath = flag.String("config", "", "config path")
|
||||
configPath := flag.String("config", "", "config path")
|
||||
|
||||
var unhashedPwd string
|
||||
flag.StringVar(&unhashedPwd, "hash", "", "generate hash of given password")
|
||||
@ -164,7 +145,7 @@ func ConfigInit() {
|
||||
}
|
||||
|
||||
if printConfig {
|
||||
cfg := &ConfigType{
|
||||
config := &ConfigType{
|
||||
MySQL: DbConfig{
|
||||
Hostname: "127.0.0.1:3306",
|
||||
Username: "root",
|
||||
@ -173,10 +154,10 @@ func ConfigInit() {
|
||||
Port: ":3000",
|
||||
TmpPath: "/tmp/semaphore",
|
||||
}
|
||||
cfg.GenerateCookieSecrets()
|
||||
config.GenerateCookieSecrets()
|
||||
|
||||
b, _ := json.MarshalIndent(cfg, "", "\t")
|
||||
fmt.Println(string(b))
|
||||
bytes, _ := config.ToJSON()
|
||||
fmt.Println(string(bytes))
|
||||
|
||||
os.Exit(0)
|
||||
}
|
||||
@ -188,7 +169,7 @@ func ConfigInit() {
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
loadConfig()
|
||||
loadConfig(configPath)
|
||||
validateConfig()
|
||||
|
||||
var encryption []byte
|
||||
@ -205,24 +186,27 @@ func ConfigInit() {
|
||||
}
|
||||
}
|
||||
|
||||
func loadConfig() {
|
||||
|
||||
//If the confPath option has been set try to load and decode it
|
||||
if confPath != nil && len(*confPath) > 0 {
|
||||
file, err := os.Open(*confPath)
|
||||
func loadConfig(configPath *string) {
|
||||
//If the configPath option has been set try to load and decode it
|
||||
var usedPath string
|
||||
if configPath != nil && len(*configPath) > 0 {
|
||||
path := *configPath
|
||||
file, err := os.Open(path)
|
||||
exitOnConfigError(err)
|
||||
decodeConfig(file)
|
||||
usedPath = path
|
||||
} else {
|
||||
// if no confPath look in the cwd
|
||||
// if no configPath look in the cwd
|
||||
cwd, err := os.Getwd()
|
||||
exitOnConfigError(err)
|
||||
cwd = cwd + "/config.json"
|
||||
confPath = &cwd
|
||||
file, err := os.Open(*confPath)
|
||||
defaultPath := path.Join(cwd, "config.json")
|
||||
file, err := os.Open(defaultPath)
|
||||
exitOnConfigError(err)
|
||||
decodeConfig(file)
|
||||
usedPath = defaultPath
|
||||
}
|
||||
fmt.Println("Using config file: " + *confPath)
|
||||
|
||||
fmt.Println("Using config file: " + usedPath)
|
||||
}
|
||||
|
||||
func validateConfig() {
|
||||
@ -325,205 +309,3 @@ func (conf *ConfigType) GenerateCookieSecrets() {
|
||||
conf.CookieHash = base64.StdEncoding.EncodeToString(hash)
|
||||
conf.CookieEncryption = base64.StdEncoding.EncodeToString(encryption)
|
||||
}
|
||||
|
||||
func (conf *ConfigType) ScanBoltDb() {
|
||||
filename, err := os.Getwd() // os.UserHomeDir()
|
||||
exitOnConfigError(err)
|
||||
filename = filepath.Join(filename, "database.bolt")
|
||||
fmt.Print(" > DB filename (default " + filename + "): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.BoltDb.Hostname))
|
||||
if len(conf.BoltDb.Hostname) == 0 {
|
||||
conf.BoltDb.Hostname = filename
|
||||
}
|
||||
}
|
||||
|
||||
func (conf *ConfigType) ScanMySQL() {
|
||||
|
||||
fmt.Print(" > DB Hostname (default 127.0.0.1:3306): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.MySQL.Hostname))
|
||||
if len(conf.MySQL.Hostname) == 0 {
|
||||
conf.MySQL.Hostname = "127.0.0.1:3306"
|
||||
}
|
||||
|
||||
fmt.Print(" > DB User (default root): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.MySQL.Username))
|
||||
if len(conf.MySQL.Username) == 0 {
|
||||
conf.MySQL.Username = "root"
|
||||
}
|
||||
|
||||
fmt.Print(" > DB Password: ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.MySQL.Password))
|
||||
|
||||
fmt.Print(" > DB Name (default semaphore): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.MySQL.DbName))
|
||||
if len(conf.MySQL.DbName) == 0 {
|
||||
conf.MySQL.DbName = "semaphore"
|
||||
}
|
||||
}
|
||||
|
||||
//nolint: gocyclo
|
||||
func (conf *ConfigType) Scan() {
|
||||
db := 1
|
||||
fmt.Println(" > DB")
|
||||
fmt.Println(" 1 - MySQL")
|
||||
fmt.Println(" 2 - bbolt")
|
||||
fmt.Print(" (default 1): ")
|
||||
ScanErrorChecker(fmt.Scanln(&db))
|
||||
|
||||
switch db {
|
||||
case 1:
|
||||
conf.ScanMySQL()
|
||||
case 2:
|
||||
conf.ScanBoltDb()
|
||||
}
|
||||
|
||||
fmt.Print(" > Playbook path (default /tmp/semaphore): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.TmpPath))
|
||||
|
||||
if len(conf.TmpPath) == 0 {
|
||||
conf.TmpPath = "/tmp/semaphore"
|
||||
}
|
||||
conf.TmpPath = path.Clean(conf.TmpPath)
|
||||
|
||||
fmt.Print(" > Web root URL (optional, see https://github.com/ansible-semaphore/semaphore/wiki/Web-root-URL): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.WebHost))
|
||||
|
||||
var EmailAlertAnswer string
|
||||
fmt.Print(" > Enable email alerts (y/n, default n): ")
|
||||
ScanErrorChecker(fmt.Scanln(&EmailAlertAnswer))
|
||||
if EmailAlertAnswer == longPos || EmailAlertAnswer == shortPos {
|
||||
|
||||
conf.EmailAlert = true
|
||||
|
||||
fmt.Print(" > Mail server host (default localhost): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.EmailHost))
|
||||
|
||||
if len(conf.EmailHost) == 0 {
|
||||
conf.EmailHost = "localhost"
|
||||
}
|
||||
|
||||
fmt.Print(" > Mail server port (default 25): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.EmailPort))
|
||||
|
||||
if len(conf.EmailPort) == 0 {
|
||||
conf.EmailPort = "25"
|
||||
}
|
||||
|
||||
fmt.Print(" > Mail sender address (default semaphore@localhost): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.EmailSender))
|
||||
|
||||
if len(conf.EmailSender) == 0 {
|
||||
conf.EmailSender = "semaphore@localhost"
|
||||
}
|
||||
|
||||
} else {
|
||||
conf.EmailAlert = false
|
||||
}
|
||||
|
||||
var TelegramAlertAnswer string
|
||||
fmt.Print(" > Enable telegram alerts (y/n, default n): ")
|
||||
ScanErrorChecker(fmt.Scanln(&TelegramAlertAnswer))
|
||||
if TelegramAlertAnswer == longPos || TelegramAlertAnswer == shortPos {
|
||||
|
||||
conf.TelegramAlert = true
|
||||
|
||||
fmt.Print(" > Telegram bot token (you can get it from @BotFather) (default ''): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.TelegramToken))
|
||||
|
||||
if len(conf.TelegramToken) == 0 {
|
||||
conf.TelegramToken = ""
|
||||
}
|
||||
|
||||
fmt.Print(" > Telegram chat ID (default ''): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.TelegramChat))
|
||||
|
||||
if len(conf.TelegramChat) == 0 {
|
||||
conf.TelegramChat = ""
|
||||
}
|
||||
|
||||
} else {
|
||||
conf.TelegramAlert = false
|
||||
}
|
||||
|
||||
var LdapAnswer string
|
||||
fmt.Print(" > Enable LDAP authentication (y/n, default n): ")
|
||||
ScanErrorChecker(fmt.Scanln(&LdapAnswer))
|
||||
if LdapAnswer == longPos || LdapAnswer == shortPos {
|
||||
|
||||
conf.LdapEnable = true
|
||||
|
||||
fmt.Print(" > LDAP server host (default localhost:389): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.LdapServer))
|
||||
|
||||
if len(conf.LdapServer) == 0 {
|
||||
conf.LdapServer = "localhost:389"
|
||||
}
|
||||
|
||||
var LdapTLSAnswer string
|
||||
fmt.Print(" > Enable LDAP TLS connection (y/n, default n): ")
|
||||
ScanErrorChecker(fmt.Scanln(&LdapTLSAnswer))
|
||||
if LdapTLSAnswer == longPos || LdapTLSAnswer == shortPos {
|
||||
conf.LdapNeedTLS = true
|
||||
} else {
|
||||
conf.LdapNeedTLS = false
|
||||
}
|
||||
|
||||
fmt.Print(" > LDAP DN for bind (default cn=user,ou=users,dc=example): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.LdapBindDN))
|
||||
|
||||
if len(conf.LdapBindDN) == 0 {
|
||||
conf.LdapBindDN = "cn=user,ou=users,dc=example"
|
||||
}
|
||||
|
||||
fmt.Print(" > Password for LDAP bind user (default pa55w0rd): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.LdapBindPassword))
|
||||
|
||||
if len(conf.LdapBindPassword) == 0 {
|
||||
conf.LdapBindPassword = "pa55w0rd"
|
||||
}
|
||||
|
||||
fmt.Print(" > LDAP DN for user search (default ou=users,dc=example): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.LdapSearchDN))
|
||||
|
||||
if len(conf.LdapSearchDN) == 0 {
|
||||
conf.LdapSearchDN = "ou=users,dc=example"
|
||||
}
|
||||
|
||||
fmt.Print(" > LDAP search filter (default (uid=" + "%" + "s)): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.LdapSearchFilter))
|
||||
|
||||
if len(conf.LdapSearchFilter) == 0 {
|
||||
conf.LdapSearchFilter = "(uid=%s)"
|
||||
}
|
||||
|
||||
fmt.Print(" > LDAP mapping for DN field (default dn): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.LdapMappings.DN))
|
||||
|
||||
if len(conf.LdapMappings.DN) == 0 {
|
||||
conf.LdapMappings.DN = "dn"
|
||||
}
|
||||
|
||||
fmt.Print(" > LDAP mapping for username field (default uid): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.LdapMappings.UID))
|
||||
|
||||
if len(conf.LdapMappings.UID) == 0 {
|
||||
conf.LdapMappings.UID = "uid"
|
||||
}
|
||||
|
||||
fmt.Print(" > LDAP mapping for full name field (default cn): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.LdapMappings.CN))
|
||||
|
||||
if len(conf.LdapMappings.CN) == 0 {
|
||||
conf.LdapMappings.CN = "cn"
|
||||
}
|
||||
|
||||
fmt.Print(" > LDAP mapping for email field (default mail): ")
|
||||
ScanErrorChecker(fmt.Scanln(&conf.LdapMappings.Mail))
|
||||
|
||||
if len(conf.LdapMappings.Mail) == 0 {
|
||||
conf.LdapMappings.Mail = "mail"
|
||||
}
|
||||
} else {
|
||||
conf.LdapEnable = false
|
||||
}
|
||||
}
|
||||
|
234
web2/package-lock.json
generated
234
web2/package-lock.json
generated
@ -1913,17 +1913,6 @@
|
||||
"unique-filename": "^1.1.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.0",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.0.tgz",
|
||||
"integrity": "sha512-qwx12AxXe2Q5xQ43Ac//I6v5aXTipYrSESdOgzrN+9XjgEpyjpKuvSGaN4qE93f7TQTlerQQ8S+EQ0EyDoVL1A==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"cliui": {
|
||||
"version": "6.0.0",
|
||||
"resolved": "https://registry.npmjs.org/cliui/-/cliui-6.0.0.tgz",
|
||||
@ -1971,25 +1960,6 @@
|
||||
"path-exists": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"locate-path": {
|
||||
"version": "5.0.0",
|
||||
"resolved": "https://registry.npmjs.org/locate-path/-/locate-path-5.0.0.tgz",
|
||||
@ -2045,25 +2015,15 @@
|
||||
"dev": true
|
||||
},
|
||||
"ssri": {
|
||||
"version": "7.1.0",
|
||||
"resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.0.tgz",
|
||||
"integrity": "sha512-77/WrDZUWocK0mvA5NTRQyveUf+wsrIc6vyrxpS8tVvYBcX215QbafrJR3KtkpskIzoFLqqNuuYQvxaMjXJ/0g==",
|
||||
"version": "7.1.1",
|
||||
"resolved": "https://registry.npmjs.org/ssri/-/ssri-7.1.1.tgz",
|
||||
"integrity": "sha512-w+daCzXN89PseTL99MkA+fxJEcU3wfaE/ah0i0lnOlpG1CYLJ2ZjzEry68YBKfLs4JfoTShrTEsJkAZuNZ/stw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"figgy-pudding": "^3.5.1",
|
||||
"minipass": "^3.1.1"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
},
|
||||
"terser-webpack-plugin": {
|
||||
"version": "2.3.8",
|
||||
"resolved": "https://registry.npmjs.org/terser-webpack-plugin/-/terser-webpack-plugin-2.3.8.tgz",
|
||||
@ -2081,18 +2041,6 @@
|
||||
"webpack-sources": "^1.4.3"
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.0.0-beta.10",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.0.0-beta.10.tgz",
|
||||
"integrity": "sha512-PflGsj4RHW3tuYFmSPhcozAkds8ELXf8d19twWorQTjcuWxl/Xqb9W1NgfsY7AAkCkkRRYy2FwIX4tSnskfKig==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^2.0.0"
|
||||
}
|
||||
},
|
||||
"wrap-ansi": {
|
||||
"version": "6.2.0",
|
||||
"resolved": "https://registry.npmjs.org/wrap-ansi/-/wrap-ansi-6.2.0.tgz",
|
||||
@ -3291,15 +3239,30 @@
|
||||
}
|
||||
},
|
||||
"browserslist": {
|
||||
"version": "4.14.5",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.14.5.tgz",
|
||||
"integrity": "sha512-Z+vsCZIvCBvqLoYkBFTwEYH3v5MCQbsAjp50ERycpOjnPmolg1Gjy4+KaWWpm8QOJt9GHkhdqAl14NpCX73CWA==",
|
||||
"version": "4.16.6",
|
||||
"resolved": "https://registry.npmjs.org/browserslist/-/browserslist-4.16.6.tgz",
|
||||
"integrity": "sha512-Wspk/PqO+4W9qp5iUTJsa1B/QrYn1keNCcEP5OvP7WBwT4KaDly0uONYmC6Xa3Z5IqnUgS0KcgLYu1l74x0ZXQ==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"caniuse-lite": "^1.0.30001135",
|
||||
"electron-to-chromium": "^1.3.571",
|
||||
"escalade": "^3.1.0",
|
||||
"node-releases": "^1.1.61"
|
||||
"caniuse-lite": "^1.0.30001219",
|
||||
"colorette": "^1.2.2",
|
||||
"electron-to-chromium": "^1.3.723",
|
||||
"escalade": "^3.1.1",
|
||||
"node-releases": "^1.1.71"
|
||||
},
|
||||
"dependencies": {
|
||||
"caniuse-lite": {
|
||||
"version": "1.0.30001245",
|
||||
"resolved": "https://registry.npmjs.org/caniuse-lite/-/caniuse-lite-1.0.30001245.tgz",
|
||||
"integrity": "sha512-768fM9j1PKXpOCKws6eTo3RHmvTUsG9UrpT4WoREFeZgJBTi4/X9g565azS/rVUGtqb8nt7FjLeF5u4kukERnA==",
|
||||
"dev": true
|
||||
},
|
||||
"colorette": {
|
||||
"version": "1.2.2",
|
||||
"resolved": "https://registry.npmjs.org/colorette/-/colorette-1.2.2.tgz",
|
||||
"integrity": "sha512-MKGMzyfeuutC/ZJ1cba9NqcNpfeqMUcYmyF1ZFY6/Cn7CNSAKx6a+s48sqLqyAiZuaP2TcqMhoo+dlwFnVxT9w==",
|
||||
"dev": true
|
||||
}
|
||||
}
|
||||
},
|
||||
"buffer": {
|
||||
@ -5228,9 +5191,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"dns-packet": {
|
||||
"version": "1.3.1",
|
||||
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.1.tgz",
|
||||
"integrity": "sha512-0UxfQkMhYAUaZI+xrNZOz/as5KgDU0M/fQ9b6SpkyLbk3GEswDi6PADJVaYJradtRVsRIlF1zLyOodbcTCDzUg==",
|
||||
"version": "1.3.4",
|
||||
"resolved": "https://registry.npmjs.org/dns-packet/-/dns-packet-1.3.4.tgz",
|
||||
"integrity": "sha512-BQ6F4vycLXBvdrJZ6S3gZewt6rcrks9KBgM9vrhW+knGRqc8uEdT7fuCwloc7nny5xNoMJ17HGH0R/6fpo8ECA==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"ip": "^1.1.0",
|
||||
@ -5427,9 +5390,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"electron-to-chromium": {
|
||||
"version": "1.3.572",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.572.tgz",
|
||||
"integrity": "sha512-TKqdEukCCl7JC20SwEoWTbtnGt4YjfHWAv4tcNky0a9qGo0WdM+Lrd60tps+nkaJCmktKBJjr99fLtEBU1ipWQ==",
|
||||
"version": "1.3.776",
|
||||
"resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.3.776.tgz",
|
||||
"integrity": "sha512-V0w7eFSBoFPpdw4xexjVPZ770UDZIevSwkkj4W97XbE3IsCsTRFpa7/yXGZ88EOQAUEA09JMMsWK0xsw0kRAYw==",
|
||||
"dev": true
|
||||
},
|
||||
"elliptic": {
|
||||
@ -5576,9 +5539,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"escalade": {
|
||||
"version": "3.1.0",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.0.tgz",
|
||||
"integrity": "sha512-mAk+hPSO8fLDkhV7V0dXazH5pDc6MrjBTPyD3VeKzxnVFjH1MIxbCdqGZB9O8+EwWakZs3ZCbDS4IpRt79V1ig==",
|
||||
"version": "3.1.1",
|
||||
"resolved": "https://registry.npmjs.org/escalade/-/escalade-3.1.1.tgz",
|
||||
"integrity": "sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==",
|
||||
"dev": true
|
||||
},
|
||||
"escape-html": {
|
||||
@ -6918,9 +6881,9 @@
|
||||
}
|
||||
},
|
||||
"glob-parent": {
|
||||
"version": "5.1.1",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.1.tgz",
|
||||
"integrity": "sha512-FnI+VGOpnlGHWZxthPGR+QhR78fuiK0sNLkHQv+bL9fQi57lNNdquIbna/WrfROrolq8GK5Ek6BiMwqL/voRYQ==",
|
||||
"version": "5.1.2",
|
||||
"resolved": "https://registry.npmjs.org/glob-parent/-/glob-parent-5.1.2.tgz",
|
||||
"integrity": "sha512-AOIgSQCepiJYwP3ARnGx+5VnTu2HBYdzbGP45eLw1vr3zB3vZLeyed1sC9hnbcOc9/SrMyM5RPQrkGz4aS9Zow==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"is-glob": "^4.0.1"
|
||||
@ -7191,9 +7154,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"hosted-git-info": {
|
||||
"version": "2.8.8",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.8.tgz",
|
||||
"integrity": "sha512-f/wzC2QaWBs7t9IYqB4T3sR1xviIViXJRJTWBlx2Gf3g0Xi5vI7Yy4koXQ1c9OYDGHN9sBy1DQ2AB8fqZBWhUg==",
|
||||
"version": "2.8.9",
|
||||
"resolved": "https://registry.npmjs.org/hosted-git-info/-/hosted-git-info-2.8.9.tgz",
|
||||
"integrity": "sha512-mxIDAb9Lsm6DoOJ7xH+5+X4y1LU/4Hi50L9C5sIswK3JzULS4bwk1FvjdBgvYR4bzT4tuUQiC15FE2f5HbLvYw==",
|
||||
"dev": true
|
||||
},
|
||||
"hpack.js": {
|
||||
@ -8679,9 +8642,9 @@
|
||||
}
|
||||
},
|
||||
"lodash": {
|
||||
"version": "4.17.20",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.20.tgz",
|
||||
"integrity": "sha512-PlhdFcillOINfeV7Ni6oF1TAEayyZBoZ8bcshTHqOYJYlrqzRK5hagpagky5o4HfCzzd1TRkXPMFq6cKk9rGmA==",
|
||||
"version": "4.17.21",
|
||||
"resolved": "https://registry.npmjs.org/lodash/-/lodash-4.17.21.tgz",
|
||||
"integrity": "sha512-v2kDEe57lecTulaDIuNTPy3Ry4gLGJ6Z1O3vE1krgXZNrsQ+LFTGHVxVjcXPs17LhbZVGedAJv8XZ1tvj5FvSg==",
|
||||
"dev": true
|
||||
},
|
||||
"lodash.clonedeep": {
|
||||
@ -9845,9 +9808,9 @@
|
||||
}
|
||||
},
|
||||
"node-releases": {
|
||||
"version": "1.1.61",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.61.tgz",
|
||||
"integrity": "sha512-DD5vebQLg8jLCOzwupn954fbIiZht05DAZs0k2u8NStSe6h9XdsuIQL8hSRKYiU8WUQRznmSDrKGbv3ObOmC7g==",
|
||||
"version": "1.1.73",
|
||||
"resolved": "https://registry.npmjs.org/node-releases/-/node-releases-1.1.73.tgz",
|
||||
"integrity": "sha512-uW7fodD6pyW2FZNZnp/Z3hvWKeEW1Y8R1+1CnErE8cXFXzl5blBOoVB41CvMer6P6Q0S5FXDwcHgFd1Wj0U9zg==",
|
||||
"dev": true
|
||||
},
|
||||
"node-sass": {
|
||||
@ -10951,9 +10914,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"postcss": {
|
||||
"version": "7.0.34",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.34.tgz",
|
||||
"integrity": "sha512-H/7V2VeNScX9KE83GDrDZNiGT1m2H+UTnlinIzhjlLX9hfMUn1mHNnGeX81a1c8JSBdBvqk7c2ZOG6ZPn5itGw==",
|
||||
"version": "7.0.36",
|
||||
"resolved": "https://registry.npmjs.org/postcss/-/postcss-7.0.36.tgz",
|
||||
"integrity": "sha512-BebJSIUMwJHRH0HAQoxN4u1CN86glsrwsW0q7T+/m44eXOUAxSNdHRkNZPYz5vVUbg17hFgOQDE7fZk7li3pZw==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"chalk": "^2.4.2",
|
||||
@ -14122,9 +14085,9 @@
|
||||
}
|
||||
},
|
||||
"url-parse": {
|
||||
"version": "1.4.7",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.4.7.tgz",
|
||||
"integrity": "sha512-d3uaVyzDB9tQoSXFvuSUNFibTd9zxd2bkVrDRvF5TmvWWQwqE4lgYJ5m+x1DbecWkw+LK4RNl2CU1hHuOKPVlg==",
|
||||
"version": "1.5.1",
|
||||
"resolved": "https://registry.npmjs.org/url-parse/-/url-parse-1.5.1.tgz",
|
||||
"integrity": "sha512-HOfCOUJt7iSYzEx/UqgtwKRMC6EU91NFhsCHMv9oM03VJcVo2Qrp8T8kI9D7amFf1cu+/3CEhgb3rF9zL7k85Q==",
|
||||
"dev": true,
|
||||
"requires": {
|
||||
"querystringify": "^2.1.1",
|
||||
@ -14333,6 +14296,87 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-loader-v16": {
|
||||
"version": "npm:vue-loader@16.3.0",
|
||||
"resolved": "https://registry.npmjs.org/vue-loader/-/vue-loader-16.3.0.tgz",
|
||||
"integrity": "sha512-UDgni/tUVSdwHuQo+vuBmEgamWx88SuSlEb5fgdvHrlJSPB9qMBRF6W7bfPWSqDns425Gt1wxAUif+f+h/rWjg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"chalk": "^4.1.0",
|
||||
"hash-sum": "^2.0.0",
|
||||
"loader-utils": "^2.0.0"
|
||||
},
|
||||
"dependencies": {
|
||||
"ansi-styles": {
|
||||
"version": "4.3.0",
|
||||
"resolved": "https://registry.npmjs.org/ansi-styles/-/ansi-styles-4.3.0.tgz",
|
||||
"integrity": "sha512-zbB9rCJAT1rbjiVDb2hqKFHNYLxgtk8NURxZ3IZwD3F6NtxbXZQCnnSi1Lkx+IDohdPlFp222wVALIheZJQSEg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-convert": "^2.0.1"
|
||||
}
|
||||
},
|
||||
"chalk": {
|
||||
"version": "4.1.1",
|
||||
"resolved": "https://registry.npmjs.org/chalk/-/chalk-4.1.1.tgz",
|
||||
"integrity": "sha512-diHzdDKxcU+bAsUboHLPEDQiw0qEe0qd7SYUn3HgcFlWgbDcfLGswOHYeGrHKzG9z6UYf01d9VFMfZxPM1xZSg==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"ansi-styles": "^4.1.0",
|
||||
"supports-color": "^7.1.0"
|
||||
}
|
||||
},
|
||||
"color-convert": {
|
||||
"version": "2.0.1",
|
||||
"resolved": "https://registry.npmjs.org/color-convert/-/color-convert-2.0.1.tgz",
|
||||
"integrity": "sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"color-name": "~1.1.4"
|
||||
}
|
||||
},
|
||||
"color-name": {
|
||||
"version": "1.1.4",
|
||||
"resolved": "https://registry.npmjs.org/color-name/-/color-name-1.1.4.tgz",
|
||||
"integrity": "sha512-dOy+3AuW3a2wNbZHIuMZpTcgjGuLU/uBL/ubcZF9OXbDo8ff4O8yVp5Bf0efS8uEoYo5q4Fx7dY9OgQGXgAsQA==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"has-flag": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/has-flag/-/has-flag-4.0.0.tgz",
|
||||
"integrity": "sha512-EykJT/Q1KjTWctppgIAgfSO0tKVuZUjhgMr17kqTumMl6Afv3EISleU7qZUzoXDFTAHTDC4NOoG/ZxU3EvlMPQ==",
|
||||
"dev": true,
|
||||
"optional": true
|
||||
},
|
||||
"loader-utils": {
|
||||
"version": "2.0.0",
|
||||
"resolved": "https://registry.npmjs.org/loader-utils/-/loader-utils-2.0.0.tgz",
|
||||
"integrity": "sha512-rP4F0h2RaWSvPEkD7BLDFQnvSf+nK+wr3ESUjNTyAGobqrijmW92zc+SO6d4p4B1wh7+B/Jg1mkQe5NYUEHtHQ==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"big.js": "^5.2.2",
|
||||
"emojis-list": "^3.0.0",
|
||||
"json5": "^2.1.2"
|
||||
}
|
||||
},
|
||||
"supports-color": {
|
||||
"version": "7.2.0",
|
||||
"resolved": "https://registry.npmjs.org/supports-color/-/supports-color-7.2.0.tgz",
|
||||
"integrity": "sha512-qpCAvRl9stuOHveKsn7HncJRvv501qIacKzQlO/+Lwxc9+0q2wLyv4Dfvt80/DPn2pqOBsJdDiogXGR9+OvwRw==",
|
||||
"dev": true,
|
||||
"optional": true,
|
||||
"requires": {
|
||||
"has-flag": "^4.0.0"
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
"vue-router": {
|
||||
"version": "3.4.4",
|
||||
"resolved": "https://registry.npmjs.org/vue-router/-/vue-router-3.4.4.tgz",
|
||||
@ -15100,9 +15144,9 @@
|
||||
}
|
||||
},
|
||||
"ws": {
|
||||
"version": "7.3.1",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.3.1.tgz",
|
||||
"integrity": "sha512-D3RuNkynyHmEJIpD2qrgVkc9DQ23OrN/moAwZX4L8DfvszsJxpjQuUq3LMx6HoYji9fbIOBY18XWBsAux1ZZUA==",
|
||||
"version": "7.5.3",
|
||||
"resolved": "https://registry.npmjs.org/ws/-/ws-7.5.3.tgz",
|
||||
"integrity": "sha512-kQ/dHIzuLrS6Je9+uv81ueZomEwH0qVYstcAQ4/Z93K8zeko9gtAbttJWzoC5ukqXY1PpoouV3+VSOqEAFt5wg==",
|
||||
"dev": true
|
||||
},
|
||||
"xml-name-validator": {
|
||||
@ -15124,9 +15168,9 @@
|
||||
"dev": true
|
||||
},
|
||||
"y18n": {
|
||||
"version": "4.0.0",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.0.tgz",
|
||||
"integrity": "sha512-r9S/ZyXu/Xu9q1tYlpsLIsa3EeLXXk0VwlxqTcFRfg9EhMW+17kbt9G0NrgCmhGb5vT2hyhJZLfDGx+7+5Uj/w==",
|
||||
"version": "4.0.3",
|
||||
"resolved": "https://registry.npmjs.org/y18n/-/y18n-4.0.3.tgz",
|
||||
"integrity": "sha512-JKhqTOwSrqNA1NY5lSztJ1GrBiUodLMmIZuLiDaMRJ+itFd+ABVE8XBjOvIWL+rSqNDC74LCSFmlb/U4UZ4hJQ==",
|
||||
"dev": true
|
||||
},
|
||||
"yallist": {
|
||||
|
Loading…
Reference in New Issue
Block a user