non-admin user permissions - http fixes

pull/116/head
Hunter Long 2018-12-17 21:25:33 -08:00
parent 894e1e4430
commit 2ff197115a
14 changed files with 83 additions and 44 deletions

View File

@ -17,6 +17,7 @@ package handlers
import ( import (
"bytes" "bytes"
"fmt"
"github.com/hunterlong/statping/core" "github.com/hunterlong/statping/core"
"github.com/hunterlong/statping/core/notifier" "github.com/hunterlong/statping/core/notifier"
"github.com/hunterlong/statping/source" "github.com/hunterlong/statping/source"
@ -27,7 +28,7 @@ import (
) )
func dashboardHandler(w http.ResponseWriter, r *http.Request) { func dashboardHandler(w http.ResponseWriter, r *http.Request) {
if !IsFullAuthenticated(r) { if !IsUser(r) {
err := core.ErrorResponse{} err := core.ErrorResponse{}
ExecuteResponse(w, r, "login.gohtml", err, nil) ExecuteResponse(w, r, "login.gohtml", err, nil)
} else { } else {
@ -47,7 +48,9 @@ func loginHandler(w http.ResponseWriter, r *http.Request) {
if auth { if auth {
session.Values["authenticated"] = true session.Values["authenticated"] = true
session.Values["user_id"] = user.Id session.Values["user_id"] = user.Id
session.Values["admin"] = user.Admin.Bool
session.Save(r, w) session.Save(r, w)
utils.Log(1, fmt.Sprintf("User %v logged in from IP %v", user.Username, r.RemoteAddr))
http.Redirect(w, r, "/dashboard", http.StatusSeeOther) http.Redirect(w, r, "/dashboard", http.StatusSeeOther)
} else { } else {
err := core.ErrorResponse{Error: "Incorrect login information submitted, try again."} err := core.ErrorResponse{Error: "Incorrect login information submitted, try again."}
@ -58,12 +61,14 @@ func loginHandler(w http.ResponseWriter, r *http.Request) {
func logoutHandler(w http.ResponseWriter, r *http.Request) { func logoutHandler(w http.ResponseWriter, r *http.Request) {
session, _ := sessionStore.Get(r, cookieKey) session, _ := sessionStore.Get(r, cookieKey)
session.Values["authenticated"] = false session.Values["authenticated"] = false
session.Values["admin"] = false
session.Values["user_id"] = 0
session.Save(r, w) session.Save(r, w)
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
} }
func helpHandler(w http.ResponseWriter, r *http.Request) { func helpHandler(w http.ResponseWriter, r *http.Request) {
if !IsFullAuthenticated(r) { if !IsUser(r) {
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }

View File

@ -136,6 +136,23 @@ func IsFullAuthenticated(r *http.Request) bool {
return true return true
} }
} }
return IsAdmin(r)
}
// IsAdmin returns true if the user session is an administrator
func IsAdmin(r *http.Request) bool {
session, err := sessionStore.Get(r, cookieKey)
if err != nil {
return false
}
if session.Values["admin"] == nil {
return false
}
return session.Values["admin"].(bool)
}
// IsUser returns true if the user is registered
func IsUser(r *http.Request) bool {
session, err := sessionStore.Get(r, cookieKey) session, err := sessionStore.Get(r, cookieKey)
if err != nil { if err != nil {
return false return false
@ -160,6 +177,9 @@ var handlerFuncs = func(w http.ResponseWriter, r *http.Request) template.FuncMap
"Auth": func() bool { "Auth": func() bool {
return IsFullAuthenticated(r) return IsFullAuthenticated(r)
}, },
"IsUser": func() bool {
return IsUser(r)
},
"VERSION": func() string { "VERSION": func() string {
return core.VERSION return core.VERSION
}, },

View File

@ -26,7 +26,7 @@ import (
) )
func messagesHandler(w http.ResponseWriter, r *http.Request) { func messagesHandler(w http.ResponseWriter, r *http.Request) {
if !IsFullAuthenticated(r) { if !IsUser(r) {
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }

View File

@ -47,7 +47,7 @@ func renderServiceChartsHandler(w http.ResponseWriter, r *http.Request) {
} }
func servicesHandler(w http.ResponseWriter, r *http.Request) { func servicesHandler(w http.ResponseWriter, r *http.Request) {
if !IsFullAuthenticated(r) { if !IsUser(r) {
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }

View File

@ -28,7 +28,7 @@ import (
) )
func usersHandler(w http.ResponseWriter, r *http.Request) { func usersHandler(w http.ResponseWriter, r *http.Request) {
if !IsFullAuthenticated(r) { if !IsUser(r) {
http.Redirect(w, r, "/", http.StatusSeeOther) http.Redirect(w, r, "/", http.StatusSeeOther)
return return
} }

View File

@ -61,7 +61,7 @@ func (u *lineNotifier) Send(msg interface{}) error {
message := msg.(string) message := msg.(string)
v := url.Values{} v := url.Values{}
v.Set("message", message) v.Set("message", message)
headers := []string{fmt.Sprintf("Authorization=Bearer %v", u.GetValue("api_secret"))} headers := []string{fmt.Sprintf("Authorization=Bearer %v", u.ApiSecret)}
_, _, err := utils.HttpRequest("https://notify-api.line.me/api/notify", "POST", "application/x-www-form-urlencoded", headers, strings.NewReader(v.Encode()), time.Duration(10*time.Second)) _, _, err := utils.HttpRequest("https://notify-api.line.me/api/notify", "POST", "application/x-www-form-urlencoded", headers, strings.NewReader(v.Encode()), time.Duration(10*time.Second))
return err return err
} }

View File

@ -1,7 +1,7 @@
{{define "title"}}Statping | Help{{end}} {{define "title"}}Statping | Help{{end}}
{{define "content"}} {{define "content"}}
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light"> <div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
{{if Auth}} {{if IsUser}}
{{template "nav"}} {{template "nav"}}
{{end}} {{end}}
<div class="col-12"> <div class="col-12">

View File

@ -21,10 +21,10 @@
<td>{{if .Service}}<a href="/service/{{.Service.Id}}">{{.Service.Name}}</a>{{end}}</td> <td>{{if .Service}}<a href="/service/{{.Service.Id}}">{{.Service.Name}}</a>{{end}}</td>
<td>{{.StartOn}}</td> <td>{{.StartOn}}</td>
<td class="text-right"> <td class="text-right">
<div class="btn-group"> {{if Auth}}<div class="btn-group">
<a href="/message/{{.Id}}" class="btn btn-outline-secondary"><i class="fas fa-exclamation-triangle"></i> Edit</a> <a href="/message/{{.Id}}" class="btn btn-outline-secondary"><i class="fas fa-exclamation-triangle"></i> Edit</a>
<a href="/api/messages/{{.Id}}" class="ajax_delete btn btn-danger" data-method="DELETE" data-obj="message_{{.Id}}" data-id="{{.Id}}"><i class="fas fa-times"></i></a> <a href="/api/messages/{{.Id}}" class="ajax_delete btn btn-danger" data-method="DELETE" data-obj="message_{{.Id}}" data-id="{{.Id}}"><i class="fas fa-times"></i></a>
</div> </div>{{end}}
</td> </td>
</tr> </tr>
{{end}} {{end}}
@ -32,10 +32,12 @@
</table> </table>
</div> </div>
{{end}} {{end}}
{{if Auth}}
<div class="col-12"> <div class="col-12">
<h3>Create Message</h3> <h3>Create Message</h3>
{{template "form_message" NewMessage}} {{template "form_message" NewMessage}}
</div> </div>
{{end}}
</div> </div>
{{end}} {{end}}
{{define "extra_css"}} {{define "extra_css"}}

View File

@ -1,4 +1,5 @@
{{define "nav"}} {{define "nav"}}
{{$isAdmin := Auth}}
<nav class="navbar navbar-expand-lg navbar-light bg-light"> <nav class="navbar navbar-expand-lg navbar-light bg-light">
<a class="navbar-brand" href="/">Statping</a> <a class="navbar-brand" href="/">Statping</a>
<button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation"> <button class="navbar-toggler" type="button" data-toggle="collapse" data-target="#navbarText" aria-controls="navbarText" aria-expanded="false" aria-label="Toggle navigation">
@ -19,12 +20,14 @@
<li class="nav-item{{ if eq URL "/messages" }} active{{ end }}"> <li class="nav-item{{ if eq URL "/messages" }} active{{ end }}">
<a class="nav-link" href="/messages">Messages</a> <a class="nav-link" href="/messages">Messages</a>
</li> </li>
{{ if $isAdmin }}
<li class="nav-item{{ if eq URL "/settings" }} active{{ end }}"> <li class="nav-item{{ if eq URL "/settings" }} active{{ end }}">
<a class="nav-link" href="/settings">Settings</a> <a class="nav-link" href="/settings">Settings</a>
</li> </li>
<li class="nav-item{{ if eq URL "/logs" }} active{{ end }}"> <li class="nav-item{{ if eq URL "/logs" }} active{{ end }}">
<a class="nav-link" href="/logs">Logs</a> <a class="nav-link" href="/logs">Logs</a>
</li> </li>
{{end}}
<li class="nav-item{{ if eq URL "/help" }} active{{ end }}"> <li class="nav-item{{ if eq URL "/help" }} active{{ end }}">
<a class="nav-link" href="/help">Help</a> <a class="nav-link" href="/help">Help</a>
</li> </li>

View File

@ -2,9 +2,10 @@
{{define "description"}}{{$s := .Service}}{{if $s.Online }}{{.Service.Name}} is currently online and responding within {{$s.AvgTime}} milliseconds with {{$s.TotalUptime}}% total uptime on {{$s.Domain}}.{{else}}{{.Service.Name}} is currently offline on {{$s.Domain}}. Notify the admin to let them know their service is offline.{{end}}{{end}} {{define "description"}}{{$s := .Service}}{{if $s.Online }}{{.Service.Name}} is currently online and responding within {{$s.AvgTime}} milliseconds with {{$s.TotalUptime}}% total uptime on {{$s.Domain}}.{{else}}{{.Service.Name}} is currently offline on {{$s.Domain}}. Notify the admin to let them know their service is offline.{{end}}{{end}}
{{ define "content" }} {{ define "content" }}
{{$s := .Service}} {{$s := .Service}}
{{$isAdmin := Auth}}
<div class="container col-md-7 col-sm-12 mt-md-5 bg-light"> <div class="container col-md-7 col-sm-12 mt-md-5 bg-light">
{{if Auth}} {{if IsUser}}
{{template "nav"}} {{template "nav"}}
{{end}} {{end}}
@ -43,16 +44,16 @@
{{if $s.ActiveMessages}} {{if $s.ActiveMessages}}
<div class="col-12 mb-5"> <div class="col-12 mb-5">
{{range $s.ActiveMessages}} {{range $s.ActiveMessages}}
<div class="alert alert-warning" role="alert"> <div class="alert alert-warning" role="alert">
<h3>{{.Title}}</h3> <h3>{{.Title}}</h3>
<span class="mb-3">{{safe .Description}}</span> <span class="mb-3">{{safe .Description}}</span>
<div class="d-block mt-2 mb-4"> <div class="d-block mt-2 mb-4">
<span class="float-left small">Starts at {{.StartOn}}</span> <span class="float-left small">Starts at {{.StartOn}}</span>
<span class="float-right small">Ends on {{.EndOn}}</span> <span class="float-right small">Ends on {{.EndOn}}</span>
</div>
</div> </div>
</div> {{end}}
{{end}}
</div> </div>
{{end}} {{end}}
@ -74,15 +75,16 @@
<div class="col-12 small text-center mt-3 text-muted">{{$s.DowntimeText}}</div> <div class="col-12 small text-center mt-3 text-muted">{{$s.DowntimeText}}</div>
{{end}} {{end}}
{{if Auth}} {{if IsUser}}
{{$failures := $s.LimitedFailures 16}} {{$failures := $s.LimitedFailures 16}}
<nav class="nav nav-pills flex-column flex-sm-row mt-3" id="service_tabs" role="serviceLists"> <nav class="nav nav-pills flex-column flex-sm-row mt-3" id="service_tabs" role="serviceLists">
<a class="flex-sm-fill text-sm-center nav-link active" id="edit-tab" data-toggle="tab" href="#edit" role="tab" aria-controls="edit" aria-selected="false">Edit Service</a> {{if $isAdmin}}<a class="flex-sm-fill text-sm-center nav-link active" id="edit-tab" data-toggle="tab" href="#edit" role="tab" aria-controls="edit" aria-selected="false">Edit Service</a>{{end}}
<a class="flex-sm-fill text-sm-center nav-link{{ if not $failures }} disabled{{end}}" id="failures-tab" data-toggle="tab" href="#failures" role="tab" aria-controls="failures" aria-selected="true">Failures</a> <a class="flex-sm-fill text-sm-center nav-link{{ if not $failures }} disabled{{end}}" id="failures-tab" data-toggle="tab" href="#failures" role="tab" aria-controls="failures" aria-selected="true">Failures</a>
<a class="flex-sm-fill text-sm-center nav-link" id="checkins-tab" data-toggle="tab" href="#checkins" role="tab" aria-controls="checkins" aria-selected="false">Checkins</a> {{if $isAdmin}}<a class="flex-sm-fill text-sm-center nav-link" id="checkins-tab" data-toggle="tab" href="#checkins" role="tab" aria-controls="checkins" aria-selected="false">Checkins</a>{{end}}
<a class="flex-sm-fill text-sm-center nav-link" id="response-tab" data-toggle="tab" href="#response" role="tab" aria-controls="response" aria-selected="false">Response</a> <a class="flex-sm-fill text-sm-center nav-link{{if not $isAdmin}} active{{end}}" id="response-tab" data-toggle="tab" href="#response" role="tab" aria-controls="response" aria-selected="false">Response</a>
</nav> </nav>
<div class="tab-content" id="myTabContent"> <div class="tab-content" id="myTabContent">
{{if $isAdmin}}
<div class="tab-pane fade" id="failures" role="serviceLists" aria-labelledby="failures-tab"> <div class="tab-pane fade" id="failures" role="serviceLists" aria-labelledby="failures-tab">
{{ if $failures }} {{ if $failures }}
<div class="list-group mt-3 mb-4"> <div class="list-group mt-3 mb-4">
@ -98,6 +100,8 @@
</div> </div>
{{ end }} {{ end }}
</div> </div>
{{end}}
{{if $isAdmin}}
<div class="tab-pane fade" id="checkins" role="serviceLists" aria-labelledby="checkins-tab"> <div class="tab-pane fade" id="checkins" role="serviceLists" aria-labelledby="checkins-tab">
{{if $s.AllCheckins}} {{if $s.AllCheckins}}
<table class="table"> <table class="table">
@ -135,8 +139,9 @@
</tbody> </tbody>
</table> </table>
{{end}} {{end}}
{{template "form_checkin" $s}} {{if $isAdmin}}
{{template "form_checkin" $s}}
{{end}}
{{$failures := $s.LimitedCheckinFailures 16}} {{$failures := $s.LimitedCheckinFailures 16}}
{{ if $failures }} {{ if $failures }}
<div class="list-group mt-3 mb-4"> <div class="list-group mt-3 mb-4">
@ -152,7 +157,8 @@
</div> </div>
{{ end }} {{ end }}
</div> </div>
<div class="tab-pane fade" id="response" role="serviceLists" aria-labelledby="response-tab"> {{ end }}
<div class="tab-pane fade{{if not $isAdmin}} show active{{end}}" id="response" role="serviceLists" aria-labelledby="response-tab">
<div class="col-12 mt-4{{if ne $s.Type "http"}} d-none{{end}}"> <div class="col-12 mt-4{{if ne $s.Type "http"}} d-none{{end}}">
<h3>Last Response</h3> <h3>Last Response</h3>
<textarea rows="8" class="form-control" readonly>{{ $s.LastResponse }}</textarea> <textarea rows="8" class="form-control" readonly>{{ $s.LastResponse }}</textarea>
@ -164,14 +170,15 @@
</div> </div>
</div> </div>
</div> </div>
{{if $isAdmin}}
<div class="tab-pane fade show active" id="edit" role="serviceLists" aria-labelledby="edit-tab"> <div class="tab-pane fade show active" id="edit" role="serviceLists" aria-labelledby="edit-tab">
{{template "form_service" $s}} {{template "form_service" $s}}
</div> </div>
</div> {{end}}
</div> </div>
{{end}} {{end}}
</div> </div>
</div>
{{end}} {{end}}
{{define "extra_css"}} {{define "extra_css"}}
<link rel="stylesheet" href="/css/flatpickr.min.css"> <link rel="stylesheet" href="/css/flatpickr.min.css">

View File

@ -22,7 +22,7 @@
<td class="text-right"> <td class="text-right">
<div class="btn-group"> <div class="btn-group">
<a href="/service/{{.Id}}" class="btn btn-outline-secondary"><i class="fas fa-chart-area"></i> View</a> <a href="/service/{{.Id}}" class="btn btn-outline-secondary"><i class="fas fa-chart-area"></i> View</a>
<a href="/api/services/{{.Id}}" class="ajax_delete btn btn-danger" data-method="DELETE" data-obj="service_{{.Id}}" data-id="{{.Id}}"><i class="fas fa-times"></i></a> {{if Auth}}<a href="/api/services/{{.Id}}" class="ajax_delete btn btn-danger" data-method="DELETE" data-obj="service_{{.Id}}" data-id="{{.Id}}"><i class="fas fa-times"></i></a>{{end}}
</div> </div>
</td> </td>
</tr> </tr>
@ -30,11 +30,10 @@
</tbody> </tbody>
</table> </table>
{{end}} {{end}}
{{if Auth}}
<h3>Create Service</h3> <h3>Create Service</h3>
{{template "form_service" NewService}}
{{template "form_service" NewService}} {{end}}
</div> </div>
</div> </div>
{{end}} {{end}}

View File

@ -16,20 +16,19 @@
<tr id="user_{{.Id}}"> <tr id="user_{{.Id}}">
<td>{{.Username}}</td> <td>{{.Username}}</td>
<td class="text-right"> <td class="text-right">
<div class="btn-group"> {{if Auth}}<div class="btn-group">
<a href="/user/{{.Id}}" class="btn btn-outline-secondary"><i class="fas fa-user-edit"></i> Edit</a> <a href="/user/{{.Id}}" class="btn btn-outline-secondary"><i class="fas fa-user-edit"></i> Edit</a>
<a href="/api/users/{{.Id}}" class="ajax_delete btn btn-danger" data-method="DELETE" data-obj="user_{{.Id}}" data-id="{{.Id}}"><i class="fas fa-times"></i></a> <a href="/api/users/{{.Id}}" class="ajax_delete btn btn-danger" data-method="DELETE" data-obj="user_{{.Id}}" data-id="{{.Id}}"><i class="fas fa-times"></i></a>
</div> </div>{{end}}
</td> </td>
</tr> </tr>
{{end}} {{end}}
</tbody> </tbody>
</table> </table>
{{if Auth}}
<h3>Create User</h3> <h3>Create User</h3>
{{template "form_user" NewUser}}
{{template "form_user" NewUser}} {{end}}
</div> </div>
</div> </div>
{{end}} {{end}}

View File

@ -248,7 +248,11 @@ func HttpRequest(url, method string, content interface{}, headers []string, body
r := new(http.Request) r := new(http.Request)
for _, h := range headers { for _, h := range headers {
keyVal := strings.Split(h, "=") keyVal := strings.Split(h, "=")
r.Header.Add(keyVal[0], keyVal[1]) if len(keyVal) == 2 {
if keyVal[0] != "" && keyVal[1] != "" {
r.Header.Add(keyVal[0], keyVal[1])
}
}
} }
if r, err = http.NewRequest(method, url, body); err != nil { if r, err = http.NewRequest(method, url, body); err != nil {
return nil, nil, err return nil, nil, err

View File

@ -1 +1 @@
0.80.2 0.80.3