diff --git a/server/cmd/api/api.go b/server/cmd/api/api.go index df94752..81e67ff 100644 --- a/server/cmd/api/api.go +++ b/server/cmd/api/api.go @@ -142,12 +142,16 @@ func (a *API) CheckAuth(ctx *ReqCtx) (resp *BBJResponse, err error) { } if args.Hash == "" || args.Username == "" { - err = invalidArgs(err.Error()) + err = invalidArgs("missing either username or auth hash") return } _, err = checkAuth(a.Opts, args.Username, args.Hash) if err != nil { + if err.Error() != "bad credentials" { + return + } + err = &HTTPError{Code: 403, Msg: err.Error()} return } diff --git a/server/cmd/api/api_test.go b/server/cmd/api/api_test.go index f4e52a9..f15c80c 100644 --- a/server/cmd/api/api_test.go +++ b/server/cmd/api/api_test.go @@ -41,6 +41,137 @@ func userCount(db *sql.DB) (count int, err error) { return } +func Test_CheckAuth(t *testing.T) { + ts := []struct { + name string + req func() *http.Request + setup func(*config.Options) error + assert func(*BBJResponse, *testing.T) + wantErr *HTTPError + }{ + { + name: "blank user", + req: func() *http.Request { + req, _ := http.NewRequest("POST", "/check_auth", strings.NewReader(`{"target_hash":"abc123"}`)) + return req + }, + wantErr: &HTTPError{Code: 400, Msg: "invalid args: missing either username or auth hash"}, + }, + { + name: "blank hash", + req: func() *http.Request { + req, _ := http.NewRequest("POST", "/check_auth", strings.NewReader(`{"target_user":"jillvalentine"}`)) + return req + }, + wantErr: &HTTPError{Code: 400, Msg: "invalid args: missing either username or auth hash"}, + }, + { + name: "bad method", + req: func() *http.Request { + r, _ := http.NewRequest("GET", "", strings.NewReader("")) + return r + }, + wantErr: &HTTPError{ + Msg: "bad method", + Code: 400, + }, + }, + { + name: "mismatch hash", + setup: func(opts *config.Options) error { + return db.CreateUser(opts.DB, db.User{ + Username: "jillvalentine", + Hash: "xyz789", + Created: time.Now(), + }) + }, + req: func() *http.Request { + req, _ := http.NewRequest("POST", "/check_auth", strings.NewReader(`{"target_user":"jillvalentine", "target_hash":"abc123"}`)) + return req + }, + wantErr: &HTTPError{Code: 403, Msg: "bad credentials"}, + }, + { + name: "good", + setup: func(opts *config.Options) error { + return db.CreateUser(opts.DB, db.User{ + Username: "jillvalentine", + Hash: "xyz789", + Created: time.Now(), + }) + }, + req: func() *http.Request { + req, _ := http.NewRequest("POST", "/check_auth", strings.NewReader(`{"target_user":"jillvalentine", "target_hash":"xyz789"}`)) + return req + }, + assert: func(resp *BBJResponse, t *testing.T) { + if !resp.Data.(bool) { + t.Error("expected true Data") + } + }, + }, + } + + for _, tt := range ts { + t.Run(tt.name, func(t *testing.T) { + // TODO BOILERPLATE + opts, err := createTestState() + if err != nil { + t.Fatalf("failed to create test state: %s", err.Error()) + return + } + var req *http.Request + if tt.req == nil { + req, _ = http.NewRequest("POST", "", strings.NewReader(`{"user_name":"albertwesker","auth_hash":"1234abc"}`)) + } else { + req = tt.req() + } + teardown, err := db.Setup(opts) + if err != nil { + t.Fatalf("could not initialize DB: %s", err.Error()) + return + } + defer teardown() + + err = db.EnsureSchema(*opts) + if err != nil { + t.Fatalf("could not initialize DB: %s", err.Error()) + return + } + + if tt.setup != nil { + err = tt.setup(opts) + if err != nil { + t.Fatalf("setup failed: %s", err.Error()) + return + } + } + // END BOILERPLATE + + api := &API{Opts: *opts} + ctx := &ReqCtx{Req: req} + var resp *BBJResponse + resp, err = api.CheckAuth(ctx) + if err != nil { + if tt.wantErr == nil || tt.wantErr.Error() != err.Error() { + t.Errorf("got unexpected error: %s", err) + } + return + } else { + if tt.wantErr != nil { + t.Error("expected error, got none") + return + } + } + + if tt.assert != nil { + tt.assert(resp, t) + } + + }) + } +} + func Test_UserRegister(t *testing.T) { ts := []struct { name string