package main import ( "errors" "net/http" "strings" "github.com/jackc/pgx/v5" ) type clearChatRequest struct { Scope string `json:"scope"` } func (s *Server) handleClearChat(w http.ResponseWriter, r *http.Request) { user, ok := userFromContext(r.Context()) if !ok { writeError(w, http.StatusUnauthorized, "Unauthorized") return } conversationID := strings.TrimSpace(r.PathValue("id")) if !s.canAccessConversation(r.Context(), conversationID, user.ID) { writeError(w, http.StatusForbidden, "Kein Zugriff auf diesen Chat") return } if !s.isConversationMember(r.Context(), conversationID, user.ID) { writeError(w, http.StatusForbidden, "Nur Mitglieder können diesen Chat leeren") return } var input clearChatRequest if err := readJSON(r, &input); err != nil { writeError(w, http.StatusBadRequest, "Ungültige Anfrage") return } scope := strings.TrimSpace(input.Scope) if scope != "me" && scope != "all" { writeError(w, http.StatusBadRequest, "Ungültiger Löschumfang") return } var conversationType, ownerID, teamID string err := s.db.QueryRow( r.Context(), ` SELECT type, COALESCE(created_by::TEXT, ''), COALESCE(team_id::TEXT, '') FROM conversations WHERE id = $1 `, conversationID, ).Scan(&conversationType, &ownerID, &teamID) if errors.Is(err, pgx.ErrNoRows) { writeError(w, http.StatusNotFound, "Chat wurde nicht gefunden") return } if err != nil { writeError(w, http.StatusInternalServerError, "Chat konnte nicht geladen werden") return } if scope == "all" { switch conversationType { case "direct": case "group": if teamID != "" { if !canManageTeamGroup(user) { writeError(w, http.StatusForbidden, "Keine Berechtigung zum Leeren dieses Team-Gruppenchats") return } } else if !canManageGroup(user, ownerID) { writeError(w, http.StatusForbidden, "Nur der Ersteller oder ein Administrator darf die Gruppe für alle leeren") return } default: writeError(w, http.StatusBadRequest, "Dieser Chat kann nicht für alle geleert werden") return } } if scope == "me" { if _, err := s.db.Exec( r.Context(), ` UPDATE conversation_members SET last_cleared_at = now(), last_read_at = now() WHERE conversation_id = $1 AND user_id = $2 `, conversationID, user.ID, ); err != nil { writeError(w, http.StatusInternalServerError, "Chat konnte nicht geleert werden") return } conversation, err := s.getChatConversation(r.Context(), conversationID, user.ID, user.ShowLastSeen) if err != nil { writeError(w, http.StatusInternalServerError, "Chat konnte nicht geladen werden") return } writeJSON(w, http.StatusOK, map[string]any{ "conversation": conversation, }) return } tx, err := s.db.Begin(r.Context()) if err != nil { writeError(w, http.StatusInternalServerError, "Chat konnte nicht geleert werden") return } defer tx.Rollback(r.Context()) if _, err := tx.Exec( r.Context(), ` UPDATE messages SET deleted_at = now() WHERE conversation_id = $1 AND deleted_at IS NULL `, conversationID, ); err != nil { writeError(w, http.StatusInternalServerError, "Chat konnte nicht geleert werden") return } if _, err := tx.Exec( r.Context(), ` UPDATE conversations SET last_message_at = ( SELECT MAX(created_at) FROM messages WHERE conversation_id = $1 AND deleted_at IS NULL AND (expires_at IS NULL OR expires_at > now()) ), updated_at = now() WHERE id = $1 `, conversationID, ); err != nil { writeError(w, http.StatusInternalServerError, "Chat konnte nicht geleert werden") return } if err := tx.Commit(r.Context()); err != nil { writeError(w, http.StatusInternalServerError, "Chat konnte nicht geleert werden") return } s.publishChatMessagesReload(r.Context(), conversationID) s.publishConversationUpdate(r.Context(), conversationID) conversation, err := s.getChatConversation(r.Context(), conversationID, user.ID, user.ShowLastSeen) if err != nil { writeError(w, http.StatusInternalServerError, "Chat konnte nicht geladen werden") return } writeJSON(w, http.StatusOK, map[string]any{ "conversation": conversation, }) }