package handlers import ( "fmt" "io" "net/http" "os" "path/filepath" "strings" "time" "github.com/gin-contrib/sessions" "github.com/gin-gonic/gin" "gorm.io/gorm" "go_blog/models" ) // ProfilePage renders the profile edit page. func ProfilePage(db *gorm.DB) gin.HandlerFunc { return func(c *gin.Context) { tr := getTr(c) session := sessions.Default(c) userID := session.Get("user_id") var user models.User if err := db.First(&user, userID).Error; err != nil { c.String(http.StatusInternalServerError, "User not found") return } data := DefaultData(c) data["Title"] = tr["profile_title"] data["Profile"] = user // Flash messages (success / error). if msg := c.Query("saved"); msg == "1" { data["Success"] = tr["profile_saved"] } if msg := c.Query("error"); msg == "pw" { data["Error"] = tr["profile_wrong_password"] } c.HTML(http.StatusOK, "profile", data) } } // UpdateProfile processes the profile edit form (multipart). func UpdateProfile(db *gorm.DB, storagePath string) gin.HandlerFunc { return func(c *gin.Context) { session := sessions.Default(c) userID := session.Get("user_id") var user models.User if err := db.First(&user, userID).Error; err != nil { c.Redirect(http.StatusFound, "/profile") return } // --- Text fields --- if v := c.PostForm("display_name"); v != "" { user.DisplayName = v } if v := c.PostForm("gender"); v != "" { user.Gender = v } if v := c.PostForm("email"); v != "" { user.Email = v } if v := c.PostForm("birthday"); v != "" { if t, err := time.Parse("2006-01-02", v); err == nil { user.Birthday = &t } } // --- Avatar upload --- file, header, err := c.Request.FormFile("avatar") if err == nil { defer file.Close() // Determine file extension. ext := strings.ToLower(filepath.Ext(header.Filename)) if ext == "" || (ext != ".jpg" && ext != ".jpeg" && ext != ".png" && ext != ".gif" && ext != ".webp") { ext = ".jpg" } // Save under storagePath/avatars/. avatarDir := filepath.Join(storagePath, "avatars") if err := os.MkdirAll(avatarDir, 0755); err != nil { c.Redirect(http.StatusFound, "/profile") return } // Use user ID as filename base to avoid duplicates. savedName := fmt.Sprintf("%d%s", user.ID, ext) savedPath := filepath.Join(avatarDir, savedName) dst, err := os.Create(savedPath) if err != nil { c.Redirect(http.StatusFound, "/profile") return } defer dst.Close() if _, err := io.Copy(dst, file); err != nil { c.Redirect(http.StatusFound, "/profile") return } user.Avatar = savedName // Update session display immediately. session.Set("avatar", savedName) } // --- Password change --- currentPass := c.PostForm("current_password") newPass := c.PostForm("new_password") if currentPass != "" && newPass != "" { if !user.CheckPassword(currentPass) { session.Save() c.Redirect(http.StatusFound, "/profile?error=pw") return } if err := user.SetPassword(newPass); err != nil { session.Save() c.Redirect(http.StatusFound, "/profile") return } } // Save user record. if err := db.Save(&user).Error; err != nil { session.Save() c.Redirect(http.StatusFound, "/profile") return } // Update display name in session. session.Set("display_name", user.DisplayName) session.Save() c.Redirect(http.StatusFound, "/profile?saved=1") } }