diff --git a/CHANGELOG.md b/CHANGELOG.md
index 23f78053..e6d693af 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,3 +1,17 @@
+# 0.90.69 (09-18-2020)
+- Fixed issue with service view not loading. #808 #811 #800
+
+# 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)
+- Fixed Custom OAuth response_type issue
+- Added Configs tab in Settings to edit the config.yml from frontend
+
+# 0.90.67 (09-14-2020)
+- Modified core settings to update config.yml on save
+- Modified Theme Editor to restart the HTTP router on create/delete (fixing 404's)
+
# 0.90.66 (09-08-2020)
- Added Import and Export views in Dashboard
- Modified services list sparkline to use start/end of day timestamp
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/database/database.go b/database/database.go
index c6136cfc..79b6fc2a 100644
--- a/database/database.go
+++ b/database/database.go
@@ -169,10 +169,6 @@ func Available(db Database) bool {
return true
}
-func AmountGreaterThan1000(db *gorm.DB) *gorm.DB {
- return db.Where("service = ?", 1000)
-}
-
func (it *Db) MultipleSelects(args ...string) Database {
joined := strings.Join(args, ", ")
return it.Select(joined)
@@ -181,6 +177,7 @@ func (it *Db) MultipleSelects(args ...string) Database {
type Db struct {
Database *gorm.DB
Type string
+ ReadOnly bool
}
// Openw is a drop-in replacement for Open()
@@ -223,6 +220,9 @@ func OpenTester() (Database, error) {
default:
dbString = fmt.Sprintf("file:%s?mode=memory&cache=shared", utils.RandomString(12))
}
+ if utils.Params.IsSet("DB_DSN") {
+ dbString = utils.Params.GetString("DB_DSN")
+ }
newDb, err := Openw(testDB, dbString)
if err != nil {
return nil, err
@@ -239,6 +239,7 @@ func Wrap(db *gorm.DB) Database {
return &Db{
Database: db,
Type: db.Dialect().GetName(),
+ ReadOnly: utils.Params.GetBool("READ_ONLY"),
}
}
@@ -379,14 +380,26 @@ func (it *Db) Related(value interface{}, foreignKeys ...string) Database {
}
func (it *Db) FirstOrInit(out interface{}, where ...interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.FirstOrInit(out, where...))
}
func (it *Db) FirstOrCreate(out interface{}, where ...interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.FirstOrCreate(out, where...))
}
func (it *Db) Update(attrs ...interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.Update(attrs...))
}
@@ -395,22 +408,42 @@ func (it *Db) Updates(values interface{}, ignoreProtectedAttrs ...bool) Database
}
func (it *Db) UpdateColumn(attrs ...interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.UpdateColumn(attrs...))
}
func (it *Db) UpdateColumns(values interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.UpdateColumns(values))
}
func (it *Db) Save(value interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.Save(value))
}
func (it *Db) Create(value interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.Create(value))
}
func (it *Db) Delete(value interface{}, where ...interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.Delete(value, where...))
}
@@ -435,14 +468,26 @@ func (it *Db) Debug() Database {
}
func (it *Db) Begin() Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.Begin())
}
func (it *Db) Commit() Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.Commit())
}
func (it *Db) Rollback() Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.Rollback())
}
@@ -455,14 +500,26 @@ func (it *Db) RecordNotFound() bool {
}
func (it *Db) CreateTable(values ...interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.CreateTable(values...))
}
func (it *Db) DropTable(values ...interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.DropTable(values...))
}
func (it *Db) DropTableIfExists(values ...interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.DropTableIfExists(values...))
}
@@ -471,26 +528,50 @@ func (it *Db) HasTable(value interface{}) bool {
}
func (it *Db) AutoMigrate(values ...interface{}) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.AutoMigrate(values...))
}
func (it *Db) ModifyColumn(column string, typ string) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.ModifyColumn(column, typ))
}
func (it *Db) DropColumn(column string) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.DropColumn(column))
}
func (it *Db) AddIndex(indexName string, columns ...string) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.AddIndex(indexName, columns...))
}
func (it *Db) AddUniqueIndex(indexName string, columns ...string) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.AddUniqueIndex(indexName, columns...))
}
func (it *Db) RemoveIndex(indexName string) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.RemoveIndex(indexName))
}
@@ -519,6 +600,10 @@ func (it *Db) SetJoinTableHandler(source interface{}, column string, handler gor
}
func (it *Db) AddForeignKey(field string, dest string, onDelete string, onUpdate string) Database {
+ if it.ReadOnly {
+ it.Database.Error = nil
+ return Wrap(it.Database)
+ }
return Wrap(it.Database.AddForeignKey(field, dest, onDelete, onUpdate))
}
diff --git a/database/routines.go b/database/routines.go
index 92583e64..591277da 100644
--- a/database/routines.go
+++ b/database/routines.go
@@ -16,6 +16,8 @@ var (
// Maintenance will automatically delete old records from 'failures' and 'hits'
// this function is currently set to delete records 7+ days old every 60 minutes
+// env: REMOVE_AFTER - golang duration parsed time for deleting records older than REMOVE_AFTER duration from now
+// env: CLEANUP_INTERVAL - golang duration parsed time for checking old records routine
func Maintenance() {
dur := utils.Params.GetDuration("REMOVE_AFTER")
interval := utils.Params.GetDuration("CLEANUP_INTERVAL")
diff --git a/dev/kubernetes.yml b/dev/kubernetes.yml
new file mode 100644
index 00000000..15033baa
--- /dev/null
+++ b/dev/kubernetes.yml
@@ -0,0 +1,42 @@
+apiVersion: v1
+kind: Service
+metadata:
+ name: statping
+spec:
+ ports:
+ - port: 8080
+ selector:
+ app: statping
+ clusterIP: None
+---
+apiVersion: apps/v1
+kind: Deployment
+metadata:
+ name: statping
+spec:
+ selector:
+ matchLabels:
+ app: statping
+ strategy:
+ type: Recreate
+ template:
+ metadata:
+ labels:
+ app: statping
+ spec:
+ containers:
+ - image: statping/statping
+ name: statping
+ env:
+ - name: ALLOW_REPORTS
+ value: "true"
+ ports:
+ - containerPort: 8080
+ name: statping
+ volumeMounts:
+ - name: statping-storage
+ mountPath: /app
+ volumes:
+ - name: statping-storage
+ persistentVolumeClaim:
+ claimName: statping-claim
diff --git a/frontend/src/API.js b/frontend/src/API.js
index 8a0d3fcc..3edd8702 100644
--- a/frontend/src/API.js
+++ b/frontend/src/API.js
@@ -7,8 +7,8 @@ const tokenKey = "statping_auth";
class Api {
constructor() {
- this.version = "0.90.66";
- this.commit = "a3ce4124f654b13c7f2af88b8410f998bd57fcef";
+ this.version = "0.90.67";
+ this.commit = "7e121335791d2143a2eefd404dbcce83b8f46f61";
}
async oauth() {
@@ -261,6 +261,14 @@ class Api {
})
}
+ async configs() {
+ 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/assets/scss/layout.scss b/frontend/src/assets/scss/layout.scss
index 974c9f39..59b82352 100644
--- a/frontend/src/assets/scss/layout.scss
+++ b/frontend/src/assets/scss/layout.scss
@@ -10,10 +10,6 @@ A {
color: $text-color;
}
-A:HOVER {
- color: lighten($text-color, 12%) !important;
-}
-
.modal-backdrop {
position: absolute;
top: 0;
@@ -21,7 +17,7 @@ A:HOVER {
z-index: 1040;
width: 100%;
height: 100%;
- background-color: rgb(0 0 0 / 50%);
+ background-color: rgba(0, 0, 0, 0.5);
}
.modal {
diff --git a/frontend/src/components/Dashboard/Configs.vue b/frontend/src/components/Dashboard/Configs.vue
new file mode 100644
index 00000000..0d2977b6
--- /dev/null
+++ b/frontend/src/components/Dashboard/Configs.vue
@@ -0,0 +1,67 @@
+
+Configuration
+ For security reasons, all database credentials cannot be editted from this page.
+
+
You can even run Statping on your Raspberry Pi by installing the precompiled binary from Latest Releases. For the Raspberry Pi 3 you’ll want to download the statping-linux-arm7.tar.gz
file. Be sure to change VERSION
to the latest version in Releases, and include the ‘v’.
VERSION=$(curl -sL "https://github.com/statping/statping/releases/latest" | grep -o 'tag/[v.0-9]*' | awk -F/ '{print $2}' | head -n1)
-wget https://github.com/statping/statping/releases/download/$VERSION/statping-linux-arm7.tar.gz
-tar -xvzf statping-linux-arm7.tar.gz
+wget https://github.com/statping/statping/releases/download/$VERSION/statping-linux-arm-7.tar.gz
+tar -xvzf statping-linux-arm-7.tar.gz
chmod +x statping
mv statping /usr/local/bin/statping
@@ -2275,7 +2275,7 @@ OluFxewsEO0QNDrfFb+0gnjYlnGqOFcZjUMXbDdY5oLSPtXohynuTK1qyQ==