feat: avatars for humans #273

Merged
talksik merged 11 commits from worktree-refactored-strolling-treasure into main 2026-06-11 22:30:21 +00:00
Showing only changes of commit 6f8349c62f - Show all commits
+12 -6
View File
2
@@ -342,18 +342,17 @@ func (h *Handler) DeleteAvatar(w http.ResponseWriter, r *http.Request) {
return
}
err := h.humanSvc.DeleteAvatar(r.Context(), humanId)
human, err := h.humanSvc.GetByID(r.Context(), humanId)
if err != nil {
flog.Error("failed to delete avatar from human", "error", err)
flog.Error("failed to get human by id", "error", err, "humanId", humanId)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
// best-effort, gracefully continue
human, err := h.humanSvc.GetByID(r.Context(), humanId)
err := h.humanSvc.DeleteAvatar(r.Context(), humanId)
if err != nil {
flog.Error("failed to get human by id", "error", err, "humanId", humanId)
w.WriteHeader(http.StatusNoContent)
flog.Error("failed to delete avatar from human", "error", err)
http.Error(w, "internal server error", http.StatusInternalServerError)
return
}
@@ -401,6 +400,13 @@ func (h *Handler) UpdateAvatar(w http.ResponseWriter, r *http.Request) {
if err != nil {
flog.Error("failed to update human avatar", "error", err, "humanId", humanId)
http.Error(w, "internal server error", http.StatusInternalServerError)
coderabbitai[bot] commented 2026-06-11 22:11:53 +00:00 (Migrated from github.com)
Review

⚠️ Potential issue | 🟡 Minor | Quick win

Return 413 for oversized avatar uploads instead of 500.

When http.MaxBytesReader limit is exceeded, the handler currently falls into a generic 500. This should map to http.StatusRequestEntityTooLarge.

Suggested fix
  object, err := h.depotSvc.CreateFromReader(r.Context(), depot.CreateFromReaderInput{
      Prefix:      "avatars",
      Name:        fmt.Sprintf("%s-avatar", humanId),
      ContentType: r.Header.Get("Content-Type"),
  }, r.Body)
  if err != nil {
+     var maxErr *http.MaxBytesError
+     if errors.As(err, &maxErr) {
+         http.Error(w, "avatar file too large", http.StatusRequestEntityTooLarge)
+         return
+     }
      flog.Error("failed to upload avatar with depo", "error", err, "humanId", humanId)
      http.Error(w, "internal server error", http.StatusInternalServerError)
      return
  }
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

	r.Body = http.MaxBytesReader(w, r.Body, maxBodySize)

	object, err := h.depotSvc.CreateFromReader(r.Context(), depot.CreateFromReaderInput{
		Prefix:      "avatars",
		Name:        fmt.Sprintf("%s-avatar", humanId),
		ContentType: r.Header.Get("Content-Type"),
	}, r.Body)
	if err != nil {
		var maxErr *http.MaxBytesError
		if errors.As(err, &maxErr) {
			http.Error(w, "avatar file too large", http.StatusRequestEntityTooLarge)
			return
		}
		flog.Error("failed to upload avatar with depo", "error", err, "humanId", humanId)
		http.Error(w, "internal server error", http.StatusInternalServerError)
		return
	}
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.

In `@go/internal/handler/handler.go` around lines 381 - 391, The handler wraps the
request body with http.MaxBytesReader but treats any upload-size error from
h.depotSvc.CreateFromReader as a 500; detect the MaxBytesReader overflow and
return http.StatusRequestEntityTooLarge instead. Update the error handling after
calling h.depotSvc.CreateFromReader: if errors.Is(err, http.ErrBodyTooLarge) (or
if that sentinel isn't available, match the "request body too large" error
string) respond with http.Error(w, "request entity too large",
http.StatusRequestEntityTooLarge); otherwise keep the existing flog.Error and
500 behavior. Ensure you import the errors package if needed and reference the
r.Body wrapping and h.depotSvc.CreateFromReader call in your change.

Addressed in commits ffac812 to 6bf2c99

_⚠️ Potential issue_ | _🟡 Minor_ | _⚡ Quick win_ **Return 413 for oversized avatar uploads instead of 500.** When `http.MaxBytesReader` limit is exceeded, the handler currently falls into a generic 500. This should map to `http.StatusRequestEntityTooLarge`. <details> <summary>Suggested fix</summary> ```diff object, err := h.depotSvc.CreateFromReader(r.Context(), depot.CreateFromReaderInput{ Prefix: "avatars", Name: fmt.Sprintf("%s-avatar", humanId), ContentType: r.Header.Get("Content-Type"), }, r.Body) if err != nil { + var maxErr *http.MaxBytesError + if errors.As(err, &maxErr) { + http.Error(w, "avatar file too large", http.StatusRequestEntityTooLarge) + return + } flog.Error("failed to upload avatar with depo", "error", err, "humanId", humanId) http.Error(w, "internal server error", http.StatusInternalServerError) return } ``` </details> <!-- suggestion_start --> <details> <summary>📝 Committable suggestion</summary> > ‼️ **IMPORTANT** > Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements. ```suggestion r.Body = http.MaxBytesReader(w, r.Body, maxBodySize) object, err := h.depotSvc.CreateFromReader(r.Context(), depot.CreateFromReaderInput{ Prefix: "avatars", Name: fmt.Sprintf("%s-avatar", humanId), ContentType: r.Header.Get("Content-Type"), }, r.Body) if err != nil { var maxErr *http.MaxBytesError if errors.As(err, &maxErr) { http.Error(w, "avatar file too large", http.StatusRequestEntityTooLarge) return } flog.Error("failed to upload avatar with depo", "error", err, "humanId", humanId) http.Error(w, "internal server error", http.StatusInternalServerError) return } ``` </details> <!-- suggestion_end --> <details> <summary>🤖 Prompt for AI Agents</summary> ``` Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@go/internal/handler/handler.go` around lines 381 - 391, The handler wraps the request body with http.MaxBytesReader but treats any upload-size error from h.depotSvc.CreateFromReader as a 500; detect the MaxBytesReader overflow and return http.StatusRequestEntityTooLarge instead. Update the error handling after calling h.depotSvc.CreateFromReader: if errors.Is(err, http.ErrBodyTooLarge) (or if that sentinel isn't available, match the "request body too large" error string) respond with http.Error(w, "request entity too large", http.StatusRequestEntityTooLarge); otherwise keep the existing flog.Error and 500 behavior. Ensure you import the errors package if needed and reference the r.Body wrapping and h.depotSvc.CreateFromReader call in your change. ``` </details> <!-- fingerprinting:phantom:poseidon:hawk --> <!-- cr-comment:v1:6fffad183715aaf0f26ca668 --> <!-- This is an auto-generated comment by CodeRabbit --> ✅ Addressed in commits ffac812 to 6bf2c99
// best effort
err = h.depotSvc.Delete(r.Context(), object.ID)
if err != nil {
flog.Error("best-effort delete of object failed", "error", err)
}
return
}