forked from tildetown/bbj2
further unfucking of API/handlers
parent
7fd2547cd1
commit
2d22877f11
|
@ -35,28 +35,48 @@ type BBJResponse struct {
|
||||||
Usermap map[string]db.User `json:"usermap"`
|
Usermap map[string]db.User `json:"usermap"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type APIHandler func() (*BBJResponse, error)
|
type APIHandler func(*ReqCtx) (*BBJResponse, error)
|
||||||
|
|
||||||
type API struct {
|
type API struct {
|
||||||
User *db.User
|
|
||||||
Opts config.Options
|
Opts config.Options
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewAPI(opts config.Options) *API {
|
||||||
|
return &API{Opts: opts}
|
||||||
|
}
|
||||||
|
|
||||||
|
type ReqCtx struct {
|
||||||
|
User db.User
|
||||||
Req *http.Request
|
Req *http.Request
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewAPI(opts config.Options, req *http.Request) (*API, error) {
|
func (c *ReqCtx) IsGet() bool {
|
||||||
user, err := getUserFromReq(opts, req)
|
return c.Req.Method == "GET"
|
||||||
if err != nil {
|
|
||||||
return nil, &HTTPError{Msg: err.Error(), Code: 403}
|
|
||||||
}
|
|
||||||
return &API{
|
|
||||||
Opts: opts,
|
|
||||||
User: user,
|
|
||||||
Req: req,
|
|
||||||
}, nil
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Invoke(w http.ResponseWriter, apiFn APIHandler) {
|
func (c *ReqCtx) IsPost() bool {
|
||||||
resp, err := apiFn()
|
return c.Req.Method == "POST"
|
||||||
|
}
|
||||||
|
|
||||||
|
func (a *API) Invoke(w http.ResponseWriter, req *http.Request, apiFn APIHandler) {
|
||||||
|
a.Opts.Logger.Printf("<- %s", req.URL.Path)
|
||||||
|
user, err := getUserFromReq(a.Opts, req)
|
||||||
|
if err != nil {
|
||||||
|
a.Opts.Logger.Printf("failed to get user from req: %s", err.Error())
|
||||||
|
w.WriteHeader(500)
|
||||||
|
w.Header().Set("Content-Type", "application/json")
|
||||||
|
json.NewEncoder(w).Encode(BBJResponse{
|
||||||
|
Error: true,
|
||||||
|
Data: "server error check logs",
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx := ReqCtx{
|
||||||
|
User: *user,
|
||||||
|
Req: req,
|
||||||
|
}
|
||||||
|
|
||||||
|
resp, err := apiFn(&ctx)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
he := &HTTPError{}
|
he := &HTTPError{}
|
||||||
_ = errors.As(err, &he)
|
_ = errors.As(err, &he)
|
||||||
|
@ -115,16 +135,8 @@ type instanceInfo struct {
|
||||||
Admins []string
|
Admins []string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) IsGet() bool {
|
func (a *API) InstanceInfo(ctx *ReqCtx) (resp *BBJResponse, err error) {
|
||||||
return a.Req.Method == "GET"
|
if !ctx.IsGet() {
|
||||||
}
|
|
||||||
|
|
||||||
func (a *API) IsPost() bool {
|
|
||||||
return a.Req.Method == "POST"
|
|
||||||
}
|
|
||||||
|
|
||||||
func (a *API) InstanceInfo() (resp *BBJResponse, err error) {
|
|
||||||
if !a.IsGet() {
|
|
||||||
err = badMethod()
|
err = badMethod()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -140,8 +152,8 @@ func (a *API) InstanceInfo() (resp *BBJResponse, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
func (a *API) UserRegister() (resp *BBJResponse, err error) {
|
func (a *API) UserRegister(ctx *ReqCtx) (resp *BBJResponse, err error) {
|
||||||
if !a.IsPost() {
|
if !ctx.IsPost() {
|
||||||
err = badMethod()
|
err = badMethod()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -151,7 +163,7 @@ func (a *API) UserRegister() (resp *BBJResponse, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var args AuthArgs
|
var args AuthArgs
|
||||||
if err = json.NewDecoder(a.Req.Body).Decode(&args); err != nil {
|
if err = json.NewDecoder(ctx.Req.Body).Decode(&args); err != nil {
|
||||||
err = invalidArgs(err.Error())
|
err = invalidArgs(err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -7,6 +7,7 @@ import (
|
||||||
"reflect"
|
"reflect"
|
||||||
"strings"
|
"strings"
|
||||||
"testing"
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
"git.tilde.town/tildetown/bbj2/server/cmd/config"
|
"git.tilde.town/tildetown/bbj2/server/cmd/config"
|
||||||
"git.tilde.town/tildetown/bbj2/server/cmd/db"
|
"git.tilde.town/tildetown/bbj2/server/cmd/db"
|
||||||
|
@ -51,8 +52,11 @@ func TestUserRegister(t *testing.T) {
|
||||||
name: "user already exists",
|
name: "user already exists",
|
||||||
opts: *opts,
|
opts: *opts,
|
||||||
setup: func(opts *config.Options) error {
|
setup: func(opts *config.Options) error {
|
||||||
// TODO
|
return db.CreateUser(opts.DB, db.User{
|
||||||
return nil
|
Username: "albertwesker",
|
||||||
|
Hash: "1234abc",
|
||||||
|
Created: time.Now(),
|
||||||
|
})
|
||||||
},
|
},
|
||||||
assert: func(t *testing.T) error {
|
assert: func(t *testing.T) error {
|
||||||
// TODO
|
// TODO
|
||||||
|
@ -64,15 +68,27 @@ func TestUserRegister(t *testing.T) {
|
||||||
|
|
||||||
for _, tt := range ts {
|
for _, tt := range ts {
|
||||||
t.Run(tt.name, func(t *testing.T) {
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
teardown, err := db.Setup(*opts)
|
teardown, err := db.Setup(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not initialize DB: %s", err.Error())
|
t.Fatalf("could not initialize DB: %s", err.Error())
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
defer teardown()
|
defer teardown()
|
||||||
|
|
||||||
|
err = tt.setup(&tt.opts)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatalf("setup failed: %s", err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
// TODO
|
// TODO
|
||||||
|
|
||||||
|
err = tt.assert(t)
|
||||||
|
if err != nil {
|
||||||
|
t.Fatal(err.Error())
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -84,7 +100,7 @@ func TestInstanceInfo(t *testing.T) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
teardown, err := db.Setup(*opts)
|
teardown, err := db.Setup(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
t.Fatalf("could not initialize DB: %s", err.Error())
|
t.Fatalf("could not initialize DB: %s", err.Error())
|
||||||
return
|
return
|
||||||
|
|
|
@ -51,7 +51,7 @@ type Message struct {
|
||||||
SendRaw int `json:"send_raw"` // TODO bool
|
SendRaw int `json:"send_raw"` // TODO bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func Setup(opts config.Options) (func(), error) {
|
func Setup(opts *config.Options) (func(), error) {
|
||||||
db, err := sql.Open("sqlite3", opts.Config.DBPath)
|
db, err := sql.Open("sqlite3", opts.Config.DBPath)
|
||||||
opts.DB = db
|
opts.DB = db
|
||||||
return func() { db.Close() }, err
|
return func() { db.Close() }, err
|
||||||
|
@ -122,5 +122,7 @@ func CreateUser(db *sql.DB, u User) (err error) {
|
||||||
|
|
||||||
_, err = stmt.Exec(id, u.Username, u.Hash, u.Created)
|
_, err = stmt.Exec(id, u.Username, u.Hash, u.Created)
|
||||||
|
|
||||||
|
// TODO return user so we have ID
|
||||||
|
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,7 +1,6 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
"encoding/json"
|
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"log"
|
"log"
|
||||||
|
@ -56,7 +55,7 @@ func _main(opts *config.Options) error {
|
||||||
|
|
||||||
opts.Config = *cfg
|
opts.Config = *cfg
|
||||||
|
|
||||||
teardown, err := db.Setup(*opts)
|
teardown, err := db.Setup(opts)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return fmt.Errorf("could not initialize DB: %w", err)
|
return fmt.Errorf("could not initialize DB: %w", err)
|
||||||
}
|
}
|
||||||
|
@ -78,45 +77,16 @@ func _main(opts *config.Options) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func handler(opts config.Options, f http.HandlerFunc) http.HandlerFunc {
|
|
||||||
// TODO make this more real
|
|
||||||
return func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
opts.Logger.Printf("<- %s", req.URL.Path)
|
|
||||||
// TODO add user info to opts
|
|
||||||
f(w, req)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func setupAPI(opts config.Options) {
|
func setupAPI(opts config.Options) {
|
||||||
handleFailedAPICreate := func(w http.ResponseWriter, err error) {
|
a := api.NewAPI(opts)
|
||||||
opts.Logger.Printf("failed to create API: %s", err.Error())
|
|
||||||
w.WriteHeader(500)
|
|
||||||
w.Header().Set("Content-Type", "application/json")
|
|
||||||
json.NewEncoder(w).Encode(api.BBJResponse{
|
|
||||||
Error: true,
|
|
||||||
Data: "server error check logs",
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
// TODO could probably generalize this even further but it's fine for now
|
http.HandleFunc("/instance_info", func(w http.ResponseWriter, req *http.Request) {
|
||||||
|
a.Invoke(w, req, a.InstanceInfo)
|
||||||
|
})
|
||||||
|
|
||||||
http.HandleFunc("/instance_info", handler(opts, func(w http.ResponseWriter, req *http.Request) {
|
http.HandleFunc("/user_register", func(w http.ResponseWriter, req *http.Request) {
|
||||||
a, err := api.NewAPI(opts, req)
|
a.Invoke(w, req, a.UserRegister)
|
||||||
if err != nil {
|
})
|
||||||
handleFailedAPICreate(w, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
api.Invoke(w, a.InstanceInfo)
|
|
||||||
}))
|
|
||||||
|
|
||||||
http.HandleFunc("/user_register", handler(opts, func(w http.ResponseWriter, req *http.Request) {
|
|
||||||
a, err := api.NewAPI(opts, req)
|
|
||||||
if err != nil {
|
|
||||||
handleFailedAPICreate(w, err)
|
|
||||||
return
|
|
||||||
}
|
|
||||||
api.Invoke(w, a.UserRegister)
|
|
||||||
}))
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue