further unfucking of API/handlers

trunk
vilmibm 2022-06-17 16:01:25 -05:00
parent 7fd2547cd1
commit 2d22877f11
4 changed files with 70 additions and 70 deletions

View File

@ -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
}

View File

@ -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

View File

@ -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
}

View File

@ -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)
})
}