diff --git a/CHANGELOG.md b/CHANGELOG.md
index b61565f2..21c48215 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,4 +1,4 @@
-# 0.90.68 (09-15-2020)
+# 0.90.68 (09-17-2020)
- Added DB_DSN env for mysql, postgres or sqlite DSN database connection string
- Added READ_ONLY env for a read only connection to the database
- Added Custom OAuth OpenID toggle switch in settings (appends 'openid' in scope)
diff --git a/cmd/cli.go b/cmd/cli.go
index 0dd2c966..4f06b8e1 100644
--- a/cmd/cli.go
+++ b/cmd/cli.go
@@ -18,6 +18,10 @@ import (
"time"
)
+var (
+ importAll *bool
+)
+
func assetsCli() error {
dir := utils.Directory
if err := utils.InitLogs(); err != nil {
@@ -254,6 +258,9 @@ func importCli(args []string) error {
if len(exportData.Messages) > 0 {
log.Printf("Messages: %d\n", len(exportData.Messages))
}
+ if len(exportData.Incidents) > 0 {
+ log.Printf("Incidents: %d\n", len(exportData.Incidents))
+ }
if len(exportData.Users) > 0 {
log.Printf("Users: %d\n", len(exportData.Users))
}
@@ -285,14 +292,14 @@ func importCli(args []string) error {
if ask("Import Core settings?") {
c := exportData.Core
if err := c.Update(); err != nil {
- return err
+ log.Errorln(err)
}
}
for _, s := range exportData.Groups {
if ask(fmt.Sprintf("Import Group '%s'?", s.Name)) {
s.Id = 0
if err := s.Create(); err != nil {
- return err
+ log.Errorln(err)
}
}
}
@@ -300,7 +307,7 @@ func importCli(args []string) error {
if ask(fmt.Sprintf("Import Service '%s'?", s.Name)) {
s.Id = 0
if err := s.Create(); err != nil {
- return err
+ log.Errorln(err)
}
}
}
@@ -308,7 +315,7 @@ func importCli(args []string) error {
if ask(fmt.Sprintf("Import Checkin '%s'?", s.Name)) {
s.Id = 0
if err := s.Create(); err != nil {
- return err
+ log.Errorln(err)
}
}
}
@@ -316,7 +323,7 @@ func importCli(args []string) error {
if ask(fmt.Sprintf("Import Message '%s'?", s.Title)) {
s.Id = 0
if err := s.Create(); err != nil {
- return err
+ log.Errorln(err)
}
}
}
@@ -333,6 +340,7 @@ func importCli(args []string) error {
}
func ask(format string) bool {
+
fmt.Printf(fmt.Sprintf(format + " [y/N]: "))
reader := bufio.NewReader(os.Stdin)
text, _ := reader.ReadString('\n')
diff --git a/frontend/src/API.js b/frontend/src/API.js
index 0f0aff89..3edd8702 100644
--- a/frontend/src/API.js
+++ b/frontend/src/API.js
@@ -265,6 +265,10 @@ class Api {
return axios.get('api/settings/configs').then(response => (response.data)) || []
}
+ async configs_save(data) {
+ return axios.post('api/settings/configs', data).then(response => (response.data)) || []
+ }
+
token() {
return $cookies.get(tokenKey);
}
diff --git a/frontend/src/components/Dashboard/Configs.vue b/frontend/src/components/Dashboard/Configs.vue
index 9e0dca5a..0d2977b6 100644
--- a/frontend/src/components/Dashboard/Configs.vue
+++ b/frontend/src/components/Dashboard/Configs.vue
@@ -5,6 +5,7 @@
+
@@ -23,7 +24,7 @@ name: "Configs",
data() {
return {
loaded: false,
- configs: "okkoko: okokoko",
+ configs: null,
cmOptions: {
height: 700,
tabSize: 4,
@@ -35,14 +36,27 @@ name: "Configs",
}
},
mounted() {
+ this.loaded = false
this.update()
+ this.loaded = true
+ },
+ watch: {
+ "configs" () {
+ this.$refs.configs.codemirror.refresh()
+ }
},
methods: {
async update() {
- this.loaded = false
this.configs = await Api.configs()
- this.loaded = true
+ this.$refs.configs.codemirror.value = this.configs
this.$refs.configs.codemirror.refresh()
+ },
+ async save() {
+ try {
+ await Api.configs_save(this.configs)
+ } catch(e) {
+ window.console.error(e)
+ }
}
}
}
diff --git a/frontend/src/languages/chinese.js b/frontend/src/languages/chinese.js
index 162e6d58..e594cf48 100755
--- a/frontend/src/languages/chinese.js
+++ b/frontend/src/languages/chinese.js
@@ -9,6 +9,7 @@ const chinese = {
logout: "注销",
online: "在线",
offline: "离线",
+ configs: "配置",
username: "用户名",
password: "密码",
email: "电子邮件",
diff --git a/frontend/src/languages/english.js b/frontend/src/languages/english.js
index c737223f..cd34b643 100644
--- a/frontend/src/languages/english.js
+++ b/frontend/src/languages/english.js
@@ -9,6 +9,7 @@ const english = {
logout: "Logout",
online: "Online",
offline: "Offline",
+ configs: "Configuration",
username: "Username",
password: "Password",
email: "Email",
diff --git a/frontend/src/languages/french.js b/frontend/src/languages/french.js
index d448af30..4115f01c 100644
--- a/frontend/src/languages/french.js
+++ b/frontend/src/languages/french.js
@@ -9,6 +9,7 @@ const french = {
logout: "Déconnexion",
online: "En ligne",
offline: "Offline",
+ configs: "Configuration",
username: "Nom d'utilisateur",
password: "mot de passe",
email: "Email",
diff --git a/frontend/src/languages/german.js b/frontend/src/languages/german.js
index aabba35f..e9f80593 100644
--- a/frontend/src/languages/german.js
+++ b/frontend/src/languages/german.js
@@ -9,6 +9,7 @@ const german = {
logout: "Abmelden",
online: "Online",
offline: "Offline",
+ configs: "Konfiguration",
username: "Benutzername",
password: "Kennwort",
email: "Mail",
diff --git a/frontend/src/languages/italian.js b/frontend/src/languages/italian.js
index 90cff78d..ccf9a417 100755
--- a/frontend/src/languages/italian.js
+++ b/frontend/src/languages/italian.js
@@ -9,6 +9,7 @@ const italian = {
logout: "Disconnetti",
online: "Online",
offline: "Offline",
+ configs: "Configurazione",
username: "Nome utente",
password: "Password",
email: "E-mail",
diff --git a/frontend/src/languages/japanese.js b/frontend/src/languages/japanese.js
index 8e1c9cbf..eed5a90c 100755
--- a/frontend/src/languages/japanese.js
+++ b/frontend/src/languages/japanese.js
@@ -9,6 +9,7 @@ const japanese = {
logout: "ログアウト",
online: "オンライン",
offline: "オフライン",
+ configs: "構成",
username: "ユーザ名",
password: "パスワード",
email: "Eメール",
diff --git a/frontend/src/languages/korean.js b/frontend/src/languages/korean.js
index 6939dec7..2cba872f 100755
--- a/frontend/src/languages/korean.js
+++ b/frontend/src/languages/korean.js
@@ -9,6 +9,7 @@ const korean = {
logout: "로그아웃",
online: "온라인",
offline: "오프라인",
+ configs: "구성",
username: "사용자 이름",
password: "비밀번호",
email: "이메일",
diff --git a/frontend/src/languages/russian.js b/frontend/src/languages/russian.js
index 4f9d89e9..4a578938 100644
--- a/frontend/src/languages/russian.js
+++ b/frontend/src/languages/russian.js
@@ -9,6 +9,7 @@ const russian = {
logout: "Выход из системы",
online: "Онлайн",
offline: "Оффлайн",
+ configs: "Конфигурация",
username: "Имя пользователя",
password: "Пароль",
email: "Электронная почта",
diff --git a/frontend/src/languages/spanish.js b/frontend/src/languages/spanish.js
index aa7457b6..ea6e4293 100644
--- a/frontend/src/languages/spanish.js
+++ b/frontend/src/languages/spanish.js
@@ -9,6 +9,7 @@ const spanish = {
logout: "Cerrar sesión",
online: "En línea",
offline: "Offline",
+ configs: "Configuración",
username: "Nombre de usuario",
password: "Contraseña",
email: "Correo",
diff --git a/frontend/src/pages/Settings.vue b/frontend/src/pages/Settings.vue
index 9235a548..1f8a8016 100644
--- a/frontend/src/pages/Settings.vue
+++ b/frontend/src/pages/Settings.vue
@@ -34,7 +34,7 @@
{{ $t('import') }}
- {{ $t('configs') }}
+ {{ $t('configs') }}
{{$t('notifiers')}}
diff --git a/handlers/dashboard.go b/handlers/dashboard.go
index 8fb67ef8..4d50323d 100644
--- a/handlers/dashboard.go
+++ b/handlers/dashboard.go
@@ -10,11 +10,13 @@ import (
"github.com/statping/statping/types/core"
"github.com/statping/statping/types/errors"
"github.com/statping/statping/types/groups"
+ "github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services"
"github.com/statping/statping/types/users"
"github.com/statping/statping/utils"
+ "gopkg.in/yaml.v2"
"io"
"io/ioutil"
"net/http"
@@ -162,14 +164,16 @@ func apiThemeRemoveHandler(w http.ResponseWriter, r *http.Request) {
}
type ExportData struct {
- Config *configs.DbConfig `json:"config,omitempty"`
- Core *core.Core `json:"core"`
- Services []services.Service `json:"services"`
- Messages []*messages.Message `json:"messages"`
- Checkins []*checkins.Checkin `json:"checkins"`
- Users []*users.User `json:"users"`
- Groups []*groups.Group `json:"groups"`
- Notifiers []notifications.Notification `json:"notifiers"`
+ Config *configs.DbConfig `json:"config,omitempty"`
+ Core *core.Core `json:"core"`
+ Services []services.Service `json:"services"`
+ Messages []*messages.Message `json:"messages"`
+ Incidents []*incidents.Incident `json:"incidents"`
+ IncidentUpdates []*incidents.IncidentUpdate `json:"incident_updates"`
+ Checkins []*checkins.Checkin `json:"checkins"`
+ Users []*users.User `json:"users"`
+ Groups []*groups.Group `json:"groups"`
+ Notifiers []notifications.Notification `json:"notifiers"`
}
func (e *ExportData) JSON() []byte {
@@ -262,7 +266,32 @@ func settingsImportHandler(w http.ResponseWriter, r *http.Request) {
}
func configsSaveHandler(w http.ResponseWriter, r *http.Request) {
+ data, err := ioutil.ReadAll(r.Body)
+ if err != nil {
+ sendErrorJson(err, w, r)
+ return
+ }
+ defer r.Body.Close()
+ var cfg *configs.DbConfig
+ if err := yaml.Unmarshal(data, &cfg); err != nil {
+ sendErrorJson(err, w, r)
+ return
+ }
+
+ oldCfg, err := configs.LoadConfigs(utils.Directory + "/configs.yml")
+ if err != nil {
+ sendErrorJson(err, w, r)
+ return
+ }
+
+ newCfg := cfg.Merge(oldCfg)
+ if err := newCfg.Save(utils.Directory); err != nil {
+ sendErrorJson(err, w, r)
+ return
+ }
+
+ sendJsonAction(newCfg.Clean(), "updated", w, r)
}
func configsViewHandler(w http.ResponseWriter, r *http.Request) {
@@ -271,7 +300,7 @@ func configsViewHandler(w http.ResponseWriter, r *http.Request) {
sendErrorJson(err, w, r)
return
}
- w.Write(db.ToYAML())
+ w.Write(db.Clean().ToYAML())
}
func settingsExportHandler(w http.ResponseWriter, r *http.Request) {
diff --git a/types/configs/methods.go b/types/configs/methods.go
index a9378b27..b0e549f3 100644
--- a/types/configs/methods.go
+++ b/types/configs/methods.go
@@ -18,6 +18,28 @@ func (d *DbConfig) Save(directory string) error {
return nil
}
+// Merge will merge the database connection info into the input
+func (d *DbConfig) Merge(newCfg *DbConfig) *DbConfig {
+ d.DbConn = newCfg.DbConn
+ d.DbHost = newCfg.DbHost
+ d.DbPort = newCfg.DbPort
+ d.DbData = newCfg.DbData
+ d.DbUser = newCfg.DbUser
+ d.DbPass = newCfg.DbPass
+ return d
+}
+
+// Clean hides all sensitive database information for API requests
+func (d *DbConfig) Clean() *DbConfig {
+ d.DbConn = ""
+ d.DbHost = ""
+ d.DbPort = 0
+ d.DbData = ""
+ d.DbUser = ""
+ d.DbPass = ""
+ return d
+}
+
func (d *DbConfig) ToYAML() []byte {
c, err := yaml.Marshal(d)
if err != nil {
diff --git a/types/configs/struct.go b/types/configs/struct.go
index c0f4741a..2917b5e7 100644
--- a/types/configs/struct.go
+++ b/types/configs/struct.go
@@ -6,15 +6,15 @@ const SqliteFilename = "statping.db"
// DbConfig struct is used for the Db connection and creates the 'config.yml' file
type DbConfig struct {
- DbConn string `yaml:"connection" json:"connection"`
+ DbConn string `yaml:"connection,omitempty" json:"connection"`
DbHost string `yaml:"host,omitempty" json:"-"`
DbUser string `yaml:"user,omitempty" json:"-"`
DbPass string `yaml:"password,omitempty" json:"-"`
DbData string `yaml:"database,omitempty" json:"-"`
DbPort int `yaml:"port,omitempty" json:"-"`
- ApiSecret string `yaml:"api_secret" json:"-"`
- Language string `yaml:"language" json:"language"`
- AllowReports bool `yaml:"allow_reports" json:"allow_reports"`
+ ApiSecret string `yaml:"api_secret,omitempty" json:"-"`
+ Language string `yaml:"language,omitempty" json:"language"`
+ AllowReports bool `yaml:"allow_reports,omitempty" json:"allow_reports"`
Project string `yaml:"-" json:"-"`
Description string `yaml:"-" json:"-"`
Domain string `yaml:"-" json:"-"`
@@ -22,7 +22,7 @@ type DbConfig struct {
Password string `yaml:"-" json:"-"`
Email string `yaml:"-" json:"-"`
Error error `yaml:"-" json:"-"`
- Location string `yaml:"location" json:"-"`
+ Location string `yaml:"location,omitempty" json:"-"`
SqlFile string `yaml:"sqlfile,omitempty" json:"-"`
LetsEncryptHost string `yaml:"letsencrypt_host,omitempty" json:"letsencrypt_host"`
LetsEncryptEmail string `yaml:"letsencrypt_email,omitempty" json:"letsencrypt_email"`