teg/backend/chat_clear.go
2026-07-03 16:56:20 +02:00

170 lines
4.1 KiB
Go

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,
})
}