From 3177a4d0898d91bc0d31c15b7f036f29482149bd Mon Sep 17 00:00:00 2001 From: Hayden Hargreaves Date: Fri, 14 Nov 2025 22:33:54 -0700 Subject: [PATCH] (FEAT): Working on auth still --- internal/app/server/auth_handler_v2.go | 7 +++ internal/app/server/cookies.go | 9 +--- internal/app/server/middleware_v2.go | 7 +++ internal/app/server/server.go | 3 ++ internal/app/server/user_handler_v2.go | 25 +++++++++ web/README.md | 73 +------------------------- web/src/App.tsx | 2 +- web/src/components/Navigation.tsx | 2 +- web/src/context/AuthContext.tsx | 7 ++- web/src/context/AuthProvider.tsx | 11 +++- web/src/context/ProtectedRoute.tsx | 2 + web/src/pages/Home.tsx | 10 +--- web/src/pages/Profile.tsx | 65 +++++++++++++++++------ web/src/services/AuthService.ts | 10 +++- web/src/services/UserService.ts | 19 +++++++ web/src/types/api/auth.ts | 4 ++ web/src/types/api/user.ts | 7 +++ 17 files changed, 156 insertions(+), 107 deletions(-) create mode 100644 internal/app/server/user_handler_v2.go create mode 100644 web/src/context/ProtectedRoute.tsx create mode 100644 web/src/services/UserService.ts create mode 100644 web/src/types/api/user.ts diff --git a/internal/app/server/auth_handler_v2.go b/internal/app/server/auth_handler_v2.go index 13f44cf..c4e7d6b 100644 --- a/internal/app/server/auth_handler_v2.go +++ b/internal/app/server/auth_handler_v2.go @@ -38,3 +38,10 @@ func (s *Server) GoogleCallbackHandlerV2(ctx *gin.Context) { ctx.Redirect(http.StatusSeeOther, url) } } + +// BUG: This is not working, not yet sure why +func (s *Server) LogoutHandlerV2(ctx *gin.Context) { + s.SetCookie(ctx, "jwt_token", "", -1) + // s.SetCookie(ctx, "search-filters", "", -1) // TODO: This was copied, might function differently now + ctx.Status(http.StatusNoContent) +} diff --git a/internal/app/server/cookies.go b/internal/app/server/cookies.go index 3297c3f..0541300 100644 --- a/internal/app/server/cookies.go +++ b/internal/app/server/cookies.go @@ -20,8 +20,8 @@ func (s *Server) SetCookie(ctx *gin.Context, name, value string, duration time.D path string = "/" httpOnly bool = false // NOTE: Should use false so React can see it! maxAge int - secure bool - domain string + secure bool = false + domain string = "" ) if duration < 0 { @@ -43,11 +43,6 @@ func (s *Server) SetCookie(ctx *gin.Context, name, value string, duration time.D secure = false // domain = s.deps.EnvironmentConfig.Domain domain = "localhost" - - } else { - // Defaults - secure = false - domain = "" } ctx.SetCookie(name, value, maxAge, path, domain, secure, httpOnly) diff --git a/internal/app/server/middleware_v2.go b/internal/app/server/middleware_v2.go index a9e6168..4d4ade4 100644 --- a/internal/app/server/middleware_v2.go +++ b/internal/app/server/middleware_v2.go @@ -9,6 +9,13 @@ import ( domain "github.com/haydenhargreaves/Potion/internal/domain/server" ) +// JwtAuthMiddlewareV2 is responsible to protecting routes. Anything that may go wrong +// will be returned via JSON with a 'message' field and a 401 error code. When this +// middleware is successful, it will set the 'userId' and 'userEmail' fields and pass +// to the next function in the chain. +// +// Functions that are called after this can assume that those values defined are always +// set. func JwtAuthMiddlewareV2(jwtSecretKey []byte) gin.HandlerFunc { return func(ctx *gin.Context) { tokenString, err := ctx.Cookie("jwt_token") diff --git a/internal/app/server/server.go b/internal/app/server/server.go index db97f95..54dd6ff 100644 --- a/internal/app/server/server.go +++ b/internal/app/server/server.go @@ -204,6 +204,9 @@ func (s *Server) Setup() *Server { router_api_v2.GET("/recipe/of-the-week", s.GetRecipeOfTheWeekHandlerV2) router_api_v2.GET("/auth/login", s.GetGoogleAuthUrlHandlerV2) router_api_v2.GET("/auth/callback", s.GoogleCallbackHandlerV2) + router_api_v2.GET("/auth/logout", s.LogoutHandlerV2) + + router_api_v2.GET("/user", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), s.GetAuthenticatedUserHandlerV2) router_api_v2.GET("/protected", JwtAuthMiddlewareV2([]byte(cfg.JwtSecret)), func(ctx *gin.Context) { ctx.JSON(http.StatusOK, gin.H{"msg": "YAY"}) diff --git a/internal/app/server/user_handler_v2.go b/internal/app/server/user_handler_v2.go new file mode 100644 index 0000000..e5ff8a4 --- /dev/null +++ b/internal/app/server/user_handler_v2.go @@ -0,0 +1,25 @@ +package server + +import ( + "net/http" + + "github.com/gin-gonic/gin" +) + + +func (s *Server) GetAuthenticatedUserHandlerV2(ctx *gin.Context) { + user := s.deps.UserService.GetAuthenicatedUser(ctx) + if user == nil { + ctx.JSON(http.StatusUnauthorized, gin.H{ + "status": http.StatusUnauthorized, + "message": "[UNAUTHORIZED] Could not fetch authenticated user.", + }) + return + } + + ctx.JSON(http.StatusOK, gin.H{ + "status": http.StatusOK, + "message": "[OK] Successfully retrieved authenticated user.", + "user": user, + }) +} diff --git a/web/README.md b/web/README.md index 4dcad1f..cb7e169 100644 --- a/web/README.md +++ b/web/README.md @@ -1,73 +1,4 @@ -# React + TypeScript + Vite -This template provides a minimal setup to get React working in Vite with HMR and some ESLint rules. +# IF BACKEND CANNOT GET COOKIE -Currently, two official plugins are available: - -- [@vitejs/plugin-react](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react) uses [Babel](https://babeljs.io/) (or [oxc](https://oxc.rs) when used in [rolldown-vite](https://vite.dev/guide/rolldown)) for Fast Refresh -- [@vitejs/plugin-react-swc](https://github.com/vitejs/vite-plugin-react/blob/main/packages/plugin-react-swc) uses [SWC](https://swc.rs/) for Fast Refresh - -## React Compiler - -The React Compiler is currently not compatible with SWC. See [this issue](https://github.com/vitejs/vite-plugin-react/issues/428) for tracking the progress. - -## Expanding the ESLint configuration - -If you are developing a production application, we recommend updating the configuration to enable type-aware lint rules: - -```js -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - - // Remove tseslint.configs.recommended and replace with this - tseslint.configs.recommendedTypeChecked, - // Alternatively, use this for stricter rules - tseslint.configs.strictTypeChecked, - // Optionally, add this for stylistic rules - tseslint.configs.stylisticTypeChecked, - - // Other configs... - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` - -You can also install [eslint-plugin-react-x](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-x) and [eslint-plugin-react-dom](https://github.com/Rel1cx/eslint-react/tree/main/packages/plugins/eslint-plugin-react-dom) for React-specific lint rules: - -```js -// eslint.config.js -import reactX from 'eslint-plugin-react-x' -import reactDom from 'eslint-plugin-react-dom' - -export default defineConfig([ - globalIgnores(['dist']), - { - files: ['**/*.{ts,tsx}'], - extends: [ - // Other configs... - // Enable lint rules for React - reactX.configs['recommended-typescript'], - // Enable lint rules for React DOM - reactDom.configs.recommended, - ], - languageOptions: { - parserOptions: { - project: ['./tsconfig.node.json', './tsconfig.app.json'], - tsconfigRootDir: import.meta.dirname, - }, - // other options... - }, - }, -]) -``` +Do not forget to send the axios request with the `{ withCredentials: true }` flags. diff --git a/web/src/App.tsx b/web/src/App.tsx index aaf1f10..d6085d0 100644 --- a/web/src/App.tsx +++ b/web/src/App.tsx @@ -21,7 +21,7 @@ function ProtectedRoute({ children }: { children: ReactNode }) { } if (isLoggedIn) return children; - + // Redirect to login page if not authenicated return } diff --git a/web/src/components/Navigation.tsx b/web/src/components/Navigation.tsx index 0ebd4a8..9efb742 100644 --- a/web/src/components/Navigation.tsx +++ b/web/src/components/Navigation.tsx @@ -11,7 +11,7 @@ export default function Navigation() { return ( <> -