package api import ( "context" "net/http" "github.com/google/uuid" "golang.org/x/crypto/bcrypt" ) func Login(w http.ResponseWriter, r *http.Request) { err := r.ParseMultipartForm(64 << 10) if err != nil { http.Error(w, "Unable to parse form", http.StatusBadRequest) return } username := r.FormValue("name") password := r.FormValue("password") if username == "" || password == "" { http.Error(w, "Username and password cannot be empty", http.StatusBadRequest) return } user, err := dbGetUserByName(username) if err != nil { http.Error(w, "Invalid username or password", http.StatusUnauthorized) return } err = validatePassword(user.Password, password) if err != nil { http.Error(w, "Invalid username or password", http.StatusUnauthorized) return } sessionToken := CreateSession(username) http.SetCookie(w, &http.Cookie{ Name: "session_token", Value: sessionToken, Path: "/", HttpOnly: true, Secure: false, }) w.Write([]byte("Login successful")) } var sessionStore = make(map[string]string) func CreateSession(username string) string { sessionToken := uuid.New().String() sessionStore[sessionToken] = username return sessionToken } func ValidateSession(sessionToken string) (string, bool) { username, exists := sessionStore[sessionToken] return username, exists } type contextKey string const usernameKey contextKey = "username" func SessionAuthMiddleware(next http.Handler) http.Handler { return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { cookie, err := r.Cookie("session_token") if err != nil { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } sessionToken := cookie.Value username, valid := ValidateSession(sessionToken) if !valid { http.Error(w, "Unauthorized", http.StatusUnauthorized) return } // Add username to request context ctx := context.WithValue(r.Context(), usernameKey, username) next.ServeHTTP(w, r.WithContext(ctx)) }) } func (u *UserPayload) Render(w http.ResponseWriter, r *http.Request) error { return nil } func hashPassword(password string) (string, error) { hashedPassword, err := bcrypt.GenerateFromPassword([]byte(password), bcrypt.DefaultCost) return string(hashedPassword), err } func validatePassword(hashedPassword, password string) error { return bcrypt.CompareHashAndPassword([]byte(hashedPassword), []byte(password)) }