mirror of https://github.com/statping/statping
vue js public api with scopes within struct tags. neato.
parent
134bd073ff
commit
30e64f688c
|
@ -1,6 +1,6 @@
|
|||
<template>
|
||||
<div id="app">
|
||||
<router-view></router-view>
|
||||
<router-view/>
|
||||
<Footer/>
|
||||
</div>
|
||||
</template>
|
||||
|
@ -9,7 +9,9 @@
|
|||
import Footer from "./components/Footer";
|
||||
export default {
|
||||
name: 'app',
|
||||
components: {Footer},
|
||||
components: {
|
||||
Footer
|
||||
},
|
||||
}
|
||||
</script>
|
||||
|
||||
|
|
|
@ -13,10 +13,18 @@ class Api {
|
|||
return axios.get('/api/services').then(response => (response.data))
|
||||
}
|
||||
|
||||
async service (id) {
|
||||
return axios.get('/api/services/'+id).then(response => (response.data))
|
||||
}
|
||||
|
||||
async groups () {
|
||||
return axios.get('/api/groups').then(response => (response.data))
|
||||
}
|
||||
|
||||
async group (id) {
|
||||
return axios.get('/api/groups/'+id).then(response => (response.data))
|
||||
}
|
||||
|
||||
}
|
||||
const api = new Api()
|
||||
export default api
|
||||
|
|
|
@ -1,12 +1,50 @@
|
|||
import Vue from 'vue'
|
||||
import App from './App.vue'
|
||||
import VueRouter from 'vue-router'
|
||||
const router = require("routes")
|
||||
import Index from "./pages/Index";
|
||||
import Dashboard from "./pages/Dashboard";
|
||||
import Settings from "./pages/Settings";
|
||||
import Service from "./pages/Service";
|
||||
import Services from "./pages/Services";
|
||||
|
||||
require("./assets/css/bootstrap.min.css")
|
||||
require("./assets/css/base.css")
|
||||
|
||||
Vue.use(VueRouter)
|
||||
const routes = [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Index',
|
||||
component: Index
|
||||
},
|
||||
{
|
||||
path: '/dashboard',
|
||||
name: 'Dashboard',
|
||||
component: Dashboard
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
name: 'Settings',
|
||||
component: Settings
|
||||
},
|
||||
{
|
||||
path: '/services',
|
||||
name: 'Services',
|
||||
component: Services
|
||||
},
|
||||
{
|
||||
path: '/service/:id',
|
||||
name: 'Service',
|
||||
component: Service
|
||||
}
|
||||
];
|
||||
|
||||
const router = new VueRouter
|
||||
({
|
||||
mode: 'history',
|
||||
routes
|
||||
})
|
||||
|
||||
Vue.use(VueRouter);
|
||||
|
||||
Vue.config.productionTip = false
|
||||
new Vue({
|
||||
|
|
|
@ -1,11 +1,8 @@
|
|||
<template>
|
||||
<div class="container col-md-7 col-sm-12 mt-2 sm-container">
|
||||
<div v-show="core" 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>
|
||||
|
@ -29,6 +26,7 @@ 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: 'Dashboard',
|
||||
|
@ -46,25 +44,13 @@ export default {
|
|||
}
|
||||
},
|
||||
beforeMount() {
|
||||
this.getAPI()
|
||||
this.getGroups()
|
||||
this.getServices()
|
||||
this.loadAll()
|
||||
},
|
||||
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))
|
||||
async loadAll () {
|
||||
this.core = await Api.root()
|
||||
this.groups = await Api.groups()
|
||||
this.services = await Api.services()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
<template>
|
||||
<div class="container col-md-7 col-sm-12 mt-2 sm-container">
|
||||
|
||||
{{service}}
|
||||
</div>
|
||||
</template>
|
||||
|
||||
<script>
|
||||
import Api from "../components/API"
|
||||
|
||||
export default {
|
||||
name: 'Service',
|
||||
|
@ -13,14 +14,18 @@ export default {
|
|||
},
|
||||
data () {
|
||||
return {
|
||||
id: null,
|
||||
service: null,
|
||||
}
|
||||
},
|
||||
beforeMount() {
|
||||
|
||||
this.id = this.$route.params.id
|
||||
this.getService()
|
||||
},
|
||||
methods: {
|
||||
|
||||
async getService() {
|
||||
this.service = await Api.services()
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
|
|
@ -1,26 +0,0 @@
|
|||
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: [
|
||||
{
|
||||
path: '/',
|
||||
name: 'Index',
|
||||
component: Index
|
||||
},
|
||||
{
|
||||
path: '/dashboard',
|
||||
name: 'Dashboard',
|
||||
component: Dashboard
|
||||
},
|
||||
{
|
||||
path: '/settings',
|
||||
name: 'Settings',
|
||||
component: Settings
|
||||
}
|
||||
]
|
||||
})
|
||||
|
||||
export default router
|
|
@ -4,7 +4,7 @@ module.exports = {
|
|||
proxy: {
|
||||
'/api': {
|
||||
logLevel: 'debug',
|
||||
target: 'http://0.0.0.0:8282'
|
||||
target: 'http://0.0.0.0:8585'
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -294,43 +294,94 @@ func expandServices(s []types.ServiceInterface) []*types.Service {
|
|||
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))
|
||||
func toSafeJson(input interface{}) map[string]interface{} {
|
||||
thisData := make(map[string]interface{})
|
||||
t := reflect.TypeOf(input)
|
||||
elem := reflect.ValueOf(input)
|
||||
|
||||
d, _ := json.Marshal(input)
|
||||
|
||||
var raw map[string]*json.RawMessage
|
||||
json.Unmarshal(d, &raw)
|
||||
|
||||
if t.Kind() == reflect.Ptr {
|
||||
input = &input
|
||||
}
|
||||
returnJson(allData, w, r)
|
||||
|
||||
fmt.Println("Type:", t.Name())
|
||||
fmt.Println("Kind:", t.Kind())
|
||||
|
||||
for i := 0; i < t.NumField(); i++ {
|
||||
field := t.Field(i)
|
||||
|
||||
// Get the field tag value
|
||||
tag := field.Tag.Get("scope")
|
||||
jsonTag := field.Tag.Get("json")
|
||||
|
||||
tags := strings.Split(tag, ",")
|
||||
|
||||
if jsonTag == "" || jsonTag == "-" {
|
||||
continue
|
||||
}
|
||||
|
||||
trueValue := elem.Field(i).Interface()
|
||||
trueValue = fixValue(field, trueValue)
|
||||
|
||||
if tag == "" {
|
||||
thisData[jsonTag] = trueValue
|
||||
continue
|
||||
}
|
||||
|
||||
if isPublic(tags) {
|
||||
thisData[jsonTag] = trueValue
|
||||
}
|
||||
|
||||
fmt.Printf("%d. %v (%v), tags: '%v'\n", i, field.Name, field.Type.Name(), tags)
|
||||
}
|
||||
return thisData
|
||||
}
|
||||
|
||||
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)
|
||||
func returnSafeJson(w http.ResponseWriter, r *http.Request, input interface{}) {
|
||||
if reflect.ValueOf(input).Kind() == reflect.Slice {
|
||||
alldata := make([]map[string]interface{}, 0, 1)
|
||||
s := reflect.ValueOf(input)
|
||||
for i := 0; i < s.Len(); i++ {
|
||||
alldata = append(alldata, toSafeJson(s.Index(i).Interface()))
|
||||
}
|
||||
fmt.Printf("Field: %s\tValue: %v\n", typeOfS.Field(i).Type.String(), v.Field(i).Interface())
|
||||
returnJson(alldata, w, r)
|
||||
return
|
||||
}
|
||||
returnJson(input, w, r)
|
||||
return
|
||||
}
|
||||
|
||||
data, _ := json.Marshal(thisObj)
|
||||
|
||||
json.Unmarshal(data, &nn)
|
||||
removeKeys := safeTypes(thisObj)
|
||||
for _, k := range removeKeys {
|
||||
delete(nn, k)
|
||||
func fixValue(field reflect.StructField, val interface{}) interface{} {
|
||||
typeName := field.Type.Name()
|
||||
switch typeName {
|
||||
case "NullString":
|
||||
nullItem := val.(types.NullString)
|
||||
return nullItem.String
|
||||
case "NullBool":
|
||||
nullItem := val.(types.NullBool)
|
||||
return nullItem.Bool
|
||||
case "NullFloat64":
|
||||
nullItem := val.(types.NullFloat64)
|
||||
return nullItem.Float64
|
||||
case "NullInt64":
|
||||
nullItem := val.(types.NullInt64)
|
||||
return nullItem.Int64
|
||||
default:
|
||||
return val
|
||||
}
|
||||
return nn
|
||||
}
|
||||
|
||||
func isPublic(tags []string) bool {
|
||||
for _, v := range tags {
|
||||
if v == "public" {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// error404Handler is a HTTP handler for 404 error pages
|
||||
|
|
|
@ -15,6 +15,12 @@ var (
|
|||
authPass string
|
||||
)
|
||||
|
||||
func scopedRoute(handler func(w http.ResponseWriter, r *http.Request)) http.Handler {
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
handler(w, r)
|
||||
})
|
||||
}
|
||||
|
||||
// basicAuthHandler is a middleware to implement HTTP basic authentication using
|
||||
// AUTH_USERNAME and AUTH_PASSWORD environment variables
|
||||
func basicAuthHandler(next http.Handler) http.Handler {
|
||||
|
|
|
@ -114,7 +114,7 @@ func Router() *mux.Router {
|
|||
r.Handle("/group/{id}", http.HandlerFunc(groupViewHandler)).Methods("GET")
|
||||
|
||||
// API Routes
|
||||
r.Handle("/api", authenticated(apiIndexHandler, false))
|
||||
r.Handle("/api", scopedRoute(apiIndexHandler))
|
||||
r.Handle("/api/renew", authenticated(apiRenewHandler, false))
|
||||
r.Handle("/api/clear_cache", authenticated(apiClearCacheHandler, false))
|
||||
|
||||
|
@ -123,7 +123,7 @@ func Router() *mux.Router {
|
|||
r.Handle("/api/integrations/{name}", authenticated(apiIntegrationHandler, false)).Methods("POST")
|
||||
|
||||
// API GROUPS Routes
|
||||
r.Handle("/api/groups", readOnly(apiAllGroupHandler, false)).Methods("GET")
|
||||
r.Handle("/api/groups", scopedRoute(apiAllGroupHandler)).Methods("GET")
|
||||
r.Handle("/api/groups", authenticated(apiCreateGroupHandler, false)).Methods("POST")
|
||||
r.Handle("/api/groups/{id}", readOnly(apiGroupHandler, false)).Methods("GET")
|
||||
r.Handle("/api/groups/{id}", authenticated(apiGroupUpdateHandler, false)).Methods("POST")
|
||||
|
@ -131,9 +131,9 @@ func Router() *mux.Router {
|
|||
r.Handle("/api/reorder/groups", authenticated(apiGroupReorderHandler, false)).Methods("POST")
|
||||
|
||||
// API SERVICE Routes
|
||||
r.Handle("/api/services", http.HandlerFunc(apiAllServicesHandler)).Methods("GET")
|
||||
r.Handle("/api/services", scopedRoute(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/services/{id}", scopedRoute(apiServiceHandler)).Methods("GET")
|
||||
r.Handle("/api/reorder/services", authenticated(reorderServiceHandler, false)).Methods("POST")
|
||||
r.Handle("/api/services/{id}/running", authenticated(apiServiceRunningHandler, false)).Methods("POST")
|
||||
r.Handle("/api/services/{id}/data", cached("30s", "application/json", apiServiceDataHandler)).Methods("GET")
|
||||
|
|
|
@ -294,15 +294,23 @@ func apiServiceDeleteHandler(w http.ResponseWriter, r *http.Request) {
|
|||
}
|
||||
|
||||
func apiAllServicesHandler(w http.ResponseWriter, r *http.Request) {
|
||||
admin := IsAdmin(r)
|
||||
isAdmin := IsAdmin(r)
|
||||
services := core.Services()
|
||||
if !admin {
|
||||
returnSafeJson(w, r, expandServices(services))
|
||||
if !isAdmin {
|
||||
returnSafeJson(w, r, joinServices(services))
|
||||
return
|
||||
}
|
||||
returnJson(services, w, r)
|
||||
}
|
||||
|
||||
func joinServices(srvs []types.ServiceInterface) []types.Service {
|
||||
var services []types.Service
|
||||
for _, v := range srvs {
|
||||
services = append(services, *v.Select())
|
||||
}
|
||||
return services
|
||||
}
|
||||
|
||||
func servicesDeleteFailuresHandler(w http.ResponseWriter, r *http.Request) {
|
||||
vars := mux.Vars(r)
|
||||
service := core.SelectService(utils.ToInt(vars["id"]))
|
||||
|
|
|
@ -23,21 +23,21 @@ 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" 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"`
|
||||
Type string `gorm:"column:check_type" json:"type"`
|
||||
Method string `gorm:"column:method" json:"method"`
|
||||
PostData NullString `gorm:"column:post_data" json:"post_data"`
|
||||
Port int `gorm:"not null;column:port" json:"port"`
|
||||
Timeout int `gorm:"default:30;column:timeout" json:"timeout"`
|
||||
Domain string `gorm:"column:domain" json:"domain" private:"true" scope:"user,admin"`
|
||||
Expected NullString `gorm:"column:expected" json:"expected" scope:"user,admin"`
|
||||
ExpectedStatus int `gorm:"default:200;column:expected_status" json:"expected_status" scope:"user,admin"`
|
||||
Interval int `gorm:"default:30;column:check_interval" json:"check_interval" scope:"user,admin"`
|
||||
Type string `gorm:"column:check_type" json:"type" scope:"user,admin"`
|
||||
Method string `gorm:"column:method" json:"method" scope:"user,admin"`
|
||||
PostData NullString `gorm:"column:post_data" json:"post_data" scope:"user,admin"`
|
||||
Port int `gorm:"not null;column:port" json:"port" scope:"user,admin"`
|
||||
Timeout int `gorm:"default:30;column:timeout" json:"timeout" scope:"user,admin"`
|
||||
Order int `gorm:"default:0;column:order_id" json:"order_id"`
|
||||
AllowNotifications NullBool `gorm:"default:true;column:allow_notifications" json:"allow_notifications"`
|
||||
VerifySSL NullBool `gorm:"default:false;column:verify_ssl" json:"verify_ssl"`
|
||||
AllowNotifications NullBool `gorm:"default:true;column:allow_notifications" json:"allow_notifications" scope:"user,admin"`
|
||||
VerifySSL NullBool `gorm:"default:false;column:verify_ssl" json:"verify_ssl" scope:"user,admin"`
|
||||
Public NullBool `gorm:"default:true;column:public" json:"public"`
|
||||
GroupId int `gorm:"default:0;column:group_id" json:"group_id"`
|
||||
Headers NullString `gorm:"column:headers" json:"headers"`
|
||||
Headers NullString `gorm:"column:headers" json:"headers" scope:"user,admin"`
|
||||
Permalink NullString `gorm:"column:permalink" json:"permalink"`
|
||||
CreatedAt time.Time `gorm:"column:created_at" json:"created_at"`
|
||||
UpdatedAt time.Time `gorm:"column:updated_at" json:"updated_at"`
|
||||
|
@ -56,8 +56,8 @@ type Service struct {
|
|||
SuccessNotified bool `gorm:"-" json:"-"` // Is 'true' if the user has already be informed that the Services now again available
|
||||
LastStatusCode int `gorm:"-" json:"status_code"`
|
||||
LastOnline time.Time `gorm:"-" json:"last_success"`
|
||||
Failures []FailureInterface `gorm:"-" json:"failures,omitempty"`
|
||||
Checkins []CheckinInterface `gorm:"-" json:"checkins,omitempty"`
|
||||
Failures []FailureInterface `gorm:"-" json:"failures,omitempty" scope:"user,admin"`
|
||||
Checkins []CheckinInterface `gorm:"-" json:"checkins,omitempty" scope:"user,admin"`
|
||||
}
|
||||
|
||||
// BeforeCreate for Service will set CreatedAt to UTC
|
||||
|
|
Loading…
Reference in New Issue