package handlers import ( "crypto/sha256" "fmt" "io" "log" "net/http" "os" "path/filepath" "threadr/models" "github.com/gorilla/sessions" ) func ProfileEditHandler(app *App) http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { session := r.Context().Value("session").(*sessions.Session) userID, ok := session.Values["user_id"].(int) if !ok { http.Redirect(w, r, app.Config.ThreadrDir+"/login/", http.StatusFound) return } if r.Method == http.MethodPost { // Handle file upload file, handler, err := r.FormFile("pfp") if err == nil { defer file.Close() // Create a hash of the file h := sha256.New() if _, err := io.Copy(h, file); err != nil { log.Printf("Error hashing file: %v", err) http.Error(w, "Failed to process file", http.StatusInternalServerError) return } fileHash := fmt.Sprintf("%x", h.Sum(nil)) // Create file record in the database fileRecord := models.File{ OriginalName: handler.Filename, Hash: fileHash, HashAlgorithm: "sha256", } fileID, err := models.CreateFile(app.DB, fileRecord) if err != nil { log.Printf("Error creating file record: %v", err) http.Error(w, "Failed to save file information", http.StatusInternalServerError) return } // Save the file to disk fileExt := filepath.Ext(handler.Filename) newFileName := fmt.Sprintf("%d%s", fileID, fileExt) filePath := filepath.Join(app.Config.FileStorageDir, newFileName) // Reset file pointer file.Seek(0, 0) dst, err := os.Create(filePath) if err != nil { log.Printf("Error creating file on disk: %v", err) http.Error(w, "Failed to save file", http.StatusInternalServerError) return } defer dst.Close() if _, err := io.Copy(dst, file); err != nil { log.Printf("Error saving file to disk: %v", err) http.Error(w, "Failed to save file", http.StatusInternalServerError) return } // Update user's pfp_file_id err = models.UpdateUserPfp(app.DB, userID, fileID) if err != nil { log.Printf("Error updating user pfp: %v", err) http.Error(w, "Failed to update profile", http.StatusInternalServerError) return } } // Update other profile fields displayName := r.FormValue("display_name") bio := r.FormValue("bio") err = models.UpdateUserProfile(app.DB, userID, displayName, bio) if err != nil { log.Printf("Error updating profile: %v", err) http.Error(w, "Failed to update profile", http.StatusInternalServerError) return } http.Redirect(w, r, app.Config.ThreadrDir+"/profile/", http.StatusFound) return } user, err := models.GetUserByID(app.DB, userID) if err != nil { log.Printf("Error fetching user: %v", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } if user == nil { http.Error(w, "User not found", http.StatusNotFound) return } data := struct { PageData User models.User }{ PageData: PageData{ Title: "ThreadR - Edit Profile", Navbar: "profile", LoggedIn: true, ShowCookieBanner: false, BasePath: app.Config.ThreadrDir, StaticPath: app.Config.ThreadrDir + "/static", CurrentURL: r.URL.Path, }, User: *user, } if err := app.Tmpl.ExecuteTemplate(w, "profile_edit", data); err != nil { log.Printf("Error executing template in ProfileEditHandler: %v", err) http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } } }