mirror of https://github.com/statping/statping
vue
parent
23b230f61f
commit
134bd073ff
5
Makefile
5
Makefile
|
@ -17,6 +17,9 @@ release: dev-deps
|
|||
gpg --import statping.gpg
|
||||
make build-all
|
||||
|
||||
frontend:
|
||||
cd frontend && yarn serve
|
||||
|
||||
# build and push the images to docker hub
|
||||
docker: docker-build-all docker-publish-all
|
||||
|
||||
|
@ -371,5 +374,5 @@ heroku:
|
|||
checkall:
|
||||
golangci-lint run ./...
|
||||
|
||||
.PHONY: all build build-all build-alpine test-all test test-api docker
|
||||
.PHONY: all build build-all build-alpine test-all test test-api docker frontend
|
||||
.SILENT: travis_s3_creds
|
||||
|
|
|
@ -0,0 +1,22 @@
|
|||
import axios from 'axios'
|
||||
|
||||
class Api {
|
||||
constructor() {
|
||||
|
||||
}
|
||||
|
||||
async root () {
|
||||
return axios.get('/api').then(response => (response.data))
|
||||
}
|
||||
|
||||
async services () {
|
||||
return axios.get('/api/services').then(response => (response.data))
|
||||
}
|
||||
|
||||
async groups () {
|
||||
return axios.get('/api/groups').then(response => (response.data))
|
||||
}
|
||||
|
||||
}
|
||||
const api = new Api()
|
||||
export default api
|
|
@ -1,24 +1,13 @@
|
|||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import VueRouter from 'vue-router'
|
||||
import Index from "./components/Pages/Index";
|
||||
const router = require("routes")
|
||||
|
||||
require("./assets/css/bootstrap.min.css")
|
||||
require("./assets/css/base.css")
|
||||
|
||||
Vue.use(VueRouter)
|
||||
|
||||
const router = new VueRouter({
|
||||
routes: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Index',
|
||||
component: Index
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
|
||||
Vue.config.productionTip = false
|
||||
new Vue({
|
||||
router,
|
||||
|
|
|
@ -0,0 +1,75 @@
|
|||
<template>
|
||||
<div class="container col-md-7 col-sm-12 mt-2 sm-container">
|
||||
|
||||
<Header :core="core"/>
|
||||
|
||||
<Group/>
|
||||
<Group/>
|
||||
<Group/>
|
||||
<div v-for="(group, index) in groups" v-bind:key="index">
|
||||
<Group :group=group />
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<MessageBlock/>
|
||||
</div>
|
||||
|
||||
<div class="col-12 full-col-12">
|
||||
|
||||
<div v-for="(service, index) in services" v-bind:key="index">
|
||||
<ServiceBlock :service=service />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ServiceBlock from '../components/Service/ServiceBlock.vue'
|
||||
import MessageBlock from "../components/Index/MessageBlock";
|
||||
import Group from "../components/Index/Group";
|
||||
import Header from "../components/Index/Header";
|
||||
|
||||
export default {
|
||||
name: 'Dashboard',
|
||||
components: {
|
||||
Header,
|
||||
Group,
|
||||
MessageBlock,
|
||||
ServiceBlock,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
services: null,
|
||||
groups: null,
|
||||
core: null,
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
this.getAPI()
|
||||
this.getGroups()
|
||||
this.getServices()
|
||||
},
|
||||
methods: {
|
||||
getAPI: function() {
|
||||
axios
|
||||
.get('/api')
|
||||
.then(response => (this.core = response.data))
|
||||
},
|
||||
getServices: function() {
|
||||
axios
|
||||
.get('/api/services')
|
||||
.then(response => (this.services = response.data))
|
||||
},
|
||||
getGroups: function() {
|
||||
axios
|
||||
.get('/api/groups')
|
||||
.then(response => (this.groups = response.data))
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,61 @@
|
|||
<template>
|
||||
<div v-show="core" class="container col-md-7 col-sm-12 mt-2 sm-container">
|
||||
|
||||
<Header :core="core"/>
|
||||
|
||||
<div v-for="(group, index) in groups" v-bind:key="index">
|
||||
<Group :group=group />
|
||||
</div>
|
||||
|
||||
<div class="col-12">
|
||||
<MessageBlock/>
|
||||
</div>
|
||||
|
||||
<div class="col-12 full-col-12">
|
||||
|
||||
<div v-for="(service, index) in services" v-bind:key="index">
|
||||
<ServiceBlock :service=service />
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import ServiceBlock from '../components/Service/ServiceBlock.vue'
|
||||
import MessageBlock from "../components/Index/MessageBlock";
|
||||
import Group from "../components/Index/Group";
|
||||
import Header from "../components/Index/Header";
|
||||
import Api from "../components/API"
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
components: {
|
||||
Header,
|
||||
Group,
|
||||
MessageBlock,
|
||||
ServiceBlock,
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
services: null,
|
||||
groups: null,
|
||||
core: null,
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
this.loadAll()
|
||||
},
|
||||
methods: {
|
||||
async loadAll () {
|
||||
this.core = await Api.root()
|
||||
this.groups = await Api.groups()
|
||||
this.services = await Api.services()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<div class="container col-md-7 col-sm-12 mt-2 sm-container">
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'Service',
|
||||
components: {
|
||||
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
service: null,
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
</style>
|
|
@ -0,0 +1,30 @@
|
|||
<template>
|
||||
<div class="container col-md-7 col-sm-12 mt-2 sm-container">
|
||||
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
|
||||
export default {
|
||||
name: 'Services',
|
||||
components: {
|
||||
|
||||
},
|
||||
data () {
|
||||
return {
|
||||
services: null,
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
|
||||
},
|
||||
methods: {
|
||||
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<!-- Add "scoped" attribute to limit CSS to this component only -->
|
||||
<style scoped>
|
||||
</style>
|
|
@ -25,15 +25,14 @@
|
|||
</template>
|
||||
|
||||
<script>
|
||||
import ServiceBlock from '../Service/ServiceBlock.vue'
|
||||
import MessageBlock from "../Index/MessageBlock";
|
||||
import Group from "../Index/Group";
|
||||
import Header from "../Index/Header";
|
||||
const axios = require('axios');
|
||||
import ServiceBlock from '../components/Service/ServiceBlock.vue'
|
||||
import MessageBlock from "../components/Index/MessageBlock";
|
||||
import Group from "../components/Index/Group";
|
||||
import Header from "../components/Index/Header";
|
||||
|
||||
|
||||
export default {
|
||||
name: 'Index',
|
||||
name: 'Settings',
|
||||
components: {
|
||||
Header,
|
||||
Group,
|
|
@ -1,5 +1,7 @@
|
|||
import Index from "./components/Pages/Index";
|
||||
import Index from "./pages/Index";
|
||||
import VueRouter from 'vue-router'
|
||||
import Dashboard from "./pages/Dashboard";
|
||||
import Settings from "./pages/Settings";
|
||||
|
||||
const router = new VueRouter({
|
||||
routes: [
|
||||
|
@ -7,6 +9,16 @@ const router = new VueRouter({
|
|||
path: '/',
|
||||
name: 'Index',
|
||||
component: Index
|
||||
},
|
||||
{
|
||||
path: '/dashboard',
|
||||
name: 'Dashboard',
|
||||
component: Dashboard
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
name: 'Settings',
|
||||
component: Settings
|
||||
}
|
||||
]
|
||||
})
|
||||
|
|
|
@ -4,7 +4,7 @@ module.exports = {
|
|||
proxy: {
|
||||
'/api': {
|
||||
logLevel: 'debug',
|
||||
target: 'http://0.0.0.0:8585'
|
||||
target: 'http://0.0.0.0:8282'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -24,6 +24,7 @@ import (
|
|||
"net/http"
|
||||
"os"
|
||||
"path"
|
||||
"reflect"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
|
@ -272,6 +273,66 @@ func returnJson(d interface{}, w http.ResponseWriter, r *http.Request) {
|
|||
json.NewEncoder(w).Encode(d)
|
||||
}
|
||||
|
||||
func safeTypes(obj interface{}) []string {
|
||||
if reflect.ValueOf(obj).Kind() == reflect.Ptr {
|
||||
obj = &obj
|
||||
}
|
||||
switch v := obj.(type) {
|
||||
case types.Service:
|
||||
return types.SafeService
|
||||
default:
|
||||
fmt.Printf("%T\n", v)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func expandServices(s []types.ServiceInterface) []*types.Service {
|
||||
var services []*types.Service
|
||||
for _, v := range s {
|
||||
services = append(services, v.Select())
|
||||
}
|
||||
return services
|
||||
}
|
||||
|
||||
func returnSafeJson(w http.ResponseWriter, r *http.Request, input interface{}) {
|
||||
allData := make([]map[string]*json.RawMessage, 0, 1)
|
||||
s := reflect.ValueOf(input)
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
obj := s.Index(i)
|
||||
allData = append(allData, safeJsonKeys(obj))
|
||||
}
|
||||
returnJson(allData, w, r)
|
||||
}
|
||||
|
||||
func safeJsonKeys(in reflect.Value) map[string]*json.RawMessage {
|
||||
|
||||
thisObj := in.Elem().Interface()
|
||||
nn := make(map[string]*json.RawMessage)
|
||||
|
||||
v := reflect.ValueOf(thisObj)
|
||||
typeOfS := v.Type()
|
||||
fmt.Println("fields: ", v.NumField())
|
||||
for i := 0; i < v.NumField(); i++ {
|
||||
inter := v.Field(i).Interface()
|
||||
fmt.Println(v.Field(i).CanSet())
|
||||
if typeOfS.Field(i).Type.String() == "types.NullString" {
|
||||
ggg := inter.(types.NullString)
|
||||
fmt.Println("OKKOKOK: ", ggg)
|
||||
v.Field(i).SetString(ggg.String)
|
||||
}
|
||||
fmt.Printf("Field: %s\tValue: %v\n", typeOfS.Field(i).Type.String(), v.Field(i).Interface())
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(thisObj)
|
||||
|
||||
json.Unmarshal(data, &nn)
|
||||
removeKeys := safeTypes(thisObj)
|
||||
for _, k := range removeKeys {
|
||||
delete(nn, k)
|
||||
}
|
||||
return nn
|
||||
}
|
||||
|
||||
// error404Handler is a HTTP handler for 404 error pages
|
||||
func error404Handler(w http.ResponseWriter, r *http.Request) {
|
||||
if usingSSL {
|
||||
|
|
|
@ -131,7 +131,7 @@ func Router() *mux.Router {
|
|||
r.Handle("/api/reorder/groups", authenticated(apiGroupReorderHandler, false)).Methods("POST")
|
||||
|
||||
// API SERVICE Routes
|
||||
r.Handle("/api/services", readOnly(apiAllServicesHandler, false)).Methods("GET")
|
||||
r.Handle("/api/services", http.HandlerFunc(apiAllServicesHandler)).Methods("GET")
|
||||
r.Handle("/api/services", authenticated(apiCreateServiceHandler, false)).Methods("POST")
|
||||
r.Handle("/api/services/{id}", readOnly(apiServiceHandler, false)).Methods("GET")
|
||||
r.Handle("/api/reorder/services", authenticated(reorderServiceHandler, false)).Methods("POST")
|
||||
|
|
|
@ -294,7 +294,12 @@ func apiServiceDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func apiAllServicesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
admin := IsAdmin(r)
|
||||
services := core.Services()
|
||||
if !admin {
|
||||
returnSafeJson(w, r, expandServices(services))
|
||||
return
|
||||
}
|
||||
returnJson(services, w, r)
|
||||
}
|
||||
|
||||
|
|
|
@ -0,0 +1,6 @@
|
|||
package types
|
||||
|
||||
var (
|
||||
SafeService = []string{"domain", "expected_status", "expected", "allow_notifications", "headers", "method",
|
||||
"port", "timeout", "status_code", "verify_ssl", "post_data", "type", "check_interval", "failures"}
|
||||
)
|
|
@ -23,7 +23,7 @@ import (
|
|||
type Service struct {
|
||||
Id int64 `gorm:"primary_key;column:id" json:"id"`
|
||||
Name string `gorm:"column:name" json:"name"`
|
||||
Domain string `gorm:"column:domain" json:"domain"`
|
||||
Domain string `gorm:"column:domain" json:"domain" private:"true"`
|
||||
Expected NullString `gorm:"column:expected" json:"expected"`
|
||||
ExpectedStatus int `gorm:"default:200;column:expected_status" json:"expected_status"`
|
||||
Interval int `gorm:"default:30;column:check_interval" json:"check_interval"`
|
||||
|
|
Loading…
Reference in New Issue