Two-tier notification system: new_booking (all public bookings) + pending_booking (notes/today). Priority-sorted queue, unread count polling, enriched responses with user_name/booking_start_time. Fix critical bug: edit_requested cleanup was broken (wrong reason string in 3 handlers). Add 15 new tests covering priority ordering, enrichment, and notification creation flows. Update Admin Manual, Technical Manual, and gap backlog docs.
63 lines
1.6 KiB
Go
63 lines
1.6 KiB
Go
package user
|
|
|
|
import (
|
|
"database/sql"
|
|
"fmt"
|
|
"log"
|
|
"net/http"
|
|
|
|
"crussell/db"
|
|
"crussell/internal/dav"
|
|
"crussell/mw"
|
|
)
|
|
|
|
// DELETE /api/user/account
|
|
func DeleteAccountHandler(w http.ResponseWriter, r *http.Request) {
|
|
userID, ok := mw.GetUserID(r.Context())
|
|
if !ok {
|
|
http.Error(w, "unauthorized", http.StatusUnauthorized)
|
|
return
|
|
}
|
|
|
|
var accountRole string
|
|
err := db.DB.QueryRow(r.Context(), `SELECT account_role FROM users WHERE id = $1`, userID).Scan(&accountRole)
|
|
if err != nil {
|
|
if err == sql.ErrNoRows {
|
|
http.Error(w, "user not found", http.StatusNotFound)
|
|
return
|
|
}
|
|
log.Printf("Failed to fetch user role for deletion: %v", err)
|
|
http.Error(w, "server error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
|
|
if accountRole == "guest" {
|
|
_, err = db.DB.Exec(r.Context(), `SELECT delete_guest_user($1)`, userID)
|
|
if err != nil {
|
|
log.Printf("Failed to delete guest user %s: %v", userID, err)
|
|
http.Error(w, "server error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
} else {
|
|
_, err = db.DB.Exec(r.Context(), `SELECT anonymize_user($1)`, userID)
|
|
if err != nil {
|
|
log.Printf("Failed to anonymize user %s: %v", userID, err)
|
|
http.Error(w, "server error", http.StatusInternalServerError)
|
|
return
|
|
}
|
|
// TODO: Create 'user_anonymized' notification for admin audit trail
|
|
}
|
|
|
|
// Delete CardDAV contact (non-blocking, best-effort)
|
|
if dav.Service != nil {
|
|
go func() {
|
|
uri := fmt.Sprintf("%s.vcf", userID)
|
|
if err := dav.Service.DeleteContact(1, uri); err != nil {
|
|
log.Printf("Warning: Failed to delete CardDAV contact for user %s: %v", userID, err)
|
|
}
|
|
}()
|
|
}
|
|
|
|
w.WriteHeader(http.StatusNoContent)
|
|
}
|