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"`
|
||||
}
|
||||
|
||||
type APIHandler func() (*BBJResponse, error)
|
||||
type APIHandler func(*ReqCtx) (*BBJResponse, error)
|
||||
|
||||
type API struct {
|
||||
User *db.User
|
||||
Opts config.Options
|
||||
}
|
||||
|
||||
func NewAPI(opts config.Options) *API {
|
||||
return &API{Opts: opts}
|
||||
}
|
||||
|
||||
type ReqCtx struct {
|
||||
User db.User
|
||||
Req *http.Request
|
||||
}
|
||||
|
||||
func NewAPI(opts config.Options, req *http.Request) (*API, error) {
|
||||
user, err := getUserFromReq(opts, req)
|
||||
if err != nil {
|
||||
return nil, &HTTPError{Msg: err.Error(), Code: 403}
|
||||
}
|
||||
return &API{
|
||||
Opts: opts,
|
||||
User: user,
|
||||
Req: req,
|
||||
}, nil
|
||||
func (c *ReqCtx) IsGet() bool {
|
||||
return c.Req.Method == "GET"
|
||||
}
|
||||
|
||||
func Invoke(w http.ResponseWriter, apiFn APIHandler) {
|
||||
resp, err := apiFn()
|
||||
func (c *ReqCtx) IsPost() bool {
|
||||
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 {
|
||||
he := &HTTPError{}
|
||||
_ = errors.As(err, &he)
|
||||
|
@ -115,16 +135,8 @@ type instanceInfo struct {
|
|||
Admins []string
|
||||
}
|
||||
|
||||
func (a *API) IsGet() bool {
|
||||
return a.Req.Method == "GET"
|
||||
}
|
||||
|
||||
func (a *API) IsPost() bool {
|
||||
return a.Req.Method == "POST"
|
||||
}
|
||||
|
||||
func (a *API) InstanceInfo() (resp *BBJResponse, err error) {
|
||||
if !a.IsGet() {
|
||||
func (a *API) InstanceInfo(ctx *ReqCtx) (resp *BBJResponse, err error) {
|
||||
if !ctx.IsGet() {
|
||||
err = badMethod()
|
||||
return
|
||||
}
|
||||
|
@ -140,8 +152,8 @@ func (a *API) InstanceInfo() (resp *BBJResponse, err error) {
|
|||
return
|
||||
}
|
||||
|
||||
func (a *API) UserRegister() (resp *BBJResponse, err error) {
|
||||
if !a.IsPost() {
|
||||
func (a *API) UserRegister(ctx *ReqCtx) (resp *BBJResponse, err error) {
|
||||
if !ctx.IsPost() {
|
||||
err = badMethod()
|
||||
return
|
||||
}
|
||||
|
@ -151,7 +163,7 @@ func (a *API) UserRegister() (resp *BBJResponse, err error) {
|
|||
}
|
||||
|
||||
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())
|
||||
return
|
||||
}
|
||||
|
|
|
@ -7,6 +7,7 @@ import (
|
|||
"reflect"
|
||||
"strings"
|
||||
"testing"
|
||||
"time"
|
||||
|
||||
"git.tilde.town/tildetown/bbj2/server/cmd/config"
|
||||
"git.tilde.town/tildetown/bbj2/server/cmd/db"
|
||||
|
@ -51,8 +52,11 @@ func TestUserRegister(t *testing.T) {
|
|||
name: "user already exists",
|
||||
opts: *opts,
|
||||
setup: func(opts *config.Options) error {
|
||||
// TODO
|
||||
return nil
|
||||
return db.CreateUser(opts.DB, db.User{
|
||||
Username: "albertwesker",
|
||||
Hash: "1234abc",
|
||||
Created: time.Now(),
|
||||
})
|
||||
},
|
||||
assert: func(t *testing.T) error {
|
||||
// TODO
|
||||
|
@ -64,15 +68,27 @@ func TestUserRegister(t *testing.T) {
|
|||
|
||||
for _, tt := range ts {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
teardown, err := db.Setup(*opts)
|
||||
teardown, err := db.Setup(opts)
|
||||
if err != nil {
|
||||
t.Fatalf("could not initialize DB: %s", err.Error())
|
||||
return
|
||||
}
|
||||
defer teardown()
|
||||
|
||||
err = tt.setup(&tt.opts)
|
||||
if err != nil {
|
||||
t.Fatalf("setup failed: %s", err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
// TODO
|
||||
|
||||
err = tt.assert(t)
|
||||
if err != nil {
|
||||
t.Fatal(err.Error())
|
||||
return
|
||||
}
|
||||
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -84,7 +100,7 @@ func TestInstanceInfo(t *testing.T) {
|
|||
return
|
||||
}
|
||||
|
||||
teardown, err := db.Setup(*opts)
|
||||
teardown, err := db.Setup(opts)
|
||||
if err != nil {
|
||||
t.Fatalf("could not initialize DB: %s", err.Error())
|
||||
return
|
||||
|
|
|
@ -51,7 +51,7 @@ type Message struct {
|
|||
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)
|
||||
opts.DB = db
|
||||
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)
|
||||
|
||||
// TODO return user so we have ID
|
||||
|
||||
return
|
||||
}
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
package main
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"flag"
|
||||
"fmt"
|
||||
"log"
|
||||
|
@ -56,7 +55,7 @@ func _main(opts *config.Options) error {
|
|||
|
||||
opts.Config = *cfg
|
||||
|
||||
teardown, err := db.Setup(*opts)
|
||||
teardown, err := db.Setup(opts)
|
||||
if err != nil {
|
||||
return fmt.Errorf("could not initialize DB: %w", err)
|
||||
}
|
||||
|
@ -78,45 +77,16 @@ func _main(opts *config.Options) error {
|
|||
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) {
|
||||
handleFailedAPICreate := func(w http.ResponseWriter, err error) {
|
||||
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",
|
||||
a := api.NewAPI(opts)
|
||||
|
||||
http.HandleFunc("/instance_info", func(w http.ResponseWriter, req *http.Request) {
|
||||
a.Invoke(w, req, a.InstanceInfo)
|
||||
})
|
||||
}
|
||||
|
||||
// TODO could probably generalize this even further but it's fine for now
|
||||
|
||||
http.HandleFunc("/instance_info", 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.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)
|
||||
}))
|
||||
http.HandleFunc("/user_register", func(w http.ResponseWriter, req *http.Request) {
|
||||
a.Invoke(w, req, a.UserRegister)
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue