feat(web): move from react-router to @tanstack/router (#1338)

* fix(auth): invalid cookie handling and wrongful basic auth invalidation

* fix(auth): fix test to reflect new HTTP status code

* fix(auth/web): do not throw on error

* fix(http): replace http codes in middleware to prevent basic auth invalidation
fix typo in comment

* fix test

* fix(web): api client handle 403

* refactor(http): auth_test use testify.assert

* refactor(http): set session opts after valid login

* refactor(http): send more client headers

* fix(http): test

* refactor(web): move router to tanstack/router

* refactor(web): use route loaders and suspense

* refactor(web): useSuspense for settings

* refactor(web): invalidate cookie in middleware

* fix: loclfile

* fix: load filter/id

* fix(web): login, onboard, types, imports

* fix(web): filter load

* fix(web): build errors

* fix(web): ts-expect-error

* fix(tests): filter_test.go

* fix(filters): tests

* refactor: remove duplicate spinner components
refactor: ReleaseTable.tsx loading animation
refactor: remove dedicated `pendingComponent` for `settingsRoute`

* fix: refactor missed SectionLoader to RingResizeSpinner

* fix: substitute divides with borders to account for unloaded elements

* fix(api): action status URL param

* revert: action status URL param
add comment

* fix(routing): notfound handling and split files

* fix(filters): notfound get params

* fix(queries): colon

* fix(queries): comments ts-ignore

* fix(queries): extract queryKeys

* fix(queries): remove err

* fix(routes): move zob schema inline

* fix(auth): middleware and redirect to login

* fix(auth): failing test

* fix(logs): invalidate correct key

* fix(logs): invalidate correct key

* fix(logs): invalidate correct key

* fix: JSX element stealing focus from searchbar

* reimplement empty release table state text

* fix(context): use deep-copy

* fix(releases): empty state and filter input warnings

* fix(releases): empty states

* fix(auth): onboarding

* fix(cache): invalidate queries

---------

Co-authored-by: ze0s <43699394+zze0s@users.noreply.github.com>
This commit is contained in:
martylukyy 2024-02-12 13:07:00 +01:00 committed by GitHub
parent cc9656cd41
commit 1a23b69bcf
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
64 changed files with 2543 additions and 2091 deletions

View file

@ -21,6 +21,7 @@ import (
"github.com/go-chi/chi/v5"
"github.com/gorilla/sessions"
"github.com/rs/zerolog"
"github.com/stretchr/testify/assert"
)
type authServiceMock struct {
@ -144,9 +145,7 @@ func TestAuthHandlerLogin(t *testing.T) {
defer resp.Body.Close()
// check for response, here we'll just check for 204 NoContent
if status := resp.StatusCode; status != http.StatusNoContent {
t.Errorf("login: handler returned wrong status code: got %v want %v", status, http.StatusNoContent)
}
assert.Equalf(t, http.StatusNoContent, resp.StatusCode, "login handler: unexpected http status")
if v := resp.Header.Get("Set-Cookie"); v == "" {
t.Errorf("handler returned no cookie")
@ -207,12 +206,10 @@ func TestAuthHandlerValidateOK(t *testing.T) {
defer resp.Body.Close()
// check for response, here we'll just check for 204 NoContent
if status := resp.StatusCode; status != http.StatusNoContent {
t.Errorf("login: handler returned wrong status code: got %v want %v", status, http.StatusNoContent)
}
assert.Equalf(t, http.StatusNoContent, resp.StatusCode, "login handler: bad response")
if v := resp.Header.Get("Set-Cookie"); v == "" {
t.Errorf("handler returned no cookie")
assert.Equalf(t, "", v, "login handler: expected Set-Cookie header")
}
// validate token
@ -223,9 +220,7 @@ func TestAuthHandlerValidateOK(t *testing.T) {
defer resp.Body.Close()
if status := resp.StatusCode; status != http.StatusNoContent {
t.Errorf("validate: handler returned wrong status code: got %v want %v", status, http.StatusNoContent)
}
assert.Equalf(t, http.StatusNoContent, resp.StatusCode, "validate handler: unexpected http status")
}
func TestAuthHandlerValidateBad(t *testing.T) {
@ -272,9 +267,7 @@ func TestAuthHandlerValidateBad(t *testing.T) {
defer resp.Body.Close()
if status := resp.StatusCode; status != http.StatusNoContent {
t.Errorf("validate: handler returned wrong status code: got %v want %v", status, http.StatusNoContent)
}
assert.Equalf(t, http.StatusForbidden, resp.StatusCode, "validate handler: unexpected http status")
}
func TestAuthHandlerLoginBad(t *testing.T) {
@ -321,9 +314,7 @@ func TestAuthHandlerLoginBad(t *testing.T) {
defer resp.Body.Close()
// check for response, here we'll just check for 403 Forbidden
if status := resp.StatusCode; status != http.StatusForbidden {
t.Errorf("handler returned wrong status code: got %v want %v", status, http.StatusForbidden)
}
assert.Equalf(t, http.StatusForbidden, resp.StatusCode, "login handler: unexpected http status")
}
func TestAuthHandlerLogout(t *testing.T) {
@ -384,6 +375,8 @@ func TestAuthHandlerLogout(t *testing.T) {
t.Errorf("login: handler returned wrong status code: got %v want %v", status, http.StatusNoContent)
}
assert.Equalf(t, http.StatusNoContent, resp.StatusCode, "login handler: unexpected http status")
if v := resp.Header.Get("Set-Cookie"); v == "" {
t.Errorf("handler returned no cookie")
}
@ -396,9 +389,7 @@ func TestAuthHandlerLogout(t *testing.T) {
defer resp.Body.Close()
if status := resp.StatusCode; status != http.StatusNoContent {
t.Errorf("validate: handler returned wrong status code: got %v want %v", status, http.StatusNoContent)
}
assert.Equalf(t, http.StatusNoContent, resp.StatusCode, "validate handler: unexpected http status")
// logout
resp, err = client.Post(testServer.URL+"/auth/logout", "application/json", nil)
@ -408,9 +399,7 @@ func TestAuthHandlerLogout(t *testing.T) {
defer resp.Body.Close()
if status := resp.StatusCode; status != http.StatusNoContent {
t.Errorf("logout: handler returned wrong status code: got %v want %v", status, http.StatusNoContent)
}
assert.Equalf(t, http.StatusNoContent, resp.StatusCode, "logout handler: unexpected http status")
//if v := resp.Header.Get("Set-Cookie"); v != "" {
// t.Errorf("logout handler returned cookie")

View file

@ -67,6 +67,16 @@ func (e encoder) StatusNotFound(w http.ResponseWriter) {
w.WriteHeader(http.StatusNotFound)
}
func (e encoder) NotFoundErr(w http.ResponseWriter, err error) {
res := errorResponse{
Message: err.Error(),
}
w.Header().Set("Content-Type", "application/json; charset=utf-8")
w.WriteHeader(http.StatusNotFound)
json.NewEncoder(w).Encode(res)
}
func (e encoder) StatusInternalError(w http.ResponseWriter) {
w.WriteHeader(http.StatusInternalServerError)
}

View file

@ -119,7 +119,7 @@ func (h filterHandler) getByID(w http.ResponseWriter, r *http.Request) {
filter, err := h.service.FindByID(ctx, id)
if err != nil {
if errors.Is(err, domain.ErrRecordNotFound) {
h.encoder.StatusNotFound(w)
h.encoder.NotFoundErr(w, errors.New("filter with id %d not found", id))
return
}

View file

@ -38,7 +38,6 @@ func (s Server) IsAuthenticated(next http.Handler) http.Handler {
// MaxAge<0 means delete cookie immediately
session.Options.MaxAge = -1
session.Options.Path = s.config.Config.BaseURL
if err := session.Save(r, w); err != nil {
@ -50,13 +49,10 @@ func (s Server) IsAuthenticated(next http.Handler) http.Handler {
return
}
if session.IsNew {
http.Error(w, http.StatusText(http.StatusNoContent), http.StatusNoContent)
return
}
// Check if user is authenticated
if auth, ok := session.Values["authenticated"].(bool); !ok || !auth {
s.log.Warn().Msg("session not authenticated")
http.Error(w, http.StatusText(http.StatusForbidden), http.StatusForbidden)
return
}