diff --git a/backend/internal/handlers/auth_handlers.go b/backend/internal/handlers/auth_handlers.go index 941666c..4ad0082 100644 --- a/backend/internal/handlers/auth_handlers.go +++ b/backend/internal/handlers/auth_handlers.go @@ -4,6 +4,8 @@ import ( "encoding/json" "os" + "strings" + "gitea.d3m0k1d.ru/d3m0k1d/d3m0k1d.ru/backend/internal/auth" "gitea.d3m0k1d.ru/d3m0k1d/d3m0k1d.ru/backend/internal/logger" "gitea.d3m0k1d.ru/d3m0k1d/d3m0k1d.ru/backend/internal/repositories" @@ -73,7 +75,7 @@ func (h *AuthHandlers) CallbackGithub(c *gin.Context) { code := c.Query("code") if code == "" { h.logger.Error("missing code") - c.JSON(400, gin.H{"error": "missing code"}) + c.Redirect(302, "https://d3m0k1d.ru/login?error=missing_code") return } @@ -82,7 +84,7 @@ func (h *AuthHandlers) CallbackGithub(c *gin.Context) { token, err := h.config.Exchange(c.Request.Context(), code) if err != nil { h.logger.Error("Exchange failed: " + err.Error()) - c.JSON(500, gin.H{"error": "exchange failed", "details": err.Error()}) + c.Redirect(302, "https://d3m0k1d.ru/login?error=auth_failed") return } @@ -90,7 +92,7 @@ func (h *AuthHandlers) CallbackGithub(c *gin.Context) { resp, err := client.Get("https://api.github.com/user") if err != nil { h.logger.Error("Get failed: " + err.Error()) - c.JSON(500, gin.H{"error": "get request failed to github", "details": err.Error()}) + c.Redirect(302, "https://d3m0k1d.ru/login?error=github_api_failed") return } @@ -98,14 +100,14 @@ func (h *AuthHandlers) CallbackGithub(c *gin.Context) { err = json.NewDecoder(resp.Body).Decode(&ghUser) if err != nil { h.logger.Error("Decode failed: " + err.Error()) - c.JSON(500, gin.H{"error": "decode failed", "details": err.Error()}) + c.Redirect(302, "https://d3m0k1d.ru/login?error=decode_failed") return } isreg, err := h.repo.IsRegistered(c.Request.Context(), ghUser.GithubID) if err != nil { h.logger.Error("Database check failed: " + err.Error()) - c.JSON(500, gin.H{"error": "database error", "details": err.Error()}) + c.Redirect(302, "https://d3m0k1d.ru/login?error=database_error") return } @@ -114,7 +116,7 @@ func (h *AuthHandlers) CallbackGithub(c *gin.Context) { id, err = h.repo.Register(c.Request.Context(), ghUser) if err != nil { h.logger.Error("Registration failed: " + err.Error()) - c.JSON(500, gin.H{"error": "registration failed", "details": err.Error()}) + c.Redirect(302, "https://d3m0k1d.ru/login?error=registration_failed") return } } else { @@ -122,7 +124,7 @@ func (h *AuthHandlers) CallbackGithub(c *gin.Context) { user, err := h.repo.GetUserByGithubID(c.Request.Context(), ghUser.GithubID) if err != nil { h.logger.Error("Failed to fetch user: " + err.Error()) - c.JSON(500, gin.H{"error": "failed to fetch user", "details": err.Error()}) + c.Redirect(302, "https://d3m0k1d.ru/login?error=user_fetch_failed") return } id = user.ID @@ -138,26 +140,17 @@ func (h *AuthHandlers) CallbackGithub(c *gin.Context) { Email: ghUser.Email, AvatarURL: ghUser.AvatarURL, } + jwtToken, err := auth.GenerateJWT(user) if err != nil { h.logger.Error("JWT generation failed: " + err.Error()) - c.JSON(500, gin.H{"error": "token generation failed", "details": err.Error()}) + c.Redirect(302, "https://d3m0k1d.ru/login?error=token_failed") return } h.logger.Info("Authentication successful for user: " + ghUser.GithubLogin) - c.SetCookie( - "auth_token", - jwtToken, - 3600*24*30, - "/", - "", - true, - true, - ) - - c.Redirect(302, "https://d3m0k1d.ru") + c.Redirect(302, "https://d3m0k1d.ru/auth/callback#token="+jwtToken) } // GetSession godoc @@ -169,12 +162,18 @@ func (h *AuthHandlers) CallbackGithub(c *gin.Context) { // @Failure 401 {object} map[string]string "Unauthorized" // @Router /session [get] func (h *AuthHandlers) GetSession(c *gin.Context) { - tokenString, err := c.Cookie("auth_token") - if err != nil { + authHeader := c.GetHeader("Authorization") + if authHeader == "" { c.JSON(401, gin.H{"error": "unauthorized"}) return } + tokenString := strings.TrimPrefix(authHeader, "Bearer ") + if tokenString == authHeader { + c.JSON(401, gin.H{"error": "invalid authorization header"}) + return + } + user, err := auth.ValidateJWT(tokenString) if err != nil { c.JSON(401, gin.H{"error": "invalid token"}) diff --git a/frontend/index.html b/frontend/index.html index b8aa7e8..50878e7 100644 --- a/frontend/index.html +++ b/frontend/index.html @@ -1,42 +1,117 @@ + + + + + + + + + + + + d3m0k1d - DevOps Engineer & InfoSec Student - - - - - - - - - - - - d3m0k1d - DevOps Engineer & InfoSec Student - + #initial-loader .spinner { + width: 48px; + height: 48px; + border: 3px solid rgba(255, 255, 255, 0.1); + border-top-color: hsl(270, 73%, 63%); + border-radius: 50%; + animation: spin 1s linear infinite; + } - -
- - + #initial-loader .text { + margin-top: 16px; + color: #666; + font-size: 14px; + } + #initial-loader .cursor { + color: hsl(270, 73%, 63%); + animation: blink 1s infinite; + } + + @keyframes spin { + to { + transform: rotate(360deg); + } + } + + @keyframes blink { + 0%, + 50% { + opacity: 1; + } + 51%, + 100% { + opacity: 0; + } + } + + /* Скрываем loader когда React готов */ + body.loaded #initial-loader { + opacity: 0; + pointer-events: none; + transition: opacity 0.3s ease-out; + } + + + + + +
+
+
+ $ loading_ +
+
+ +
+ + diff --git a/frontend/src/App.tsx b/frontend/src/App.tsx index 74cee14..ca3d92c 100644 --- a/frontend/src/App.tsx +++ b/frontend/src/App.tsx @@ -1,12 +1,18 @@ import "./App.css"; import { BrowserRouter, Routes, Route } from "react-router-dom"; +import { useEffect } from "react"; import Navigation from "./components/Navigation.tsx"; import Footer from "./components/Footer.tsx"; +import AuthCallback from "./components/AuthCallback.tsx"; import Home from "./pages/Home.tsx"; import About from "./components/Skills.tsx"; import Login from "./pages/Login.tsx"; function App() { + useEffect(() => { + document.body.classList.add("loaded"); + }, []); + return (
@@ -23,6 +29,7 @@ function App() { } /> } /> + } />