frontend change, oauth fixes

pull/821/head
hunterlong 2020-09-17 21:14:27 -07:00
parent edeac80ee7
commit 4fec05c43e
17 changed files with 110 additions and 24 deletions

View File

@ -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 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 READ_ONLY env for a read only connection to the database
- Added Custom OAuth OpenID toggle switch in settings (appends 'openid' in scope) - Added Custom OAuth OpenID toggle switch in settings (appends 'openid' in scope)

View File

@ -18,6 +18,10 @@ import (
"time" "time"
) )
var (
importAll *bool
)
func assetsCli() error { func assetsCli() error {
dir := utils.Directory dir := utils.Directory
if err := utils.InitLogs(); err != nil { if err := utils.InitLogs(); err != nil {
@ -254,6 +258,9 @@ func importCli(args []string) error {
if len(exportData.Messages) > 0 { if len(exportData.Messages) > 0 {
log.Printf("Messages: %d\n", len(exportData.Messages)) 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 { if len(exportData.Users) > 0 {
log.Printf("Users: %d\n", len(exportData.Users)) log.Printf("Users: %d\n", len(exportData.Users))
} }
@ -285,14 +292,14 @@ func importCli(args []string) error {
if ask("Import Core settings?") { if ask("Import Core settings?") {
c := exportData.Core c := exportData.Core
if err := c.Update(); err != nil { if err := c.Update(); err != nil {
return err log.Errorln(err)
} }
} }
for _, s := range exportData.Groups { for _, s := range exportData.Groups {
if ask(fmt.Sprintf("Import Group '%s'?", s.Name)) { if ask(fmt.Sprintf("Import Group '%s'?", s.Name)) {
s.Id = 0 s.Id = 0
if err := s.Create(); err != nil { 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)) { if ask(fmt.Sprintf("Import Service '%s'?", s.Name)) {
s.Id = 0 s.Id = 0
if err := s.Create(); err != nil { 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)) { if ask(fmt.Sprintf("Import Checkin '%s'?", s.Name)) {
s.Id = 0 s.Id = 0
if err := s.Create(); err != nil { 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)) { if ask(fmt.Sprintf("Import Message '%s'?", s.Title)) {
s.Id = 0 s.Id = 0
if err := s.Create(); err != nil { 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 { func ask(format string) bool {
fmt.Printf(fmt.Sprintf(format + " [y/N]: ")) fmt.Printf(fmt.Sprintf(format + " [y/N]: "))
reader := bufio.NewReader(os.Stdin) reader := bufio.NewReader(os.Stdin)
text, _ := reader.ReadString('\n') text, _ := reader.ReadString('\n')

View File

@ -265,6 +265,10 @@ class Api {
return axios.get('api/settings/configs').then(response => (response.data)) || [] 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() { token() {
return $cookies.get(tokenKey); return $cookies.get(tokenKey);
} }

View File

@ -5,6 +5,7 @@
<codemirror v-show="loaded" v-model="configs" ref="configs" :options="cmOptions" class="mt-4 codemirrorInput"/> <codemirror v-show="loaded" v-model="configs" ref="configs" :options="cmOptions" class="mt-4 codemirrorInput"/>
<button @click.prevent="save" class="btn col-12 btn-primary mt-3">Save</button>
</div> </div>
</template> </template>
@ -23,7 +24,7 @@ name: "Configs",
data() { data() {
return { return {
loaded: false, loaded: false,
configs: "okkoko: okokoko", configs: null,
cmOptions: { cmOptions: {
height: 700, height: 700,
tabSize: 4, tabSize: 4,
@ -35,14 +36,27 @@ name: "Configs",
} }
}, },
mounted() { mounted() {
this.loaded = false
this.update() this.update()
this.loaded = true
},
watch: {
"configs" () {
this.$refs.configs.codemirror.refresh()
}
}, },
methods: { methods: {
async update() { async update() {
this.loaded = false
this.configs = await Api.configs() this.configs = await Api.configs()
this.loaded = true this.$refs.configs.codemirror.value = this.configs
this.$refs.configs.codemirror.refresh() this.$refs.configs.codemirror.refresh()
},
async save() {
try {
await Api.configs_save(this.configs)
} catch(e) {
window.console.error(e)
}
} }
} }
} }

View File

@ -9,6 +9,7 @@ const chinese = {
logout: "注销", logout: "注销",
online: "在线", online: "在线",
offline: "离线", offline: "离线",
configs: "配置",
username: "用户名", username: "用户名",
password: "密码", password: "密码",
email: "电子邮件", email: "电子邮件",

View File

@ -9,6 +9,7 @@ const english = {
logout: "Logout", logout: "Logout",
online: "Online", online: "Online",
offline: "Offline", offline: "Offline",
configs: "Configuration",
username: "Username", username: "Username",
password: "Password", password: "Password",
email: "Email", email: "Email",

View File

@ -9,6 +9,7 @@ const french = {
logout: "Déconnexion", logout: "Déconnexion",
online: "En ligne", online: "En ligne",
offline: "Offline", offline: "Offline",
configs: "Configuration",
username: "Nom d'utilisateur", username: "Nom d'utilisateur",
password: "mot de passe", password: "mot de passe",
email: "Email", email: "Email",

View File

@ -9,6 +9,7 @@ const german = {
logout: "Abmelden", logout: "Abmelden",
online: "Online", online: "Online",
offline: "Offline", offline: "Offline",
configs: "Konfiguration",
username: "Benutzername", username: "Benutzername",
password: "Kennwort", password: "Kennwort",
email: "Mail", email: "Mail",

View File

@ -9,6 +9,7 @@ const italian = {
logout: "Disconnetti", logout: "Disconnetti",
online: "Online", online: "Online",
offline: "Offline", offline: "Offline",
configs: "Configurazione",
username: "Nome utente", username: "Nome utente",
password: "Password", password: "Password",
email: "E-mail", email: "E-mail",

View File

@ -9,6 +9,7 @@ const japanese = {
logout: "ログアウト", logout: "ログアウト",
online: "オンライン", online: "オンライン",
offline: "オフライン", offline: "オフライン",
configs: "構成",
username: "ユーザ名", username: "ユーザ名",
password: "パスワード", password: "パスワード",
email: "Eメール", email: "Eメール",

View File

@ -9,6 +9,7 @@ const korean = {
logout: "로그아웃", logout: "로그아웃",
online: "온라인", online: "온라인",
offline: "오프라인", offline: "오프라인",
configs: "구성",
username: "사용자 이름", username: "사용자 이름",
password: "비밀번호", password: "비밀번호",
email: "이메일", email: "이메일",

View File

@ -9,6 +9,7 @@ const russian = {
logout: "Выход из системы", logout: "Выход из системы",
online: "Онлайн", online: "Онлайн",
offline: "Оффлайн", offline: "Оффлайн",
configs: "Конфигурация",
username: "Имя пользователя", username: "Имя пользователя",
password: "Пароль", password: "Пароль",
email: "Электронная почта", email: "Электронная почта",

View File

@ -9,6 +9,7 @@ const spanish = {
logout: "Cerrar sesión", logout: "Cerrar sesión",
online: "En línea", online: "En línea",
offline: "Offline", offline: "Offline",
configs: "Configuración",
username: "Nombre de usuario", username: "Nombre de usuario",
password: "Contraseña", password: "Contraseña",
email: "Correo", email: "Correo",

View File

@ -34,7 +34,7 @@
<font-awesome-icon icon="cloud-download-alt" class="mr-2"/> {{ $t('import') }} <font-awesome-icon icon="cloud-download-alt" class="mr-2"/> {{ $t('import') }}
</a> </a>
<a @click.prevent="changeTab" class="nav-link" v-bind:class="{active: liClass('v-pills-configs-tab')}" id="v-pills-configs-tab" data-toggle="pill" href="#v-pills-configs" role="tab" aria-controls="v-pills-configs" aria-selected="false"> <a @click.prevent="changeTab" class="nav-link" v-bind:class="{active: liClass('v-pills-configs-tab')}" id="v-pills-configs-tab" data-toggle="pill" href="#v-pills-configs" role="tab" aria-controls="v-pills-configs" aria-selected="false">
<font-awesome-icon icon="cloud-download-alt" class="mr-2"/> {{ $t('configs') }} <font-awesome-icon icon="cogs" class="mr-2"/> {{ $t('configs') }}
</a> </a>
<h6 class="mt-4 text-muted">{{$t('notifiers')}}</h6> <h6 class="mt-4 text-muted">{{$t('notifiers')}}</h6>

View File

@ -10,11 +10,13 @@ import (
"github.com/statping/statping/types/core" "github.com/statping/statping/types/core"
"github.com/statping/statping/types/errors" "github.com/statping/statping/types/errors"
"github.com/statping/statping/types/groups" "github.com/statping/statping/types/groups"
"github.com/statping/statping/types/incidents"
"github.com/statping/statping/types/messages" "github.com/statping/statping/types/messages"
"github.com/statping/statping/types/notifications" "github.com/statping/statping/types/notifications"
"github.com/statping/statping/types/services" "github.com/statping/statping/types/services"
"github.com/statping/statping/types/users" "github.com/statping/statping/types/users"
"github.com/statping/statping/utils" "github.com/statping/statping/utils"
"gopkg.in/yaml.v2"
"io" "io"
"io/ioutil" "io/ioutil"
"net/http" "net/http"
@ -162,14 +164,16 @@ func apiThemeRemoveHandler(w http.ResponseWriter, r *http.Request) {
} }
type ExportData struct { type ExportData struct {
Config *configs.DbConfig `json:"config,omitempty"` Config *configs.DbConfig `json:"config,omitempty"`
Core *core.Core `json:"core"` Core *core.Core `json:"core"`
Services []services.Service `json:"services"` Services []services.Service `json:"services"`
Messages []*messages.Message `json:"messages"` Messages []*messages.Message `json:"messages"`
Checkins []*checkins.Checkin `json:"checkins"` Incidents []*incidents.Incident `json:"incidents"`
Users []*users.User `json:"users"` IncidentUpdates []*incidents.IncidentUpdate `json:"incident_updates"`
Groups []*groups.Group `json:"groups"` Checkins []*checkins.Checkin `json:"checkins"`
Notifiers []notifications.Notification `json:"notifiers"` Users []*users.User `json:"users"`
Groups []*groups.Group `json:"groups"`
Notifiers []notifications.Notification `json:"notifiers"`
} }
func (e *ExportData) JSON() []byte { 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) { 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) { func configsViewHandler(w http.ResponseWriter, r *http.Request) {
@ -271,7 +300,7 @@ func configsViewHandler(w http.ResponseWriter, r *http.Request) {
sendErrorJson(err, w, r) sendErrorJson(err, w, r)
return return
} }
w.Write(db.ToYAML()) w.Write(db.Clean().ToYAML())
} }
func settingsExportHandler(w http.ResponseWriter, r *http.Request) { func settingsExportHandler(w http.ResponseWriter, r *http.Request) {

View File

@ -18,6 +18,28 @@ func (d *DbConfig) Save(directory string) error {
return nil 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 { func (d *DbConfig) ToYAML() []byte {
c, err := yaml.Marshal(d) c, err := yaml.Marshal(d)
if err != nil { if err != nil {

View File

@ -6,15 +6,15 @@ const SqliteFilename = "statping.db"
// DbConfig struct is used for the Db connection and creates the 'config.yml' file // DbConfig struct is used for the Db connection and creates the 'config.yml' file
type DbConfig struct { type DbConfig struct {
DbConn string `yaml:"connection" json:"connection"` DbConn string `yaml:"connection,omitempty" json:"connection"`
DbHost string `yaml:"host,omitempty" json:"-"` DbHost string `yaml:"host,omitempty" json:"-"`
DbUser string `yaml:"user,omitempty" json:"-"` DbUser string `yaml:"user,omitempty" json:"-"`
DbPass string `yaml:"password,omitempty" json:"-"` DbPass string `yaml:"password,omitempty" json:"-"`
DbData string `yaml:"database,omitempty" json:"-"` DbData string `yaml:"database,omitempty" json:"-"`
DbPort int `yaml:"port,omitempty" json:"-"` DbPort int `yaml:"port,omitempty" json:"-"`
ApiSecret string `yaml:"api_secret" json:"-"` ApiSecret string `yaml:"api_secret,omitempty" json:"-"`
Language string `yaml:"language" json:"language"` Language string `yaml:"language,omitempty" json:"language"`
AllowReports bool `yaml:"allow_reports" json:"allow_reports"` AllowReports bool `yaml:"allow_reports,omitempty" json:"allow_reports"`
Project string `yaml:"-" json:"-"` Project string `yaml:"-" json:"-"`
Description string `yaml:"-" json:"-"` Description string `yaml:"-" json:"-"`
Domain string `yaml:"-" json:"-"` Domain string `yaml:"-" json:"-"`
@ -22,7 +22,7 @@ type DbConfig struct {
Password string `yaml:"-" json:"-"` Password string `yaml:"-" json:"-"`
Email string `yaml:"-" json:"-"` Email string `yaml:"-" json:"-"`
Error error `yaml:"-" json:"-"` Error error `yaml:"-" json:"-"`
Location string `yaml:"location" json:"-"` Location string `yaml:"location,omitempty" json:"-"`
SqlFile string `yaml:"sqlfile,omitempty" json:"-"` SqlFile string `yaml:"sqlfile,omitempty" json:"-"`
LetsEncryptHost string `yaml:"letsencrypt_host,omitempty" json:"letsencrypt_host"` LetsEncryptHost string `yaml:"letsencrypt_host,omitempty" json:"letsencrypt_host"`
LetsEncryptEmail string `yaml:"letsencrypt_email,omitempty" json:"letsencrypt_email"` LetsEncryptEmail string `yaml:"letsencrypt_email,omitempty" json:"letsencrypt_email"`