upgrades - plugins

pull/10/head
Hunter Long 2018-06-11 00:49:41 -07:00
parent a95f725348
commit 9a510c8dfc
11 changed files with 109 additions and 142 deletions

View File

@ -1,6 +1,9 @@
package main package main
import "github.com/gorilla/sessions" import (
"github.com/gorilla/sessions"
"github.com/hunterlong/statup/plugin"
)
type Core struct { type Core struct {
Name string Name string
@ -8,6 +11,7 @@ type Core struct {
Key string Key string
Secret string Secret string
Version string Version string
Plugins []*plugin.Plugin
} }
func SelectCore() (*Core, error) { func SelectCore() (*Core, error) {

View File

@ -6,6 +6,7 @@ import (
_ "github.com/lib/pq" _ "github.com/lib/pq"
"math/rand" "math/rand"
"time" "time"
"github.com/hunterlong/statup/plugin"
) )
func DbConnection() { func DbConnection() {
@ -15,7 +16,7 @@ func DbConnection() {
if err != nil { if err != nil {
panic(err) panic(err)
} }
InitPluginsDatabase() plugin.SetDatabase(db)
} }
func UpgradeDatabase() { func UpgradeDatabase() {

View File

@ -18,6 +18,12 @@
<div class="row"> <div class="row">
{{ range .Plugins }}
{{ . }}
{{end}}
<div class="col-4"> <div class="col-4">
<div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical"> <div class="nav flex-column nav-pills" id="v-pills-tab" role="tablist" aria-orientation="vertical">

60
main.go
View File

@ -9,6 +9,9 @@ import (
_ "github.com/lib/pq" _ "github.com/lib/pq"
"golang.org/x/crypto/bcrypt" "golang.org/x/crypto/bcrypt"
"io/ioutil" "io/ioutil"
"github.com/hunterlong/statup/plugin"
plg "plugin"
"strings"
) )
var ( var (
@ -22,6 +25,7 @@ var (
jsBox *rice.Box jsBox *rice.Box
tmplBox *rice.Box tmplBox *rice.Box
setupMode bool setupMode bool
allPlugins []*plugin.Plugin
) )
type Config struct { type Config struct {
@ -46,6 +50,12 @@ func main() {
mainProcess() mainProcess()
} }
type Greeter interface {
Greet()
}
func mainProcess() { func mainProcess() {
var err error var err error
DbConnection() DbConnection()
@ -55,10 +65,60 @@ func mainProcess() {
} }
go CheckServices() go CheckServices()
if !setupMode { if !setupMode {
LoadPlugins()
RunHTTPServer() RunHTTPServer()
} }
} }
func LoadPlugins() {
files, err := ioutil.ReadDir("./plugins")
if err != nil {
fmt.Printf("Plugins directory was not found. Error: %v\n", err)
return
}
for _, f := range files {
ext := strings.Split(f.Name(), ".")
if len(ext) != 2 {
continue
}
if ext[1] == "so" {
plug, err := plg.Open("plugins/"+f.Name())
if err != nil {
fmt.Printf("Plugin '%v' could not load correctly.\n", f.Name())
continue
}
symPlugin, err := plug.Lookup("Plugin")
var plugActions plugin.PluginActions
plugActions, ok := symPlugin.(plugin.PluginActions)
if !ok {
fmt.Printf("Plugin '%v' could not load correctly, error: %v\n", f.Name(), "unexpected type from module symbol")
continue
}
plugin := plugActions.Plugin()
fmt.Printf("Plugin Loaded '%v' created by: %v\n", plugin.Name, plugin.Creator)
plugActions.OnLoad()
fmt.Println(plugActions.Form())
allPlugins = append(allPlugins, plugin)
}
}
core.Plugins = allPlugins
fmt.Printf("Loaded %v Plugins\n", len(allPlugins))
}
func RenderBoxes() { func RenderBoxes() {
sqlBox = rice.MustFindBox("sql") sqlBox = rice.MustFindBox("sql")
cssBox = rice.MustFindBox("html/css") cssBox = rice.MustFindBox("html/css")

View File

@ -1,23 +1,21 @@
package plugins package plugin
import ( import (
"database/sql"
"fmt"
"net/http" "net/http"
"database/sql"
) )
var ( var (
db *sql.DB DB *sql.DB
PluginRoutes []*Routing
Plugins []*Plugin
) )
type Plugin struct { type Plugin struct {
PluginActions
Name string Name string
Creator string
Version string
InstallSQL string InstallSQL string
InstallFunc func() Routes []*Routing
UninstallFunc func()
SaveFunc func()
} }
type Routing struct { type Routing struct {
@ -26,39 +24,36 @@ type Routing struct {
Handler func(http.ResponseWriter, *http.Request) Handler func(http.ResponseWriter, *http.Request)
} }
func (p *Plugin) Add() { type PluginActions interface {
Plugins = append(Plugins, p) Plugin() *Plugin
OnLoad()
Install()
Uninstall()
Save()
Form() string
OnNewUser()
OnFailure()
OnHit()
} }
func AddRoute(url string, method string, handle func(http.ResponseWriter, *http.Request)) { func SetDatabase(db *sql.DB) {
route := &Routing{url, method, handle} DB = db
PluginRoutes = append(PluginRoutes, route)
} }
func (p *Plugin) InstallPlugin(w http.ResponseWriter, r *http.Request) { func (p *Plugin) InstallPlugin(w http.ResponseWriter, r *http.Request) {
p.InstallFunc()
//sql := "CREATE TABLE " + p.Name + " (enabled BOOLEAN, api_key text, api_secret text, channel text);"
//db.QueryRow(p.InstallSQL()).Scan()
http.Redirect(w, r, "/plugins", http.StatusSeeOther) http.Redirect(w, r, "/plugins", http.StatusSeeOther)
} }
func (p *Plugin) UninstallPlugin(w http.ResponseWriter, r *http.Request) { func (p *Plugin) UninstallPlugin(w http.ResponseWriter, r *http.Request) {
p.UninstallFunc()
http.Redirect(w, r, "/plugins", http.StatusSeeOther) http.Redirect(w, r, "/plugins", http.StatusSeeOther)
} }
func (p *Plugin) SavePlugin(w http.ResponseWriter, r *http.Request) { func (p *Plugin) SavePlugin(w http.ResponseWriter, r *http.Request) {
p.SaveFunc() //values := r.PostForm
//p.SaveFunc(values)
http.Redirect(w, r, "/plugins", http.StatusSeeOther) http.Redirect(w, r, "/plugins", http.StatusSeeOther)
} }
func Authenticated(r *http.Request) bool {
return true
}
func log(msg ...string) {
fmt.Println(" @plugins: ", msg)
}
func InitDB(database *sql.DB) {
db = database
}

View File

@ -1,38 +0,0 @@
package main
import (
"github.com/hunterlong/statup/plugins"
)
var (
pluginRoutes []*plugins.Routing
allPlugins []*plugins.Plugin
)
func InitPluginsDatabase() {
plugins.InitDB(db)
}
func SetAuthorized() {
}
func AfterInstall() {
}
func AfterUninstall() {
}
func AfterSave() {
}
func Routes() []*plugins.Routing {
return plugins.PluginRoutes
}
func AllPlugins() []*plugins.Plugin {
return plugins.Plugins
}

View File

@ -1 +0,0 @@
yooyyo

View File

@ -1,67 +0,0 @@
package plugins
import (
"net/http"
)
const (
SLACK_TABLE = "plugin_slack"
SLACK_INSTALL = "CREATE TABLE " + SLACK_TABLE + " (enabled BOOLEAN, api_key text, api_secret text, channel text);"
)
type Slack struct {
Key string
Secret string
Enabled bool
Channel string
InstallFunc func()
UninstallFunc func()
SaveFunc func(*http.Request)
}
func init() {
plugin := &Plugin{
"slack",
SLACK_INSTALL,
InstallSlack,
UninstallSlack,
SaveSlack,
}
plugin.Add()
}
func InstallSlack() {
CreateTable()
}
func UninstallSlack() {
DropTable()
}
func SaveSlack() {
//key := r.PostForm.Get("key")
//secret := r.PostForm.Get("secret")
//enabled, _ := strconv.ParseBool(r.PostForm.Get("enabled"))
//channel := r.PostForm.Get("channel")
//slack.UpdateTable()
}
func CreateTable() {
sql := "CREATE TABLE " + SLACK_TABLE + " (enabled BOOLEAN, api_key text, api_secret text, channel text);"
db.QueryRow(sql).Scan()
}
func (s *Slack) UpdateTable() {
sql := "CREATE TABLE " + SLACK_TABLE + " (enabled BOOLEAN, api_key text, api_key text, channel text);"
db.QueryRow(sql).Scan()
}
func DropTable() {
sql := "DROP TABLE " + SLACK_TABLE + ";"
db.QueryRow(sql).Scan()
}

BIN
plugins/slack.so Normal file

Binary file not shown.

BIN
slack.so Normal file

Binary file not shown.

15
web.go
View File

@ -7,10 +7,14 @@ import (
"net/http" "net/http"
"strconv" "strconv"
"time" "time"
"github.com/gorilla/sessions"
)
var (
session *sessions.CookieStore
) )
func RunHTTPServer() { func RunHTTPServer() {
r := mux.NewRouter() r := mux.NewRouter()
fmt.Println("Statup HTTP Server running on http://localhost:8080") fmt.Println("Statup HTTP Server running on http://localhost:8080")
@ -39,8 +43,12 @@ func RunHTTPServer() {
r.Handle("/plugins", http.HandlerFunc(PluginsHandler)) r.Handle("/plugins", http.HandlerFunc(PluginsHandler))
r.Handle("/help", http.HandlerFunc(HelpHandler)) r.Handle("/help", http.HandlerFunc(HelpHandler))
for _, plugin := range AllPlugins() { for _, plugin := range allPlugins {
fmt.Printf("Adding plugin: %v\n", plugin.Name) for _, route := range plugin.Routes {
path := fmt.Sprintf("/plugins/%v/%v", plugin.Name, route.URL)
r.Handle(path, http.HandlerFunc(route.Handler)).Methods(route.Method)
fmt.Printf("Added Route %v for plugin %v\n", path, plugin.Name)
}
r.Handle("/plugins/install_"+plugin.Name, http.HandlerFunc(plugin.InstallPlugin)).Methods("GET") r.Handle("/plugins/install_"+plugin.Name, http.HandlerFunc(plugin.InstallPlugin)).Methods("GET")
r.Handle("/plugins/uninstall_"+plugin.Name, http.HandlerFunc(plugin.UninstallPlugin)).Methods("GET") r.Handle("/plugins/uninstall_"+plugin.Name, http.HandlerFunc(plugin.UninstallPlugin)).Methods("GET")
r.Handle("/plugins/save_"+plugin.Name, http.HandlerFunc(plugin.SavePlugin)).Methods("POST") r.Handle("/plugins/save_"+plugin.Name, http.HandlerFunc(plugin.SavePlugin)).Methods("POST")
@ -247,7 +255,6 @@ func ServicesUpdateHandler(w http.ResponseWriter, r *http.Request) {
// //
//vars := mux.Vars(r) //vars := mux.Vars(r)
//service := SelectService(vars["id"]) //service := SelectService(vars["id"])
} }
func ServicesViewHandler(w http.ResponseWriter, r *http.Request) { func ServicesViewHandler(w http.ResponseWriter, r *http.Request) {