You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
236 lines
5.3 KiB
236 lines
5.3 KiB
package main
|
|
|
|
import (
|
|
"database/sql"
|
|
"encoding/json"
|
|
"fmt"
|
|
"html/template"
|
|
"log"
|
|
"net/http"
|
|
"os"
|
|
"strings"
|
|
|
|
_ "github.com/go-sql-driver/mysql"
|
|
)
|
|
|
|
//Global db object
|
|
var db *sql.DB
|
|
|
|
// Used in writing out errors when they occur
|
|
type errorMessage struct {
|
|
StatusCode int
|
|
Msg string
|
|
}
|
|
|
|
// Writes the given error message in the template. If not, just writes the message raw
|
|
func writeError(w http.ResponseWriter, e errorMessage) {
|
|
// Try to use error template
|
|
w.WriteHeader(e.StatusCode)
|
|
t := template.Must(template.New("error.html").ParseFiles("html/error.html"))
|
|
err := t.Execute(w, e)
|
|
// If something goes wrong just tell them the error in an ugly way
|
|
if err != nil {
|
|
// Can't tell the user since the writer already wrote out
|
|
log.Println(err)
|
|
}
|
|
}
|
|
|
|
// Get all the currently available hooks
|
|
func getHooks(w http.ResponseWriter) []Hook {
|
|
// Get all hooks from db
|
|
rows, err := db.Query("SELECT ID FROM Hooks")
|
|
if err != nil {
|
|
logError(w, err)
|
|
}
|
|
defer rows.Close()
|
|
|
|
// Look through hooks
|
|
hooks := make([]Hook, 0)
|
|
for rows.Next() {
|
|
var hook Hook
|
|
err = rows.Scan(&hook.Name)
|
|
// Hook doesn't have a name (This shouldn't really happen)
|
|
if err != nil {
|
|
logError(w, err)
|
|
}
|
|
hooks = append(hooks, hook)
|
|
}
|
|
return hooks
|
|
}
|
|
|
|
// Run a particular hook (will probably come up with a better solution)
|
|
func runHook(w http.ResponseWriter, r *http.Request, hook Hook) {
|
|
b, err := json.Marshal(hook)
|
|
if err != nil {
|
|
logError(w, err)
|
|
} else {
|
|
fmt.Fprint(w, string(b))
|
|
}
|
|
}
|
|
|
|
func loadTemplate(w http.ResponseWriter, r *http.Request, path string, name string, arg interface{}) {
|
|
// Log request to this url
|
|
log.Println(r.URL.String(), r.Method)
|
|
if r.URL.String() == path {
|
|
// Serve index template
|
|
t := template.Must(template.New(name+".html").ParseFiles("html/"+name+".html"))
|
|
err := t.Execute(w, arg)
|
|
if err != nil {
|
|
// writeError(w, errorMessage{
|
|
// StatusCode: http.StatusInternalServerError,
|
|
// Msg: "Failed to Load Page",
|
|
// })
|
|
}
|
|
// Can't find the page
|
|
} else {
|
|
writeError(w, errorMessage{
|
|
StatusCode: http.StatusNotFound,
|
|
Msg: "Not Found",
|
|
})
|
|
}
|
|
}
|
|
|
|
// Show the index
|
|
func index(w http.ResponseWriter, r *http.Request) {
|
|
u := r.URL.String()
|
|
// Some bad path to start
|
|
path := "/bad"
|
|
// In case people think this is actually static html
|
|
if u == "/" || u == "/index.html" || u == "/index.htm" || u == "/index" {
|
|
loadTemplate(w, r, u, "index", getHooks(w))
|
|
// Catch those trying to cheat and go to /bad
|
|
} else if u == "/bad" {
|
|
path = "/very_bad"
|
|
} else {
|
|
loadTemplate(w, r, path, "index", getHooks(w))
|
|
}
|
|
}
|
|
|
|
// Show the configuration page
|
|
func configureHook(w http.ResponseWriter, r *http.Request, hook Hook) {
|
|
loadTemplate(w, r, r.URL.String(),"configure", hook)
|
|
}
|
|
|
|
// Handles requests to /hook/
|
|
func hookHandler(w http.ResponseWriter, r *http.Request) {
|
|
// Log request to this url
|
|
log.Println(r.URL.String(), r.Method)
|
|
if r.URL.String() == "/hook/" {
|
|
switch r.Method {
|
|
// Display all hooks
|
|
case http.MethodGet:
|
|
showHooks(w)
|
|
// Method unsupported
|
|
default:
|
|
writeError(w, errorMessage{
|
|
StatusCode: http.StatusMethodNotAllowed,
|
|
Msg: "Method Unsupported",
|
|
})
|
|
}
|
|
return
|
|
}
|
|
|
|
// Hook name
|
|
name := r.URL.String()[len("/hook/"):]
|
|
nameSplit := strings.Split(name, "/")
|
|
name = strings.ToLower(nameSplit[0])
|
|
|
|
switch r.Method {
|
|
// Handle the hook
|
|
case http.MethodGet, http.MethodPost:
|
|
// See if the hook exists
|
|
row := db.QueryRow("SELECT EXISTS(SELECT id FROM Hooks WHERE Hooks.id = ?)", name)
|
|
var res int
|
|
row.Scan(&res)
|
|
// Hook doesn't exist
|
|
if res == 0 {
|
|
writeError(w, errorMessage{
|
|
StatusCode: http.StatusNotFound,
|
|
Msg: "Not Found",
|
|
})
|
|
return
|
|
}
|
|
|
|
// Construct the hook from the results
|
|
hook := Hook{
|
|
Name: name,
|
|
conditions: nil,
|
|
}
|
|
|
|
// Check to see if it's configure web page instead of API endpoint
|
|
if len(nameSplit) == 2 && nameSplit[1] == "configure" {
|
|
configureHook(w, r, hook)
|
|
} else {
|
|
// Run the user's hook
|
|
runHook(w, r, hook)
|
|
}
|
|
|
|
// Create / Update the hook
|
|
case http.MethodPut:
|
|
createHook(w, name)
|
|
|
|
// Delete the hook
|
|
case http.MethodDelete:
|
|
deleteHook(w, name)
|
|
|
|
// Method unsupported
|
|
default:
|
|
writeError(w, errorMessage{
|
|
StatusCode: http.StatusMethodNotAllowed,
|
|
Msg: "Method Not Allowed",
|
|
})
|
|
}
|
|
}
|
|
|
|
// Shows all of the hooks
|
|
func showHooks(w http.ResponseWriter) {
|
|
hooks := getHooks(w)
|
|
b, err := json.Marshal(hooks)
|
|
if err != nil {
|
|
logError(w, err)
|
|
} else {
|
|
fmt.Fprint(w, string(b))
|
|
}
|
|
}
|
|
|
|
// Creates a new hook
|
|
func createHook(w http.ResponseWriter, name string) {
|
|
statement, err := db.Prepare("INSERT IGNORE INTO Hooks(id) VALUES(?)")
|
|
// Shouldn't really happen, but incase the insert goes wrong
|
|
if err != nil {
|
|
logError(w, err)
|
|
os.Exit(1)
|
|
return
|
|
}
|
|
defer statement.Close()
|
|
statement.Exec(name)
|
|
fmt.Fprintln(w, name)
|
|
}
|
|
|
|
// Delete a hook
|
|
func deleteHook(w http.ResponseWriter, name string) {
|
|
statement, err := db.Prepare("DELETE FROM Hooks WHERE ID=(?)")
|
|
//Shouldn't ever error
|
|
if err != nil {
|
|
logError(w, err)
|
|
return
|
|
}
|
|
defer statement.Close()
|
|
|
|
// Get results
|
|
res, err := statement.Exec(name)
|
|
// Shouldn't ever error
|
|
if err != nil {
|
|
logError(w, err)
|
|
return
|
|
}
|
|
|
|
// Probably also shouldn't error
|
|
_, err = res.RowsAffected()
|
|
if err != nil {
|
|
logError(w, err)
|
|
return
|
|
}
|
|
|
|
fmt.Fprintln(w, name)
|
|
}
|